diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml
index c37a0646dee..db453f4cd3b 100644
--- a/Mage.Client/pom.xml
+++ b/Mage.Client/pom.xml
@@ -147,14 +147,9 @@
https://stackoverflow.com/questions/714243/sax2-driver-class-org-apache-crimson-parser-xmlreaderimpl-not-found-when-using
-->
- batik
- batik-transcoder
- 1.6-1
-
-
- crimson
- crimson
- 1.1.3
+ org.apache.xmlgraphics
+ batik-transcoder
+ 1.7
diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.form b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.form
index e9b349e1117..17513f7a0da 100644
--- a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.form
+++ b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.form
@@ -645,6 +645,8 @@
+
+
@@ -659,6 +661,7 @@
+
@@ -846,6 +849,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java
index d23a4098246..f6fc566cef3 100644
--- a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java
+++ b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java
@@ -232,7 +232,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
FilterCard filter = new FilterCard();
String name = jTextFieldSearch.getText().trim();
- filter.add(new CardTextPredicate(name, chkNames.isSelected(), chkTypes.isSelected(), chkRules.isSelected()));
+ filter.add(new CardTextPredicate(name, chkNames.isSelected(), chkTypes.isSelected(), chkRules.isSelected(), chkUnique.isSelected()));
if (limited) {
ArrayList> predicates = new ArrayList<>();
@@ -543,6 +543,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
chkNames = new javax.swing.JCheckBox();
chkTypes = new javax.swing.JCheckBox();
chkRules = new javax.swing.JCheckBox();
+ chkUnique = new javax.swing.JCheckBox();
jButtonSearch = new javax.swing.JButton();
jButtonClean = new javax.swing.JButton();
cardCountLabel = new javax.swing.JLabel();
@@ -1062,6 +1063,22 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
chkRulesActionPerformed(evt);
}
});
+
+ chkUnique.setSelected(true);
+ chkUnique.setText("Unique");
+ chkUnique.setToolTipText("Singleton results only.");
+ chkUnique.setFocusable(false);
+ chkUnique.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
+ chkUnique.setMaximumSize(new java.awt.Dimension(69, 16));
+ chkUnique.setMinimumSize(new java.awt.Dimension(69, 16));
+ chkUnique.setPreferredSize(new java.awt.Dimension(69, 16));
+ chkUnique.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
+ chkUnique.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ chkUniqueActionPerformed(evt);
+ }
+ });
+
jButtonSearch.setText("Search");
jButtonSearch.setToolTipText("Performs the search.");
@@ -1109,6 +1126,8 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
.addComponent(chkTypes, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chkRules, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(chkUnique, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(5, 5, 5)
.addComponent(cardCountLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@@ -1122,6 +1141,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
.addGroup(cardSelectorBottomPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(chkTypes, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkRules, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(chkUnique, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkNames, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(cardSelectorBottomPanelLayout.createSequentialGroup()
.addGroup(cardSelectorBottomPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -1341,6 +1361,10 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
// TODO add your handling code here:
}//GEN-LAST:event_chkRulesActionPerformed
+ private void chkUniqueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkRulesActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_chkRulesActionPerformed
+
private void btnExpansionSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExpansionSearchActionPerformed
FastSearchUtil.showFastSearchForStringComboBox(cbExpansionSet, "Select set or expansion");
}//GEN-LAST:event_btnExpansionSearchActionPerformed
@@ -1418,6 +1442,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
private javax.swing.JCheckBox chkPennyDreadful;
private javax.swing.JCheckBox chkPiles;
private javax.swing.JCheckBox chkRules;
+ private javax.swing.JCheckBox chkUnique;
private javax.swing.JCheckBox chkTypes;
private javax.swing.JButton jButtonAddToMain;
private javax.swing.JButton jButtonAddToSideboard;
diff --git a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java
index 5992f5a424c..de2eb915056 100644
--- a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java
@@ -64,7 +64,6 @@ public class FeedbackPanel extends javax.swing.JPanel {
private static final Logger LOGGER = Logger.getLogger(FeedbackPanel.class);
public enum FeedbackMode {
-
INFORM, QUESTION, CONFIRM, CANCEL, SELECT, END
}
diff --git a/Mage.Client/src/main/java/mage/client/game/HelperPanel.java b/Mage.Client/src/main/java/mage/client/game/HelperPanel.java
index 04ccc0db76a..1bd86d7a3da 100644
--- a/Mage.Client/src/main/java/mage/client/game/HelperPanel.java
+++ b/Mage.Client/src/main/java/mage/client/game/HelperPanel.java
@@ -394,7 +394,7 @@ public class HelperPanel extends JPanel {
}
} else {
// inform about other players
- this.setOpaque(false);
+ this.mainPanel.setOpaque(false);
}
if (buttons.size() == 0) {
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java
index 950069c3fbe..498778c2b3f 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java
@@ -302,7 +302,7 @@ public class CardPanelRenderImpl extends CardPanel {
= new CardPanelAttributes(cardWidth, cardHeight, isChoosable(), isSelected());
// Draw card itself
- cardRenderer.draw(g2d, attribs);
+ cardRenderer.draw(g2d, attribs, image);
// Done
g2d.dispose();
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java
index 35ec4fc2140..d32fa0cdd07 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java
@@ -17,10 +17,10 @@ import mage.view.PermanentView;
import java.awt.*;
import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
import java.awt.image.RasterFormatException;
import java.util.ArrayList;
import java.util.List;
+import java.awt.image.BufferedImage;
/**
* @author stravant@gmail.com
@@ -201,7 +201,8 @@ public abstract class CardRenderer {
// The Draw Method
// The draw method takes the information caculated by the constructor
// and uses it to draw to a concrete size of card and graphics.
- public void draw(Graphics2D g, CardPanelAttributes attribs) {
+ public void draw(Graphics2D g, CardPanelAttributes attribs, BufferedImage image) {
+
// Pre template method layout, to calculate shared layout info
layout(attribs.cardWidth, attribs.cardHeight);
isSelected = attribs.isSelected;
@@ -211,7 +212,7 @@ public abstract class CardRenderer {
drawBorder(g);
drawBackground(g);
drawArt(g);
- drawFrame(g);
+ drawFrame(g, image);
if (!cardView.isAbility()) {
drawOverlays(g);
drawCounters(g);
@@ -226,7 +227,7 @@ public abstract class CardRenderer {
protected abstract void drawArt(Graphics2D g);
- protected abstract void drawFrame(Graphics2D g);
+ protected abstract void drawFrame(Graphics2D g, BufferedImage image);
// Template methods that are possible to override, but unlikely to be
// overridden.
@@ -462,22 +463,44 @@ public abstract class CardRenderer {
}
} else {
StringBuilder sbType = new StringBuilder();
- for (SuperType superType : cardView.getSuperTypes()) {
- sbType.append(superType).append(' ');
- }
- for (CardType cardType : cardView.getCardTypes()) {
- sbType.append(cardType.toString()).append(' ');
- }
- if (!cardView.getSubTypes().isEmpty()) {
- sbType.append("- ");
- for (SubType subType : cardView.getSubTypes()) {
- sbType.append(subType).append(' ');
+ String spType = getCardSuperTypeLine();
+ String subType = getCardSubTypeLine();
+ if (spType.equalsIgnoreCase("")) {
+ sbType.append(subType);
+ } else {
+ sbType.append(spType);
+ if (!subType.equalsIgnoreCase("")) {
+ sbType.append("- ");
+ sbType.append(subType);
}
}
+
return sbType.toString();
}
}
+ protected String getCardSuperTypeLine() {
+ StringBuilder spType = new StringBuilder();
+ for (SuperType superType : cardView.getSuperTypes()) {
+ spType.append(superType).append(' ');
+ }
+ for (CardType cardType : cardView.getCardTypes()) {
+ spType.append(cardType.toString()).append(' ');
+ }
+ return spType.toString();
+ }
+
+ protected String getCardSubTypeLine() {
+ StringBuilder subType = new StringBuilder();
+
+ if (!cardView.getSubTypes().isEmpty()) {
+ for (SubType sType : cardView.getSubTypes()) {
+ subType.append(sType).append(' ');
+ }
+ }
+ return subType.toString();
+ }
+
// Set the card art image (CardPanel will give it to us when it
// is loaded and ready)
public void setArtImage(Image image) {
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java
index eca040234fb..3702f176cb2 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java
@@ -51,8 +51,8 @@ public final class CardRendererUtils {
// Return the buffered image
return bimage;
}
-
- private static Color abitbrighter(Color c) {
+
+ public static Color abitbrighter(Color c) {
int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();
@@ -68,7 +68,7 @@ public final class CardRendererUtils {
alpha);
}
- private static Color abitdarker(Color c) {
+ public static Color abitdarker(Color c) {
int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();
@@ -108,6 +108,35 @@ public final class CardRendererUtils {
g.drawLine(x + 1 + bevel, y + h - 2, x + 1 + bevel + w - 2 * bevel - 2, y + h - 2);
}
+ public static void drawZendikarLandBox(Graphics2D g, int x, int y, int w, int h, int bevel, Paint border, Paint fill) {
+ g.setColor(new Color(0, 0, 0, 150));
+
+ g.drawOval(x - 1, y, bevel * 2, h);
+ g.setPaint(border);
+ g.drawOval(x, y, bevel * 2 - 1, h - 1);
+ g.drawOval(x + w - bevel * 2, y, bevel * 2 - 1, h - 1);
+ g.drawOval(x + 1, y + 1, bevel * 2 - 3, h - 3);
+ g.drawOval(x + 1 + w - bevel * 2, y + 1, bevel * 2 - 3, h - 3);
+
+ // The big circle in the middle.. (diameter=2+1/4 of height) - 3/4 above line, 1/2 below 0.75 + .5 + 1= 2.25 = 9/4
+ g.drawOval(x + w / 2 - h - h / 8, y - 3 * h / 4, 9 * h / 4, 9 * h / 4);
+
+ g.drawRect(x + bevel, y, w - 2 * bevel, h - 1);
+ g.drawRect(x + 1 + bevel, y + 1, w - 2 * bevel - 2, h - 3);
+ g.setPaint(fill);
+ g.setColor(abitbrighter(g.getColor()));
+ g.drawLine(x + 1 + bevel, y + 1, x + 1 + bevel + w - 2 * bevel - 2, y + 1);
+ g.setPaint(fill);
+ g.setColor(abitdarker(g.getColor()));
+ g.drawLine(x + 1 + bevel, y + h - 2, x + 1 + bevel + w - 2 * bevel - 2, y + h - 2);
+
+ g.fillOval(x + 2, y + 2, bevel * 2 - 4, h - 4);
+ g.fillOval(x + 2 + w - bevel * 2, y + 2, bevel * 2 - 4, h - 4);
+ g.fillRect(x + bevel, y + 2, w - 2 * bevel, h - 4);
+
+ g.fillOval(x + w / 2 - h - h / 8, y - 3 * h / 4, 9 * h / 4, 9 * h / 4);
+ }
+
// Get the width of a mana cost rendered with ManaSymbols.draw
public static int getManaCostWidth(String manaCost, int symbolSize) {
int width = 0;
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java
index a75c12fe634..67e5192061d 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernCardRenderer.java
@@ -7,7 +7,11 @@ package org.mage.card.arcane;
import java.awt.*;
import java.awt.font.*;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Area;
+import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
@@ -68,6 +72,13 @@ public class ModernCardRenderer extends CardRenderer {
BufferedImage img = CardRendererUtils.toBufferedImage(icon.getImage());
return new TexturePaint(img, new Rectangle(0, 0, img.getWidth(), img.getHeight()));
}
+
+ private static BufferedImage loadBackgroundImage(String name) {
+ URL url = ModernCardRenderer.class.getResource("/cardrender/background_texture_" + name + ".png");
+ ImageIcon icon = new ImageIcon(url);
+ BufferedImage img = CardRendererUtils.toBufferedImage(icon.getImage());
+ return img;
+ }
private static BufferedImage loadFramePart(String name) {
URL url = ModernCardRenderer.class.getResource("/cardrender/" + name + ".png");
@@ -97,7 +108,18 @@ public class ModernCardRenderer extends CardRenderer {
public static final Paint BG_TEXTURE_ARTIFACT = loadBackgroundTexture("artifact");
public static final Paint BG_TEXTURE_LAND = loadBackgroundTexture("land");
public static final Paint BG_TEXTURE_VEHICLE = loadBackgroundTexture("vehicle");
-
+
+ public static final BufferedImage BG_IMG_WHITE = loadBackgroundImage("white");
+ public static final BufferedImage BG_IMG_BLUE = loadBackgroundImage("blue");
+ public static final BufferedImage BG_IMG_BLACK = loadBackgroundImage("black");
+ public static final BufferedImage BG_IMG_RED = loadBackgroundImage("red");
+ public static final BufferedImage BG_IMG_GREEN = loadBackgroundImage("green");
+ public static final BufferedImage BG_IMG_GOLD = loadBackgroundImage("gold");
+ public static final BufferedImage BG_IMG_ARTIFACT = loadBackgroundImage("artifact");
+ public static final BufferedImage BG_IMG_LAND = loadBackgroundImage("land");
+ public static final BufferedImage BG_IMG_VEHICLE = loadBackgroundImage("vehicle");
+ public static final BufferedImage BG_IMG_COLORLESS = loadBackgroundImage("colorless");
+
public static final BufferedImage FRAME_INVENTION = loadFramePart("invention_frame");
public static final Color BORDER_WHITE = new Color(216, 203, 188);
@@ -279,27 +301,30 @@ public class ModernCardRenderer extends CardRenderer {
// Just draw a brown rectangle
drawCardBack(g);
} else {
- BufferedImage bufferedImage = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
-
- // Set texture to paint with
- g.setPaint(getBackgroundPaint(cardView.getColor(), cardView.getCardTypes(), cardView.getSubTypes()));
+ BufferedImage bg = getBackgroundImage(cardView.getColor(), cardView.getCardTypes(), cardView.getSubTypes());
+ if (bg == null) {
+ return;
+ }
+ int bgw = bg.getWidth();
+ int bgh = bg.getHeight();
// Draw main part (most of card)
- g.fillRoundRect(
- borderWidth, borderWidth,
+ RoundRectangle2D rr = new RoundRectangle2D.Double(borderWidth, borderWidth,
cardWidth - borderWidth * 2, cardHeight - borderWidth * 4 - cornerRadius * 2,
cornerRadius - 1, cornerRadius - 1);
+ Area a = new Area(rr);
- // Draw the M15 rounded "swoosh" at the bottom
- g.fillRoundRect(
- borderWidth, cardHeight - borderWidth * 4 - cornerRadius * 4,
+ RoundRectangle2D rr2 = new RoundRectangle2D.Double(borderWidth, cardHeight - borderWidth * 4 - cornerRadius * 4,
cardWidth - borderWidth * 2, cornerRadius * 4,
cornerRadius * 2, cornerRadius * 2);
-
- // Draw the cutout into the "swoosh" for the textbox to lie over
- g.fillRect(
- borderWidth + contentInset, cardHeight - borderWidth * 5,
- cardWidth - borderWidth * 2 - contentInset * 2, borderWidth * 2);
+ a.add(new Area(rr2));
+
+ // Draw the M15 rounded "swoosh" at the bottom
+ Rectangle r = new Rectangle(borderWidth + contentInset, cardHeight - borderWidth * 5, cardWidth - borderWidth * 2 - contentInset * 2, borderWidth * 2);
+ a.add(new Area(r));
+ g.setClip(a);
+ g.drawImage(bg, 0, 0, cardWidth, cardHeight, 0, 0, bgw, bgh, BOX_BLUE, null);
+ g.setClip(null);
}
}
@@ -312,6 +337,8 @@ public class ModernCardRenderer extends CardRenderer {
Rectangle2D rect;
if (useInventionFrame()) {
rect = new Rectangle2D.Float(0, 0, 1, 1);
+ } else if (isZendikarFullArtLand()) {
+ rect = new Rectangle2D.Float(.079f, .11f, .84f, .84f);
} else if (cardView.getFrameStyle().isFullArt() || (cardView.isToken())) {
rect = new Rectangle2D.Float(.079f, .11f, .84f, .63f);
} else {
@@ -330,6 +357,10 @@ public class ModernCardRenderer extends CardRenderer {
}
}
+ private boolean isZendikarFullArtLand() {
+ return cardView.getFrameStyle() == FrameStyle.BFZ_FULL_ART_BASIC || cardView.getFrameStyle() == FrameStyle.ZEN_FULL_ART_BASIC;
+ }
+
protected boolean isSourceArtFullArt() {
int color = artImage.getRGB(0, artImage.getHeight() / 2);
return (((color & 0x00FF0000) > 0x00200000)
@@ -352,7 +383,7 @@ public class ModernCardRenderer extends CardRenderer {
if (artImage != null && !cardView.isFaceDown()) {
boolean useFaceArt = false;
- if (faceArtImage != null) {
+ if (faceArtImage != null && !isZendikarFullArtLand()) {
useFaceArt = true;
}
@@ -395,7 +426,7 @@ public class ModernCardRenderer extends CardRenderer {
totalContentInset + 1, totalContentInset + boxHeight,
contentWidth - 2, typeLineY - totalContentInset - boxHeight,
sourceRect, shouldPreserveAspect);
- } else {
+ } else if (!isZendikarFullArtLand()) {
drawArtIntoRect(g,
totalContentInset + 1, totalContentInset + boxHeight,
contentWidth - 2, typeLineY - totalContentInset - boxHeight,
@@ -405,7 +436,7 @@ public class ModernCardRenderer extends CardRenderer {
}
@Override
- protected void drawFrame(Graphics2D g) {
+ protected void drawFrame(Graphics2D g, BufferedImage image) {
// Get the card colors to base the frame on
ObjectColor frameColors = getFrameObjectColor();
@@ -421,12 +452,13 @@ public class ModernCardRenderer extends CardRenderer {
// Draw the main card content border
g.setPaint(borderPaint);
+
if (cardView.getFrameStyle() == FrameStyle.KLD_INVENTION) {
g.drawImage(FRAME_INVENTION, 0, 0, cardWidth, cardHeight, null);
g.drawRect(
totalContentInset, typeLineY,
contentWidth - 1, cardHeight - borderWidth * 3 - typeLineY - 1);
- } else {
+ } else if (!isZendikarFullArtLand()) {
g.drawRect(
totalContentInset, totalContentInset,
contentWidth - 1, cardHeight - borderWidth * 3 - totalContentInset - 1);
@@ -437,11 +469,13 @@ public class ModernCardRenderer extends CardRenderer {
g.setPaint(new Color(255, 255, 255, 150));
} else {
g.setPaint(textboxPaint);
-
}
- g.fillRect(
- totalContentInset + 1, typeLineY,
- contentWidth - 2, cardHeight - borderWidth * 3 - typeLineY - 1);
+
+ if (!isZendikarFullArtLand()) {
+ g.fillRect(
+ totalContentInset + 1, typeLineY,
+ contentWidth - 2, cardHeight - borderWidth * 3 - typeLineY - 1);
+ }
// If it's a planeswalker, extend the textbox left border by some
if (cardView.isPlanesWalker()) {
@@ -451,7 +485,7 @@ public class ModernCardRenderer extends CardRenderer {
cardWidth / 16, cardHeight - typeLineY - boxHeight - borderWidth * 3);
}
- if (cardView.getFrameStyle() != FrameStyle.KLD_INVENTION) {
+ if (cardView.getFrameStyle() != FrameStyle.KLD_INVENTION && !isZendikarFullArtLand()) {
// Draw a shadow highlight at the right edge of the content frame
g.setColor(new Color(0, 0, 0, 100));
g.fillRect(
@@ -470,26 +504,31 @@ public class ModernCardRenderer extends CardRenderer {
cardWidth - 2 * borderWidth, boxHeight,
contentInset,
borderPaint, boxColor);
-
// Draw the type line box
- CardRendererUtils.drawRoundedBox(g,
- borderWidth, typeLineY,
- cardWidth - 2 * borderWidth, boxHeight,
- contentInset,
- borderPaint, boxColor);
+ if (!isZendikarFullArtLand()) {
+ CardRendererUtils.drawRoundedBox(g,
+ borderWidth, typeLineY,
+ cardWidth - 2 * borderWidth, boxHeight,
+ contentInset,
+ borderPaint, boxColor);
- // Draw a small separator between the type line and box, and shadow
- // at the left of the texbox, and above the name line
- g.setColor(new Color(0, 0, 0, 150));
- g.fillRect(
- totalContentInset - 1, totalContentInset - 1,
- contentWidth + 1, 1);
- g.fillRect(
- totalContentInset + 1, typeLineY + boxHeight,
- contentWidth - 2, 1);
- g.fillRect(
- cardWidth - totalContentInset - 1, typeLineY + boxHeight,
- 1, cardHeight - borderWidth * 3 - typeLineY - boxHeight);
+ // Draw a small separator between the type line and box, and shadow
+ // at the left of the texbox, and above the name line
+ g.setColor(new Color(0, 0, 0, 150));
+ g.fillRect(
+ totalContentInset - 1, totalContentInset - 1,
+ contentWidth + 1, 1);
+ g.fillRect(
+ totalContentInset + 1, typeLineY + boxHeight,
+ contentWidth - 2, 1);
+ g.fillRect(
+ cardWidth - totalContentInset - 1, typeLineY + boxHeight,
+ 1, cardHeight - borderWidth * 3 - typeLineY - boxHeight);
+ // Draw the type line
+ drawTypeLine(g, getCardTypeLine(),
+ totalContentInset, typeLineY,
+ contentWidth, boxHeight, true);
+ }
// Draw the transform circle
int nameOffset = drawTransformationCircle(g, borderPaint);
@@ -502,20 +541,163 @@ public class ModernCardRenderer extends CardRenderer {
totalContentInset + nameOffset, totalContentInset,
contentWidth - nameOffset, boxHeight);
- // Draw the type line
- drawTypeLine(g, getCardTypeLine(),
- totalContentInset, typeLineY,
- contentWidth, boxHeight);
-
// Draw the textbox rules
- drawRulesText(g, textboxKeywords, textboxRules,
- totalContentInset + 2, typeLineY + boxHeight + 2,
- contentWidth - 4, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3);
+ if (!isZendikarFullArtLand()) {
+ drawRulesText(g, textboxKeywords, textboxRules,
+ totalContentInset + 2, typeLineY + boxHeight + 2,
+ contentWidth - 4, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3);
+ } else {
+ int x = totalContentInset;
+ int y = typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset;
+ int w = contentWidth;
+ int h = boxHeight - 4;
+
+ CardRendererUtils.drawZendikarLandBox(g,
+ x, y, w, h,
+ contentInset,
+ borderPaint, boxColor);
+ drawTypeLine(g, getCardSuperTypeLine(),
+ totalContentInset + contentInset, typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset,
+ contentWidth / 2 - boxHeight, boxHeight - 4, false);
+ drawTypeLine(g, getCardSubTypeLine(),
+ totalContentInset + 4 * contentWidth / 7 + boxHeight, typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset,
+ 3 * contentWidth / 7 - boxHeight - contentInset, boxHeight - 4, true);
+
+ if (cardView.getFrameStyle() == FrameStyle.ZEN_FULL_ART_BASIC) {
+ // Draw curved lines (old Zendikar land style) - bigger (around 6%) inset on curve on bottom than inset (around 4.5%) on top...
+ int x2 = x + contentWidth;
+ int y2 = y;
+ int thisy = totalContentInset + boxHeight;
+ drawZendikarCurvedFace(g, image, x, thisy, x2, y2,
+ boxColor, borderPaint);
+ } else if (cardView.getFrameStyle() == FrameStyle.BFZ_FULL_ART_BASIC) {
+ // Draw curved lines (BFZ land style)
+ int y2 = y;
+ int yb = totalContentInset + boxHeight;
+ int topxdelta = 45 * contentWidth / 1000;
+ int endydelta = 60 * (totalContentInset + y2) / 265;
+ int x2 = x + contentWidth;
+
+ // Curve ends at 60 out of 265
+ drawBFZCurvedFace(g, image, x, yb, x2, y2,
+ topxdelta, endydelta,
+ boxColor, borderPaint);
+ }
+
+ drawRulesText(g, textboxKeywords, textboxRules,
+ x, y,
+ w, h);
+ }
// Draw the bottom right stuff
drawBottomRight(g, borderPaint, boxColor);
}
+ public void drawZendikarCurvedFace(Graphics2D g2, BufferedImage image, int x, int y, int x2, int y2,
+ Color boxColor, Paint paint) {
+
+ BufferedImage artToUse = faceArtImage;
+ boolean hadToUseFullArt = false;
+ if (faceArtImage == null) {
+ if (artImage == null) {
+ return;
+ }
+ hadToUseFullArt = true;
+ artToUse = artImage;
+ }
+ int srcW = artToUse.getWidth();
+ int srcH = artToUse.getHeight();
+
+ if (hadToUseFullArt) {
+ // Get a box based on the standard scan from gatherer.
+ // Width = 185/223 pixels (centered)
+ // Height = 220/310, 38 pixels from top
+ int subx = 19 * srcW / 223;
+ int suby = 38 * srcH / 310;
+ artToUse = artImage.getSubimage(subx, suby, 185 * srcW / 223, 220 * srcH / 310);
+ }
+
+ Path2D.Double curve = new Path2D.Double();
+
+ int ew = x2 - x;
+ int eh = 700 * (y2 - y) / 335;
+ Arc2D arc = new Arc2D.Double(x, y - 197 * eh / 700, ew, eh, 0, 360, Arc2D.OPEN);
+ Arc2D innerarc = new Arc2D.Double(x + 1, y - 197 * eh / 700 + 1, ew - 2, eh - 2, 0, 360, Arc2D.OPEN);
+
+ curve.append(new Rectangle2D.Double(x, y, x2 - x, y2 - y), false);
+ g2.setClip(new Rectangle2D.Double(x, y, x2 - x, y2 - y));
+ g2.setClip(arc);
+
+ Rectangle2D r = curve.getBounds2D();
+ g2.drawImage(artToUse, x, y, x2 - x, y2 - y, null);
+ g2.setClip(null);
+ g2.setClip(new Rectangle2D.Double(x, y, x2 - x, y2 - y));
+
+ g2.setColor(CardRendererUtils.abitdarker(boxColor));
+ g2.draw(arc);
+ g2.setColor(Color.black);
+ g2.draw(innerarc);
+
+ g2.setClip(null);
+ }
+
+ public void drawBFZCurvedFace(Graphics2D g2, BufferedImage image, int x, int y, int x2, int y2,
+ int topxdelta, int endydelta,
+ Color boxColor, Paint paint) {
+ BufferedImage artToUse = faceArtImage;
+ boolean hadToUseFullArt = false;
+ if (faceArtImage == null) {
+ if (artImage == null) {
+ return;
+ }
+ hadToUseFullArt = true;
+ artToUse = artImage;
+ }
+ int srcW = artToUse.getWidth();
+ int srcH = artToUse.getHeight();
+
+ if (hadToUseFullArt) {
+ // Get a box based on the standard scan from gatherer.
+ // Width = 185/223 pixels (centered)
+ // Height = 220/310, 38 pixels from top
+ int subx = 19 * srcW / 223;
+ int suby = 38 * srcH / 310;
+ artToUse = artImage.getSubimage(subx, suby, 185 * srcW / 223, 220 * srcH / 310);
+ }
+
+ Path2D.Double curve = new Path2D.Double();
+ curve.moveTo(x + topxdelta, y);
+ curve.quadTo(x, y + endydelta / 2, x, y + endydelta);
+ curve.lineTo(x, y2);
+ curve.lineTo(x2, y2);
+ curve.lineTo(x2, y + endydelta);
+ curve.quadTo(x2, y + endydelta / 2, x2 - topxdelta, y);
+ curve.lineTo(x + topxdelta, y);
+
+ Path2D.Double innercurve = new Path2D.Double();
+ innercurve.moveTo(x + topxdelta, y + 1);
+ innercurve.quadTo(x + 1, y + endydelta / 2, x + 1, y + endydelta);
+ innercurve.lineTo(x + 1, y2 - 1);
+ innercurve.lineTo(x2 - 1, y2 - 1);
+ innercurve.lineTo(x2 - 1, y + endydelta);
+ innercurve.quadTo(x2 - 1, y + endydelta / 2, x2 - topxdelta, y + 1);
+ innercurve.lineTo(x + topxdelta, y + 1);
+
+ Rectangle2D r = curve.getBounds2D();
+ int minX = (int) r.getX();
+
+ g2.setClip(curve);
+ g2.drawImage(artToUse, minX, y, (x2 - x) + (x - minX) * 2, y2 - y, null);
+
+ g2.setClip(null);
+ g2.setColor(CardRendererUtils.abitdarker(boxColor));
+ g2.setPaint(paint);
+ g2.draw(curve);
+
+ g2.setColor(Color.black);
+ g2.draw(innercurve);
+ }
+
// Draw the name line
protected void drawNameLine(Graphics2D g, String baseName, String manaCost, int x, int y, int w, int h) {
// Width of the mana symbols
@@ -566,13 +748,13 @@ public class ModernCardRenderer extends CardRenderer {
}
// Draw the type line (color indicator, types, and expansion symbol)
- protected void drawTypeLine(Graphics2D g, String baseTypeLine, int x, int y, int w, int h) {
+ protected void drawTypeLine(Graphics2D g, String baseTypeLine, int x, int y, int w, int h, boolean withSymbol) {
// Draw expansion symbol
- int expansionSymbolWidth;
+ int expansionSymbolWidth = 0;
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_SET_SYMBOL, "false").equals("false")) {
if (cardView.isAbility()) {
expansionSymbolWidth = 0;
- } else {
+ } else if (withSymbol) {
expansionSymbolWidth = drawExpansionSymbol(g, x, y, w, h);
}
} else {
@@ -792,9 +974,21 @@ public class ModernCardRenderer extends CardRenderer {
}
// Basic mana draw mana symbol in textbox (for basic lands)
- if (allRules.size() == 1 && (allRules.get(0) instanceof TextboxBasicManaRule) && cardView.isLand()) {
- drawBasicManaTextbox(g, x, y, w, h, ((TextboxBasicManaRule) allRules.get(0)).getBasicManaSymbol());
- return;
+ if (allRules.size() == 1 && (allRules.get(0) instanceof TextboxBasicManaRule) && cardView.isLand() || isZendikarFullArtLand()) {
+ if (!isZendikarFullArtLand()) {
+ drawBasicManaTextbox(g, x, y, w, h, ((TextboxBasicManaRule) allRules.get(0)).getBasicManaSymbol());
+ return;
+ } else // Big circle in the middle for Zendikar lands
+ if (allRules.size() == 1) {
+ // Size of mana symbol = 9/4 * h, 3/4h above line
+ drawBasicManaSymbol(g, x + w / 2 - 9 * h / 8 + 1, y - 3 * h / 4, 9 * h / 4, 9 * h / 4, ((TextboxBasicManaRule) allRules.get(0)).getBasicManaSymbol());
+ return;
+ } else {
+ if (allRules.size() > 1) {
+ drawBasicManaSymbol(g, x + w / 2 - h - h / 8, y - 3 * h / 4, 9 * h / 4, 9 * h / 4, cardView.getFrameColor().toString());
+ }
+ return;
+ }
}
// Go through possible font sizes in descending order to find the best fit
@@ -847,6 +1041,11 @@ public class ModernCardRenderer extends CardRenderer {
ManaSymbols.draw(g, symbs, x + (w - manaCostWidth) / 2, y + (h - symbHeight) / 2, symbHeight, Color.black, 2);
}
+ private void drawBasicManaSymbol(Graphics2D g, int x, int y, int w, int h, String symbol) {
+ String symbs = symbol;
+ ManaSymbols.draw(g, symbs, x, y, w, Color.black, 2);
+ }
+
// Get the first line of the textbox, the keyword string
private static String getKeywordRulesString(ArrayList keywords) {
StringBuilder builder = new StringBuilder();
@@ -1073,7 +1272,34 @@ public class ModernCardRenderer extends CardRenderer {
return new Color(71, 86, 101);
}
}
-
+
+ // Determine which background image to use from a set of colors
+ // and the current card.
+ protected static BufferedImage getBackgroundImage(ObjectColor colors, Collection types, SubTypeList subTypes) {
+ if (subTypes.contains(SubType.VEHICLE)) {
+ return BG_IMG_VEHICLE;
+ } else if (types.contains(CardType.LAND)) {
+ return BG_IMG_LAND;
+ } else if (types.contains(CardType.ARTIFACT)) {
+ return BG_IMG_ARTIFACT;
+ } else if (colors.isMulticolored()) {
+ return BG_IMG_GOLD;
+ } else if (colors.isWhite()) {
+ return BG_IMG_WHITE;
+ } else if (colors.isBlue()) {
+ return BG_IMG_BLUE;
+ } else if (colors.isBlack()) {
+ return BG_IMG_BLACK;
+ } else if (colors.isRed()) {
+ return BG_IMG_RED;
+ } else if (colors.isGreen()) {
+ return BG_IMG_GREEN;
+ } else {
+ // Colorless
+ return BG_IMG_COLORLESS;
+ }
+ }
+
// Get the box color for the given colors
protected Color getBoxColor(ObjectColor colors, Collection types, boolean isNightCard) {
if (cardView.isAbility()) {
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ModernSplitCardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ModernSplitCardRenderer.java
index 98d01254c6d..0310d8e3acc 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/ModernSplitCardRenderer.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/ModernSplitCardRenderer.java
@@ -8,6 +8,7 @@ import mage.view.CardView;
import java.awt.*;
import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
@@ -17,6 +18,7 @@ import java.util.List;
public class ModernSplitCardRenderer extends ModernCardRenderer {
private class HalfCardProps {
+
int x, y, w, h, cw, ch;
String name;
@@ -27,7 +29,11 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
ArrayList keywords = new ArrayList<>();
}
- private static ArrayList ONLY_LAND_TYPE = new ArrayList() {{add(CardType.LAND);}};
+ private static ArrayList ONLY_LAND_TYPE = new ArrayList() {
+ {
+ add(CardType.LAND);
+ }
+ };
// Right and left halves of the card content
private HalfCardProps rightHalf = new HalfCardProps();
@@ -88,20 +94,20 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
// Decide size of divider
if (isAftermath()) {
dividerSize = borderWidth;
- dividerAt = (int)(cardHeight*0.54);
+ dividerAt = (int) (cardHeight * 0.54);
} else {
- int availHeight = cardHeight - totalContentInset - 3*borderWidth;
- dividerSize = borderWidth*2;
- dividerAt = (int)(totalContentInset + availHeight * 0.5 - borderWidth);
+ int availHeight = cardHeight - totalContentInset - 3 * borderWidth;
+ dividerSize = borderWidth * 2;
+ dividerAt = (int) (totalContentInset + availHeight * 0.5 - borderWidth);
}
// Decide size of each halves box
rightHalf.x = leftHalf.x = totalContentInset;
- rightHalf.w = leftHalf.w = cardWidth - 2*totalContentInset;
+ rightHalf.w = leftHalf.w = cardWidth - 2 * totalContentInset;
leftHalf.y = totalContentInset;
leftHalf.h = dividerAt - totalContentInset;
rightHalf.y = dividerAt + dividerSize;
- rightHalf.h = cardHeight - rightHalf.y - borderWidth*3;
+ rightHalf.h = cardHeight - rightHalf.y - borderWidth * 3;
// Content width / height (Exchanged from width / height if the card part is rotated)
if (isAftermath()) {
@@ -126,7 +132,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
private ObjectColor getColorFromManaCostHack(ManaCosts costs) {
ObjectColor c = new ObjectColor();
List symbols = costs.getSymbols();
- for (String symbol: symbols) {
+ for (String symbol : symbols) {
if (symbol.contains("W")) {
c.setWhite(true);
} else if (symbol.contains("U")) {
@@ -154,18 +160,18 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
// Draw main part (most of card)
g.fillRoundRect(
borderWidth, borderWidth,
- cardWidth - 2*borderWidth, leftHalf.h + contentInset - borderWidth - 2*cornerRadius + (cornerRadius - 1),
+ cardWidth - 2 * borderWidth, leftHalf.h + contentInset - borderWidth - 2 * cornerRadius + (cornerRadius - 1),
cornerRadius - 1, cornerRadius - 1);
// Draw the M15 rounded "swoosh" at the bottom
g.fillRoundRect(
- borderWidth, dividerAt - borderWidth - 4*cornerRadius,
- cardWidth - 2*borderWidth, cornerRadius * 4,
+ borderWidth, dividerAt - borderWidth - 4 * cornerRadius,
+ cardWidth - 2 * borderWidth, cornerRadius * 4,
cornerRadius * 2, cornerRadius * 2);
// Draw the cutout into the "swoosh" for the textbox to lie over
g.fillRect(
- borderWidth + contentInset, dividerAt - 2*borderWidth,
+ borderWidth + contentInset, dividerAt - 2 * borderWidth,
cardWidth - borderWidth * 2 - contentInset * 2, borderWidth * 2);
}
@@ -176,8 +182,8 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
// Draw the M15 rounded "swoosh"es at the top and bottom
g.fillRoundRect(
borderWidth, dividerAt + dividerSize + borderWidth,
- cardWidth - 2*borderWidth, rightHalf.h - 2*borderWidth,
- cornerRadius*2, cornerRadius*2);
+ cardWidth - 2 * borderWidth, rightHalf.h - 2 * borderWidth,
+ cornerRadius * 2, cornerRadius * 2);
// Draw the cutout into the "swoosh" for the textbox to lie over
g.fillRect(
@@ -236,8 +242,8 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
// Background of textbox
g.setPaint(textboxPaint);
g.fillRect(
- 1, typeLineY,
- half.cw - 2, half.ch - typeLineY - 1);
+ 1, typeLineY,
+ half.cw - 2, half.ch - typeLineY - 1);
// Draw the name line box
CardRendererUtils.drawRoundedBox(g,
@@ -261,7 +267,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
// Draw the type line
drawTypeLine(g, half.typeLineString,
0, typeLineY,
- half.cw, boxHeight - 4);
+ half.cw, boxHeight - 4, true);
// Draw the textbox rules
drawRulesText(g, half.keywords, half.rules,
@@ -270,13 +276,13 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
}
private Graphics2D getUnmodifiedHalfContext(Graphics2D g) {
- Graphics2D g2 = (Graphics2D)g.create();
+ Graphics2D g2 = (Graphics2D) g.create();
g2.translate(leftHalf.x, leftHalf.y);
return g2;
}
private Graphics2D getAftermathHalfContext(Graphics2D g) {
- Graphics2D g2 = (Graphics2D)g.create();
+ Graphics2D g2 = (Graphics2D) g.create();
g2.translate(rightHalf.x, rightHalf.y);
g2.rotate(Math.PI / 2);
g2.translate(0, -rightHalf.w);
@@ -284,7 +290,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
}
private Graphics2D getLeftHalfContext(Graphics2D g) {
- Graphics2D g2 = (Graphics2D)g.create();
+ Graphics2D g2 = (Graphics2D) g.create();
g2.translate(leftHalf.x, leftHalf.y);
g2.rotate(-Math.PI / 2);
g2.translate(-leftHalf.cw, 0);
@@ -292,7 +298,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
}
private Graphics2D getRightHalfContext(Graphics2D g) {
- Graphics2D g2 = (Graphics2D)g.create();
+ Graphics2D g2 = (Graphics2D) g.create();
g2.translate(rightHalf.x, rightHalf.y);
g2.rotate(-Math.PI / 2);
g2.translate(-rightHalf.cw, 0);
@@ -300,13 +306,13 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
}
@Override
- protected void drawFrame(Graphics2D g) {
+ protected void drawFrame(Graphics2D g, BufferedImage image) {
if (isAftermath()) {
- drawSplitHalfFrame(getUnmodifiedHalfContext(g), leftHalf, (int)(leftHalf.ch * TYPE_LINE_Y_FRAC));
+ drawSplitHalfFrame(getUnmodifiedHalfContext(g), leftHalf, (int) (leftHalf.ch * TYPE_LINE_Y_FRAC));
drawSplitHalfFrame(getAftermathHalfContext(g), rightHalf, (rightHalf.ch - boxHeight) / 2);
} else {
- drawSplitHalfFrame(getLeftHalfContext(g), leftHalf, (int)(leftHalf.ch * TYPE_LINE_Y_FRAC));
- drawSplitHalfFrame(getRightHalfContext(g), rightHalf, (int)(rightHalf.ch * TYPE_LINE_Y_FRAC));
+ drawSplitHalfFrame(getLeftHalfContext(g), leftHalf, (int) (leftHalf.ch * TYPE_LINE_Y_FRAC));
+ drawSplitHalfFrame(getRightHalfContext(g), rightHalf, (int) (rightHalf.ch * TYPE_LINE_Y_FRAC));
if (isFuse()) {
Graphics2D g2 = getRightHalfContext(g);
int totalFuseBoxWidth = rightHalf.cw * 2 + 2 * borderWidth + dividerSize;
@@ -319,7 +325,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
borderPaint, boxColor);
drawNameLine(g2, "Fuse (You may cast both halves from your hand)", "",
0, rightHalf.ch,
- totalFuseBoxWidth - 2*borderWidth, boxHeight);
+ totalFuseBoxWidth - 2 * borderWidth, boxHeight);
}
}
}
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java
index 38b5ff2b434..385204f822c 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java
@@ -66,7 +66,7 @@ public class GathererSets implements Iterable {
//"APAC" -- gatherer do not have that set, scrly have PALP
//"ARENA" -- is't many set with different codes, not one
"CLASH", "CP", "DD3GVL", "DPA", "EURO", "FNMP", "GPX", "GRC", "GUR", "H17", "JR", "MBP", "MGDC", "MLP", "MPRP", "MPS-AKH", "PTC", "S00", "S99", "SUS", "SWS", "UGIN", "UGL", "V10", "V17", "WMCQ", // need to fix
- "H09", "PD2", "PD3", "UNH", "CM1", "E02", "V11", "M25", "UST", "IMA", "DD2", "EVG", "DDC", "DDE", "DDD", "DDT", "8EB", "9EB", "CHR" // ok
+ "H09", "PD2", "PD3", "UNH", "CM1", "E02", "V11", "A25", "UST", "IMA", "DD2", "EVG", "DDC", "DDE", "DDD", "DDT", "8EB", "9EB", "CHR" // ok
// current testing
};
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java
index 6f664975ff9..aafb2d1568f 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java
@@ -208,7 +208,7 @@ public enum ScryfallImageSource implements CardImageSource {
supportedSets.add("RIX");
supportedSets.add("WMCQ");
supportedSets.add("PPRO");
-// supportedSets.add("A25");
+ supportedSets.add("A25");
// supportedSets.add("DOM");
// supportedSets.add("M19");
diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_colorless.png b/Mage.Client/src/main/resources/cardrender/background_texture_colorless.png
new file mode 100644
index 00000000000..9a27821dab6
Binary files /dev/null and b/Mage.Client/src/main/resources/cardrender/background_texture_colorless.png differ
diff --git a/Mage.Client/src/main/resources/cardrender/background_texture_vehicle.png b/Mage.Client/src/main/resources/cardrender/background_texture_vehicle.png
index 2f58f34a361..87282e34bc8 100644
Binary files a/Mage.Client/src/main/resources/cardrender/background_texture_vehicle.png and b/Mage.Client/src/main/resources/cardrender/background_texture_vehicle.png differ
diff --git a/Mage.Client/src/main/resources/image.url.properties b/Mage.Client/src/main/resources/image.url.properties
index 63ffa1a49a9..3aba474b2fb 100644
--- a/Mage.Client/src/main/resources/image.url.properties
+++ b/Mage.Client/src/main/resources/image.url.properties
@@ -73,6 +73,6 @@ dd3evg=ddaevg
dd3gvl=ddagvl
dd3jvc=ddajvc
# Remove setname as soon as the images can be downloaded
-ignore.urls=TOK,M19,M25,DOM,H17
+ignore.urls=TOK,M19,DOM,H17
# sets ordered by release time (newest goes first)
-token.lookup.order=M19,M25,DOM,E02,RIX,UST,XLN,IMA,H17,C17,V17,E01,DDT,CMA,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,MPS,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC
\ No newline at end of file
+token.lookup.order=M19,A25,DOM,E02,RIX,UST,XLN,IMA,H17,C17,V17,E01,DDT,CMA,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,MPS,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC
\ No newline at end of file
diff --git a/Mage.Common/src/main/java/mage/remote/SessionImpl.java b/Mage.Common/src/main/java/mage/remote/SessionImpl.java
index 187b8179c1c..1f7bca2c0cb 100644
--- a/Mage.Common/src/main/java/mage/remote/SessionImpl.java
+++ b/Mage.Common/src/main/java/mage/remote/SessionImpl.java
@@ -32,7 +32,6 @@ import java.lang.reflect.UndeclaredThrowableException;
import java.net.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
-import javax.swing.*;
import mage.MageException;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
@@ -1437,12 +1436,9 @@ public class SessionImpl implements Session {
@Override
public boolean endUserSession(String userSessionId) {
try {
- if (JOptionPane.showConfirmDialog(null, "Are you sure you mean to end userSessionId " + userSessionId + '?', "WARNING",
- JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
- if (isConnected()) {
- server.endUserSession(sessionId, userSessionId);
- return true;
- }
+ if (isConnected()) {
+ server.endUserSession(sessionId, userSessionId);
+ return true;
}
} catch (MageException ex) {
handleMageException(ex);
@@ -1455,12 +1451,9 @@ public class SessionImpl implements Session {
@Override
public boolean muteUserChat(String userName, long durationMinutes) {
try {
- if (JOptionPane.showConfirmDialog(null, "Are you sure you mean to mute user " + userName + " for " + durationMinutes + " minutes?", "WARNING",
- JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
- if (isConnected()) {
- server.muteUser(sessionId, userName, durationMinutes);
- return true;
- }
+ if (isConnected()) {
+ server.muteUser(sessionId, userName, durationMinutes);
+ return true;
}
} catch (MageException ex) {
handleMageException(ex);
@@ -1473,12 +1466,9 @@ public class SessionImpl implements Session {
@Override
public boolean setActivation(String userName, boolean active) {
try {
- if (JOptionPane.showConfirmDialog(null, "Are you sure you mean to set active to " + active + " for user: " + userName + '?', "WARNING",
- JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
- if (isConnected()) {
- server.setActivation(sessionId, userName, active);
- return true;
- }
+ if (isConnected()) {
+ server.setActivation(sessionId, userName, active);
+ return true;
}
} catch (MageException ex) {
handleMageException(ex);
@@ -1491,20 +1481,9 @@ public class SessionImpl implements Session {
@Override
public boolean toggleActivation(String userName) {
try {
- if (JOptionPane.showConfirmDialog(null, "Did you want to set user: " + userName + " to active?", "WARNING",
- JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
- return setActivation(userName, true);
- }
- if (JOptionPane.showConfirmDialog(null, "Did you want to set user: " + userName + " to INactive?", "WARNING",
- JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
- return setActivation(userName, false);
- }
- if (JOptionPane.showConfirmDialog(null, "Are you sure you mean to toggle activation for user: " + userName + '?', "WARNING",
- JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
- if (isConnected()) {
- server.toggleActivation(sessionId, userName);
- return true;
- }
+ if (isConnected()) {
+ server.toggleActivation(sessionId, userName);
+ return true;
}
} catch (MageException ex) {
handleMageException(ex);
@@ -1517,12 +1496,9 @@ public class SessionImpl implements Session {
@Override
public boolean lockUser(String userName, long durationMinute) {
try {
- if (JOptionPane.showConfirmDialog(null, "Are you sure you mean to lock user: " + userName + " for " + durationMinute + " minutes?", "WARNING",
- JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
- if (isConnected()) {
- server.lockUser(sessionId, userName, durationMinute);
- return true;
- }
+ if (isConnected()) {
+ server.lockUser(sessionId, userName, durationMinute);
+ return true;
}
} catch (MageException ex) {
handleMageException(ex);
diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java
index dd5e8b70a7e..4b729539d87 100644
--- a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java
+++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java
@@ -345,22 +345,53 @@ public class ConsolePanel extends javax.swing.JPanel {
private void btnEndSessionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEndSessionActionPerformed
int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow());
- ConsoleFrame.getSession().endUserSession((String) tableUserModel.getValueAt(row, TableUserModel.POS_GAME_INFO));
+ String userSessionId = (String) tableUserModel.getValueAt(row, TableUserModel.POS_GAME_INFO);
+
+ if (JOptionPane.showConfirmDialog(null, "Are you sure you mean to end userSessionId " + userSessionId + '?', "WARNING",
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
+ ConsoleFrame.getSession().endUserSession(userSessionId);
+ }
}//GEN-LAST:event_btnEndSessionActionPerformed
private void btnMuteUserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMuteUserActionPerformed
- int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow());
- ConsoleFrame.getSession().muteUserChat((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME), ((Number) spinnerMuteDurationMinutes.getValue()).longValue());
+ int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow());
+ String userName = (String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME);
+ long durationMinute = ((Number) spinnerMuteDurationMinutes.getValue()).longValue();
+ if (JOptionPane.showConfirmDialog(null, "Are you sure you mean to mute user: " + userName + " for " + durationMinute + " minutes?", "WARNING",
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
+ ConsoleFrame.getSession().muteUserChat(userName, durationMinute);
+ }
}//GEN-LAST:event_btnMuteUserActionPerformed
private void btnDeActivateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeActivateActionPerformed
int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow());
- ConsoleFrame.getSession().toggleActivation((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME));
+ String userName = (String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME);
+
+ if (JOptionPane.showConfirmDialog(null, "Did you want to set user: " + userName + " to active?", "WARNING",
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
+ ConsoleFrame.getSession().setActivation(userName, true);
+ return;
+ }
+ if (JOptionPane.showConfirmDialog(null, "Did you want to set user: " + userName + " to inactive?", "WARNING",
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
+ ConsoleFrame.getSession().setActivation(userName, false);
+ return;
+ }
+ if (JOptionPane.showConfirmDialog(null, "Are you sure you mean to toggle activation for user: " + userName + '?', "WARNING",
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
+ ConsoleFrame.getSession().toggleActivation(userName);
+ return;
+ }
}//GEN-LAST:event_btnDeActivateActionPerformed
private void btnLockUserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLockUserActionPerformed
int row = this.tblUsers.convertRowIndexToModel(tblUsers.getSelectedRow());
- ConsoleFrame.getSession().lockUser((String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME), ((Number) spinnerMuteDurationMinutes.getValue()).longValue());
+ String userName = (String) tableUserModel.getValueAt(row, TableUserModel.POS_USER_NAME);
+ long durationMinute = ((Number) spinnerMuteDurationMinutes.getValue()).longValue();
+ if (JOptionPane.showConfirmDialog(null, "Are you sure you mean to lock user: " + userName + " for " + durationMinute + " minutes?", "WARNING",
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
+ ConsoleFrame.getSession().lockUser(userName, durationMinute);
+ }
}//GEN-LAST:event_btnLockUserActionPerformed
private void btnRemoveTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveTableActionPerformed
diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java
index 371ead70e5f..d479f1b569f 100644
--- a/Mage.Server/src/main/java/mage/server/ChatManager.java
+++ b/Mage.Server/src/main/java/mage/server/ChatManager.java
@@ -28,6 +28,7 @@
package mage.server;
import java.util.*;
+import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
@@ -37,6 +38,8 @@ import java.util.regex.Pattern;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.server.exceptions.UserNotFoundException;
+import mage.server.game.GameController;
+import mage.server.game.GameManager;
import mage.server.util.SystemUtil;
import mage.view.ChatMessage.MessageColor;
import mage.view.ChatMessage.MessageType;
@@ -220,6 +223,27 @@ public enum ChatManager {
chatSessions.get(chatId).broadcastInfoToUser(user, message);
return true;
}
+ if (command.startsWith("GAME")) {
+ message += "
" + GameManager.instance.getChatId(chatId);
+ ChatSession session = chatSessions.get(chatId);
+ if (session != null && session.getInfo() != null) {
+ String gameId = session.getInfo();
+ if (gameId.startsWith("Game ")) {
+ UUID id = java.util.UUID.fromString(gameId.substring(5, gameId.length()));
+ for (Entry entry : GameManager.instance.getGameController().entrySet()) {
+ if (entry.getKey().equals(id)) {
+ GameController controller = entry.getValue();
+ if (controller != null) {
+ message += controller.getGameStateDebugMessage();
+ chatSessions.get(chatId).broadcastInfoToUser(user, message);
+ }
+ }
+ }
+
+ }
+ }
+ return true;
+ }
if (command.startsWith("CARD ")) {
Matcher matchPattern = getCardTextPattern.matcher(message.toLowerCase());
if (matchPattern.find()) {
@@ -289,18 +313,18 @@ public enum ChatManager {
public void sendReconnectMessage(UUID userId) {
UserManager.instance.getUser(userId).ifPresent(user
-> getChatSessions()
- .stream()
- .filter(chat -> chat.hasUser(userId))
- .forEach(chatSession -> chatSession.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS, null)));
+ .stream()
+ .filter(chat -> chat.hasUser(userId))
+ .forEach(chatSession -> chatSession.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS, null)));
}
public void sendLostConnectionMessage(UUID userId, DisconnectReason reason) {
UserManager.instance.getUser(userId).ifPresent(user
-> getChatSessions()
- .stream()
- .filter(chat -> chat.hasUser(userId))
- .forEach(chatSession -> chatSession.broadcast(null, user.getName() + reason.getMessage(), MessageColor.BLUE, true, MessageType.STATUS, null)));
+ .stream()
+ .filter(chat -> chat.hasUser(userId))
+ .forEach(chatSession -> chatSession.broadcast(null, user.getName() + reason.getMessage(), MessageColor.BLUE, true, MessageType.STATUS, null)));
}
diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java
index 35df50ba08f..70157884723 100644
--- a/Mage.Server/src/main/java/mage/server/TableController.java
+++ b/Mage.Server/src/main/java/mage/server/TableController.java
@@ -990,7 +990,7 @@ public class TableController {
|| !match.isDoneSideboarding()
|| (!matchPlayer.hasQuit() && match.getGame() != null && matchPlayer.getPlayer().isInGame())) {
Optional user = UserManager.instance.getUser(userPlayerEntry.getKey());
- if (!user.isPresent()) {
+ if (!user.isPresent() || !user.get().isActive()) {
logger.warn("- Active user of match is missing: " + matchPlayer.getName());
logger.warn("-- matchId:" + match.getId());
logger.warn("-- userId:" + userPlayerEntry.getKey());
diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java
index d039beff8da..1af7921751c 100644
--- a/Mage.Server/src/main/java/mage/server/game/GameController.java
+++ b/Mage.Server/src/main/java/mage/server/game/GameController.java
@@ -50,6 +50,7 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.game.GameException;
import mage.game.GameOptions;
+import mage.game.GameState;
import mage.game.Table;
import mage.game.events.Listener;
import mage.game.events.PlayerQueryEvent;
@@ -1088,4 +1089,97 @@ public class GameController implements GameCallback {
return false;
}
+ public String getGameStateDebugMessage() {
+ if (game == null) {
+ return "";
+ }
+ GameState state = game.getState();
+ if (state == null) {
+ return "";
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append("
Game State:
");
+ sb.append(state);
+
+ sb.append("
Active player is: ");
+ sb.append(game.getPlayer(state.getActivePlayerId()).getName());
+ sb.append("
isGameOver: ");
+ sb.append(state.isGameOver());
+ sb.append("
Current phase is: ");
+ sb.append(state.getTurn().getPhase());
+ sb.append("
getBattlefield: ");
+ sb.append(state.getBattlefield());
+ sb.append("
getChoosingPlayerId: ");
+ if (state.getChoosingPlayerId() != null) {
+ sb.append(game.getPlayer(state.getChoosingPlayerId()).getName());
+ } else {
+ sb.append("noone!");
+ }
+ sb.append("
getCombat: ");
+ sb.append(state.getCombat());
+ sb.append("
getCommand: ");
+ sb.append(state.getCommand());
+ sb.append("
getContinuousEffects: ");
+ sb.append(state.getContinuousEffects());
+ sb.append("
getCopiedCards: ");
+ sb.append(state.getCopiedCards());
+ sb.append("
getDelayed: ");
+ sb.append(state.getDelayed());
+ sb.append("
getDesignations: ");
+ sb.append(state.getDesignations());
+ sb.append("
getExile: ");
+ sb.append(state.getExile());
+ sb.append("
getMonarchId: ");
+ sb.append(state.getMonarchId());
+ sb.append("
getNextPermanentOrderNumber: ");
+ sb.append(state.getNextPermanentOrderNumber());
+ sb.append("
getPlayerByOrderId: ");
+ if (state.getPlayerByOrderId() != null) {
+ sb.append(game.getPlayer(state.getPlayerByOrderId()).getName());
+ } else {
+ sb.append("noone!");
+ }
+ sb.append("
getPlayerList: ");
+ sb.append(state.getPlayerList());
+ sb.append("
getPlayers: ");
+ sb.append(state.getPlayers());
+ sb.append("
Player with Priority is: ");
+ if (state.getPriorityPlayerId() != null) {
+ sb.append(game.getPlayer(state.getPriorityPlayerId()).getName());
+ } else {
+ sb.append("noone!");
+ }
+ sb.append("
getRevealed: ");
+ sb.append(state.getRevealed());
+ sb.append("
getSpecialActions: ");
+ sb.append(state.getSpecialActions());
+ sb.append("
getStack: ");
+ sb.append(state.getStack());
+ sb.append("
getStepNum: ");
+ sb.append(state.getStepNum());
+ sb.append("
getTriggers: ");
+ sb.append(state.getTriggers());
+ sb.append("
getTurn: ");
+ sb.append(state.getTurn());
+ sb.append("
getTurnId: ");
+ sb.append(state.getTurnId());
+ sb.append("
getTurnMods: ");
+ sb.append(state.getTurnMods());
+ sb.append("
getTurnNum: ");
+ sb.append(state.getTurnNum());
+ sb.append("
Future Timeout:");
+ if (futureTimeout != null) {
+ sb.append("Cancelled?=");
+ sb.append(futureTimeout.isCancelled());
+ sb.append(",,,Done?=");
+ sb.append(futureTimeout.isDone());
+ sb.append(",,,GetDelay?=");
+ sb.append((int) futureTimeout.getDelay(TimeUnit.SECONDS));
+ } else {
+ sb.append("Not using future Timeout!");
+ }
+ sb.append("");
+ return sb.toString();
+ }
+
}
diff --git a/Mage.Sets/src/mage/cards/a/ActOfAuthority.java b/Mage.Sets/src/mage/cards/a/ActOfAuthority.java
index 3a0f108245a..38dcd6ca161 100644
--- a/Mage.Sets/src/mage/cards/a/ActOfAuthority.java
+++ b/Mage.Sets/src/mage/cards/a/ActOfAuthority.java
@@ -27,6 +27,7 @@
*/
package mage.cards.a;
+import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@@ -44,8 +45,6 @@ import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;
-import java.util.UUID;
-
/**
*
* @author LevelX2
@@ -53,8 +52,7 @@ import java.util.UUID;
public class ActOfAuthority extends CardImpl {
public ActOfAuthority(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}{W}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}");
// When Act of Authority enters the battlefield, you may exile target artifact or enchantment.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect(), true);
@@ -96,9 +94,12 @@ class ActOfAuthorityEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Permanent targetPermanent = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (targetPermanent != null && new ExileTargetEffect().apply(game, source)) {
- ContinuousEffect effect = new ActOfAuthorityGainControlEffect(Duration.Custom, targetPermanent.getControllerId());
- effect.setTargetPointer(new FixedTarget(source.getSourceId()));
- game.addEffect(effect, source);
+ Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
+ if (sourcePermanent != null) {
+ ContinuousEffect effect = new ActOfAuthorityGainControlEffect(Duration.Custom, targetPermanent.getControllerId());
+ effect.setTargetPointer(new FixedTarget(sourcePermanent, game));
+ game.addEffect(effect, source);
+ }
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/a/AdarkarValkyrie.java b/Mage.Sets/src/mage/cards/a/AdarkarValkyrie.java
index ae3abfebab8..0fccaadd0dd 100644
--- a/Mage.Sets/src/mage/cards/a/AdarkarValkyrie.java
+++ b/Mage.Sets/src/mage/cards/a/AdarkarValkyrie.java
@@ -109,7 +109,7 @@ class AdarkarValkyrieEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(new FixedTarget(this.getTargetPointer().getFirst(game, source)));
+ DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(getTargetPointer().getFixedTarget(game, source));
game.addDelayedTriggeredAbility(delayedAbility, source);
return false;
}
diff --git a/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java b/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java
index ec6cf2b57af..ce6a6d5522a 100644
--- a/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java
+++ b/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java
@@ -51,17 +51,17 @@ import mage.target.targetpointer.FixedTarget;
public class AmbuscadeShaman extends CardImpl {
public AmbuscadeShaman(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.ORC);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Ambuscade Shaman or another creature enters the battlefield under your control, that creature gets +2/+2 until end of turn.
- Effect effect = new BoostTargetEffect(2,2, Duration.EndOfTurn);
+ Effect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn);
effect.setText("that creature gets +2/+2 until end of turn");
this.addAbility(new AmbuscadeShamanTriggeredAbility(effect));
-
+
// Dash {3}{B} (You may cast this spell for its dash cost. If you do, it gains haste, and it's returned from the battlefield to its owner's hand at the beginning of the next end step.));
this.addAbility(new DashAbility(this, "{3}{B}"));
@@ -103,9 +103,7 @@ class AmbuscadeShamanTriggeredAbility extends TriggeredAbilityImpl {
Permanent permanent = game.getPermanent(targetId);
if (permanent.getControllerId().equals(this.controllerId)
&& permanent.isCreature()) {
- for (Effect effect : this.getEffects()) {
- effect.setTargetPointer(new FixedTarget(event.getTargetId()));
- }
+ this.getEffects().setTargetPointer(new FixedTarget(permanent, game));
return true;
}
return false;
@@ -115,4 +113,4 @@ class AmbuscadeShamanTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever {this} or another creature enters the battlefield under your control, that creature gets +2/+2 until end of turn.";
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/a/AnimateDead.java b/Mage.Sets/src/mage/cards/a/AnimateDead.java
index 4c57bb51d26..a6e9ad0b75d 100644
--- a/Mage.Sets/src/mage/cards/a/AnimateDead.java
+++ b/Mage.Sets/src/mage/cards/a/AnimateDead.java
@@ -100,7 +100,7 @@ class AnimateDeadReAttachEffect extends OneShotEffect {
public AnimateDeadReAttachEffect() {
super(Outcome.Benefit);
- this.staticText = "Return enchanted creature card to the battlefield under your control and attach {this} to it";
+ this.staticText = "return enchanted creature card to the battlefield under your control and attach {this} to it";
}
public AnimateDeadReAttachEffect(final AnimateDeadReAttachEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/a/AnkhOfMishra.java b/Mage.Sets/src/mage/cards/a/AnkhOfMishra.java
index 38272e1e8ef..a31aa9dbf4c 100644
--- a/Mage.Sets/src/mage/cards/a/AnkhOfMishra.java
+++ b/Mage.Sets/src/mage/cards/a/AnkhOfMishra.java
@@ -45,16 +45,16 @@ import mage.target.targetpointer.FixedTarget;
/**
*
* @author KholdFuzion
-
+ *
*/
public class AnkhOfMishra extends CardImpl {
-
+
public AnkhOfMishra(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// Whenever a land enters the battlefield, Ankh of Mishra deals 2 damage to that land's controller.
this.addAbility(new AnkhOfMishraAbility());
-
+
}
public AnkhOfMishra(final AnkhOfMishra card) {
@@ -70,16 +70,16 @@ public class AnkhOfMishra extends CardImpl {
class AnkhOfMishraAbility extends TriggeredAbilityImpl {
public AnkhOfMishraAbility() {
- super(Zone.BATTLEFIELD, new DamageTargetEffect(2));
+ super(Zone.BATTLEFIELD, new DamageTargetEffect(2));
}
AnkhOfMishraAbility(final AnkhOfMishraAbility ability) {
- super(ability);
+ super(ability);
}
@Override
public AnkhOfMishraAbility copy() {
- return new AnkhOfMishraAbility(this);
+ return new AnkhOfMishraAbility(this);
}
@Override
@@ -104,6 +104,6 @@ class AnkhOfMishraAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever a land enters the battlefield, Ankh of Mishra deals 2 damage to that land's controller.";
+ return "Whenever a land enters the battlefield, {this} deals 2 damage to that land's controller.";
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/a/ArbiterOfTheIdeal.java b/Mage.Sets/src/mage/cards/a/ArbiterOfTheIdeal.java
index 31453ff15bf..de172fddb18 100644
--- a/Mage.Sets/src/mage/cards/a/ArbiterOfTheIdeal.java
+++ b/Mage.Sets/src/mage/cards/a/ArbiterOfTheIdeal.java
@@ -29,6 +29,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
@@ -53,7 +54,7 @@ import mage.target.targetpointer.FixedTarget;
public class ArbiterOfTheIdeal extends CardImpl {
public ArbiterOfTheIdeal(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
this.subtype.add(SubType.SPHINX);
this.power = new MageInt(4);
@@ -79,6 +80,7 @@ public class ArbiterOfTheIdeal extends CardImpl {
class ArbiterOfTheIdealEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard();
+
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
@@ -102,32 +104,25 @@ class ArbiterOfTheIdealEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getControllerId());
- if (player == null) {
+ Player controller = game.getPlayer(source.getControllerId());
+ MageObject sourceObject = source.getSourceObject(game);
+ if (controller == null || sourceObject == null) {
return false;
}
-
- if (player.getLibrary().hasCards()) {
- Card card = player.getLibrary().getFromTop(game);
- Cards cards = new CardsImpl();
- cards.add(card);
- player.revealCards("Arbiter of the Ideal", cards, game);
-
- if (card != null) {
- if (filter.match(card, game) && player.chooseUse(outcome, new StringBuilder("Put ").append(card.getName()).append("onto battlefield?").toString(), source, game)) {
- card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), source.getControllerId());
- Permanent permanent = game.getPermanent(card.getId());
- if (permanent != null) {
- permanent.addCounters(new Counter("Manifestation"), source, game);
- ContinuousEffect effect = new AddCardTypeTargetEffect(Duration.Custom, CardType.ENCHANTMENT);
- effect.setTargetPointer(new FixedTarget(permanent.getId()));
- game.addEffect(effect, source);
- }
+ Card card = controller.getLibrary().getFromTop(game);
+ if (card != null) {
+ controller.revealCards(sourceObject.getIdName(), new CardsImpl(card), game);
+ if (filter.match(card, game) && controller.chooseUse(outcome, "Put " + card.getName() + "onto battlefield?", source, game)) {
+ controller.moveCards(card, Zone.BATTLEFIELD, source, game);
+ Permanent permanent = game.getPermanent(card.getId());
+ if (permanent != null) {
+ permanent.addCounters(new Counter("Manifestation"), source, game);
+ ContinuousEffect effect = new AddCardTypeTargetEffect(Duration.Custom, CardType.ENCHANTMENT);
+ effect.setTargetPointer(new FixedTarget(permanent, game));
+ game.addEffect(effect, source);
}
}
- return true;
}
-
- return false;
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java b/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java
index 6b3507d3487..50342b73b40 100644
--- a/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java
+++ b/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java
@@ -29,23 +29,18 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
-import mage.players.Player;
-import mage.target.targetpointer.FixedTarget;
/**
* @author Loki
@@ -53,7 +48,7 @@ import mage.target.targetpointer.FixedTarget;
public class ArchonOfRedemption extends CardImpl {
public ArchonOfRedemption(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
this.subtype.add(SubType.ARCHON);
this.power = new MageInt(3);
@@ -75,8 +70,9 @@ public class ArchonOfRedemption extends CardImpl {
}
class ArchonOfRedemptionTriggeredAbility extends TriggeredAbilityImpl {
+
ArchonOfRedemptionTriggeredAbility() {
- super(Zone.BATTLEFIELD, new ArchonOfRedemptionEffect(), true);
+ super(Zone.BATTLEFIELD, null, true);
}
ArchonOfRedemptionTriggeredAbility(final ArchonOfRedemptionTriggeredAbility ability) {
@@ -95,15 +91,13 @@ class ArchonOfRedemptionTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- UUID targetId = event.getTargetId();
- Permanent permanent = game.getPermanent(targetId);
- if (permanent.getControllerId().equals(this.controllerId)
+ Permanent permanent = game.getPermanent(event.getTargetId());
+ if (permanent.getControllerId().equals(getControllerId())
&& permanent.isCreature()
- && (targetId.equals(this.getSourceId())
- || (permanent.getAbilities().contains(FlyingAbility.getInstance()) && !targetId.equals(this.getSourceId())))) {
- for (Effect effect : this.getEffects()) {
- effect.setTargetPointer(new FixedTarget(event.getTargetId()));
- }
+ && (permanent.getId().equals(getSourceId())
+ || (permanent.getAbilities().contains(FlyingAbility.getInstance())))) {
+ this.getEffects().clear();
+ this.addEffect(new GainLifeEffect(permanent.getPower().getValue()));
return true;
}
return false;
@@ -111,35 +105,6 @@ class ArchonOfRedemptionTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever {this} or another creature with flying enters the battlefield under your control, you may gain life equal to that creature's power";
+ return "Whenever {this} or another creature with flying enters the battlefield under your control, you may gain life equal to that creature's power.";
}
}
-
-class ArchonOfRedemptionEffect extends OneShotEffect {
- ArchonOfRedemptionEffect() {
- super(Outcome.GainLife);
- }
-
- ArchonOfRedemptionEffect(final ArchonOfRedemptionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Permanent p = game.getPermanent(targetPointer.getFirst(game, source));
- Player player = game.getPlayer(source.getControllerId());
- if (p == null) {
- p = (Permanent) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.BATTLEFIELD);
- }
- if (p != null && player != null) {
- player.gainLife(p.getPower().getValue(), game);
- return true;
- }
- return false;
- }
-
- @Override
- public ArchonOfRedemptionEffect copy() {
- return new ArchonOfRedemptionEffect(this);
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/a/ArrogantBloodlord.java b/Mage.Sets/src/mage/cards/a/ArrogantBloodlord.java
index e6c11100593..0aa16e9cfe5 100644
--- a/Mage.Sets/src/mage/cards/a/ArrogantBloodlord.java
+++ b/Mage.Sets/src/mage/cards/a/ArrogantBloodlord.java
@@ -53,7 +53,7 @@ import mage.target.targetpointer.FixedTarget;
public class ArrogantBloodlord extends CardImpl {
public ArrogantBloodlord(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}");
this.subtype.add(SubType.VAMPIRE);
this.subtype.add(SubType.KNIGHT);
@@ -104,11 +104,8 @@ class ArrogantBloodlordTriggeredAbility extends TriggeredAbilityImpl {
&& Objects.equals(blocked, arrogantBloodlord)) {
return true;
}
- if (blocker != null && Objects.equals(blocker, arrogantBloodlord)
- && game.getPermanent(event.getTargetId()).getPower().getValue() < 2) {
- return true;
- }
- return false;
+ return blocker != null && Objects.equals(blocker, arrogantBloodlord)
+ && game.getPermanent(event.getTargetId()).getPower().getValue() < 2;
}
@Override
@@ -133,7 +130,7 @@ class ArrogantBloodlordEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect());
- delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(source.getSourceId()));
+ delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(permanent, game));
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/a/AyeshaTanaka.java b/Mage.Sets/src/mage/cards/a/AyeshaTanaka.java
index d16fa76af3b..f6e44e52830 100644
--- a/Mage.Sets/src/mage/cards/a/AyeshaTanaka.java
+++ b/Mage.Sets/src/mage/cards/a/AyeshaTanaka.java
@@ -37,16 +37,13 @@ import mage.abilities.effects.common.CounterUnlessPaysEffect;
import mage.abilities.keyword.BandingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AbilityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
-import mage.filter.FilterStackObject;
-import mage.filter.predicate.Predicate;
-import mage.game.Game;
-import mage.game.stack.StackAbility;
-import mage.target.common.TargetActivatedOrTriggeredAbility;
+import mage.filter.FilterAbility;
+import mage.filter.predicate.ability.ArtifactSourcePredicate;
+import mage.target.common.TargetActivatedAbility;
/**
*
@@ -54,26 +51,26 @@ import mage.target.common.TargetActivatedOrTriggeredAbility;
*/
public class AyeshaTanaka extends CardImpl {
- private final static FilterStackObject filter = new FilterStackObject("activated ability from an artifact source");
+ private final static FilterAbility filter = new FilterAbility("activated ability from an artifact source");
static {
filter.add(new ArtifactSourcePredicate());
}
public AyeshaTanaka(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}{W}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}{U}{U}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ARTIFICER);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
-
+
// Banding
this.addAbility(BandingAbility.getInstance());
// {T}: Counter target activated ability from an artifact source unless that ability's controller pays {W}.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(new ManaCostsImpl("{W}")), new TapSourceCost());
- ability.addTarget(new TargetActivatedOrTriggeredAbility(filter));
+ ability.addTarget(new TargetActivatedAbility(filter));
this.addAbility(ability);
}
@@ -86,22 +83,3 @@ public class AyeshaTanaka extends CardImpl {
return new AyeshaTanaka(this);
}
}
-
-class ArtifactSourcePredicate implements Predicate {
-
- public ArtifactSourcePredicate() {
- }
-
- @Override
- public boolean apply(Ability input, Game game) {
- if (input instanceof StackAbility) {
- return input.getSourceObject(game).isArtifact() && input.getAbilityType() == AbilityType.ACTIVATED;
- }
- return false;
- }
-
- @Override
- public String toString() {
- return "Source(Artifact)";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/b/BackFromTheBrink.java b/Mage.Sets/src/mage/cards/b/BackFromTheBrink.java
index 6e92e76df4d..b887c7b5a27 100644
--- a/Mage.Sets/src/mage/cards/b/BackFromTheBrink.java
+++ b/Mage.Sets/src/mage/cards/b/BackFromTheBrink.java
@@ -103,7 +103,7 @@ class BackFromTheBrinkCost extends CostImpl {
if (controller != null) {
Card card = controller.getGraveyard().get(targets.getFirstTarget(), game);
if (card != null && controller.moveCards(card, Zone.EXILED, ability, game)) {
- ability.getEffects().get(0).setTargetPointer(new FixedTarget(card.getId()));
+ ability.getEffects().get(0).setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId())));
paid = card.getManaCost().pay(ability, game, sourceId, controllerId, noMana);
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java
index 196e0544663..e8378805b5f 100644
--- a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java
+++ b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java
@@ -161,14 +161,24 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect {
// Relevant ruling for Balduvian Warlord:
// 7/15/2006 If an attacking creature has an ability that triggers “When this creature becomes blocked,”
// it triggers when a creature blocks it due to the Warlord’s ability only if it was unblocked at that point.
-
boolean notYetBlocked = chosenGroup.getBlockers().isEmpty();
- chosenGroup.addBlocker(permanent.getId(), controller.getId(), game);
+ chosenGroup.addBlockerToGroup(permanent.getId(), controller.getId(), game);
+ game.getCombat().addBlockingGroup(permanent.getId(), chosenPermanent.getId(), controller.getId(), game); // 702.21h
if (notYetBlocked) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, chosenPermanent.getId(), null));
+ for (UUID bandedId : chosenPermanent.getBandedCards()) {
+ CombatGroup bandedGroup = game.getCombat().findGroup(bandedId);
+ if (bandedGroup != null && chosenGroup.getBlockers().size() == 1) {
+ game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, bandedId, null));
+ }
+ }
}
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, chosenPermanent.getId(), permanent.getId(), permanent.getControllerId()));
}
+ CombatGroup blockGroup = findBlockingGroup(permanent, game); // a new blockingGroup is formed, so it's necessary to find it again
+ if (blockGroup != null) {
+ blockGroup.pickAttackerOrder(permanent.getControllerId(), game);
+ }
}
}
return true;
@@ -176,4 +186,15 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect {
}
return false;
}
+
+ private CombatGroup findBlockingGroup(Permanent blocker, Game game) {
+ if (game.getCombat().blockingGroupsContains(blocker.getId())) { // if (blocker.getBlocking() > 1) {
+ for (CombatGroup group : game.getCombat().getBlockingGroups()) {
+ if (group.getBlockers().contains(blocker.getId())) {
+ return group;
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/Mage.Sets/src/mage/cards/b/BarrinsUnmaking.java b/Mage.Sets/src/mage/cards/b/BarrinsUnmaking.java
index 2ef729a53cc..ec6af647eea 100644
--- a/Mage.Sets/src/mage/cards/b/BarrinsUnmaking.java
+++ b/Mage.Sets/src/mage/cards/b/BarrinsUnmaking.java
@@ -52,7 +52,7 @@ public class BarrinsUnmaking extends CardImpl {
public BarrinsUnmaking(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
- // Return target permanent to its owner's hand if that permanent shares a color with the most common color among all permanents or a color tied for most common.
+ // Return target permanent to its owner's hand if that permanent shares a color with the most common color among all permanents or a color tied for most common.
this.getSpellAbility().addEffect(new BarrinsUnmakingEffect());
this.getSpellAbility().addTarget(new TargetPermanent());
}
@@ -85,12 +85,12 @@ class BarrinsUnmakingEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Permanent permanent = game.getPermanent(source.getFirstTarget());
+ Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
Condition condition = new MostCommonColorCondition(permanent.getColor(game));
if (condition.apply(game, source)) {
Effect effect = new ReturnToHandTargetEffect();
- effect.setTargetPointer(new FixedTarget(permanent.getId()));
+ effect.setTargetPointer(new FixedTarget(permanent, game));
return effect.apply(game, source);
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BeaconOfDestiny.java b/Mage.Sets/src/mage/cards/b/BeaconOfDestiny.java
new file mode 100644
index 00000000000..b93b478839b
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BeaconOfDestiny.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.b;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.effects.RedirectionEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.game.stack.Spell;
+import mage.players.Player;
+import mage.target.TargetPermanent;
+import mage.target.TargetSource;
+
+/**
+ *
+ * @author L_J
+ */
+public class BeaconOfDestiny extends CardImpl {
+
+ public BeaconOfDestiny(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(3);
+
+ // {T}: The next time a source of your choice would deal damage to you this turn, that damage is dealt to Beacon of Destiny instead.
+ this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BeaconOfDestinyEffect(), new TapSourceCost()));
+ }
+
+ public BeaconOfDestiny(final BeaconOfDestiny card) {
+ super(card);
+ }
+
+ @Override
+ public BeaconOfDestiny copy() {
+ return new BeaconOfDestiny(this);
+ }
+}
+
+class BeaconOfDestinyEffect extends RedirectionEffect {
+
+ private final TargetSource damageSource;
+
+ public BeaconOfDestinyEffect() {
+ super(Duration.EndOfTurn, Integer.MAX_VALUE, true);
+ staticText = "The next time a source of your choice would deal damage to you this turn, that damage is dealt to {this} instead";
+ this.damageSource = new TargetSource();
+ }
+
+ public BeaconOfDestinyEffect(final BeaconOfDestinyEffect effect) {
+ super(effect);
+ this.damageSource = effect.damageSource.copy();
+ }
+
+ @Override
+ public BeaconOfDestinyEffect copy() {
+ return new BeaconOfDestinyEffect(this);
+ }
+
+ @Override
+ public void init(Ability source, Game game) {
+ this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
+ super.init(source, game);
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ // check source
+ MageObject object = game.getObject(event.getSourceId());
+ if (object == null) {
+ game.informPlayers("Couldn't find source of damage");
+ return false;
+ }
+
+ if (!object.getId().equals(damageSource.getFirstTarget())
+ && (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(damageSource.getFirstTarget()))) {
+ return false;
+ }
+ TargetPermanent target = new TargetPermanent();
+ target.add(source.getSourceId(), game);
+ this.redirectTarget = target;
+
+ // check player
+ Player player = game.getPlayer(event.getTargetId());
+ if (player != null) {
+ if (player.getId().equals(source.getControllerId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/b/BlazeOfGlory.java b/Mage.Sets/src/mage/cards/b/BlazeOfGlory.java
new file mode 100644
index 00000000000..c8e22ca5631
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BlazeOfGlory.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.b;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
+import mage.abilities.condition.common.BeforeBlockersAreDeclaredCondition;
+import mage.abilities.effects.RequirementEffect;
+import mage.abilities.effects.common.combat.CanBlockAdditionalCreatureTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.TurnPhase;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.ObjectPlayer;
+import mage.filter.predicate.ObjectPlayerPredicate;
+import mage.game.Controllable;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.target.common.TargetCreaturePermanent;
+
+/**
+ *
+ * @author L_J
+ */
+public class BlazeOfGlory extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls");
+
+ static {
+ filter.add(new BlazeOfGloryDefendingPlayerControlsPredicate());
+ }
+
+ public BlazeOfGlory(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
+
+ // Cast Blaze of Glory only during combat before blockers are declared.
+ this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(TurnPhase.COMBAT, BeforeBlockersAreDeclaredCondition.instance));
+
+ // Target creature defending player controls can block any number of creatures this turn. It blocks each attacking creature this turn if able.
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
+ this.getSpellAbility().addEffect(new CanBlockAdditionalCreatureTargetEffect(Duration.EndOfTurn, 0));
+ this.getSpellAbility().addEffect(new BlazeOfGloryRequirementEffect());
+ }
+
+ public BlazeOfGlory(final BlazeOfGlory card) {
+ super(card);
+ }
+
+ @Override
+ public BlazeOfGlory copy() {
+ return new BlazeOfGlory(this);
+ }
+}
+
+class BlazeOfGloryDefendingPlayerControlsPredicate implements ObjectPlayerPredicate> {
+
+ @Override
+ public boolean apply(ObjectPlayer input, Game game) {
+ return game.getCombat().getPlayerDefenders(game).contains(input.getObject().getControllerId());
+ }
+}
+
+class BlazeOfGloryRequirementEffect extends RequirementEffect {
+
+ public BlazeOfGloryRequirementEffect() {
+ super(Duration.EndOfTurn);
+ this.staticText = "It blocks each attacking creature this turn if able";
+ }
+
+ public BlazeOfGloryRequirementEffect(final BlazeOfGloryRequirementEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean applies(Permanent permanent, Ability source, Game game) {
+ return permanent.getId().equals(targetPointer.getFirst(game, source));
+ }
+
+ @Override
+ public boolean mustAttack(Game game) {
+ return false;
+ }
+
+ @Override
+ public boolean mustBlock(Game game) {
+ return true;
+ }
+
+ @Override
+ public boolean mustBlockAllAttackers(Game game) {
+ return true;
+ }
+
+ @Override
+ public BlazeOfGloryRequirementEffect copy() {
+ return new BlazeOfGloryRequirementEffect(this);
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java b/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java
index fc3b22aba5f..7620727df5a 100644
--- a/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java
+++ b/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java
@@ -53,7 +53,7 @@ import java.util.UUID;
*/
public class BrassTalonChimera extends CardImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Chimera creature you control");
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Chimera creature");
static {
filter.add(new SubtypePredicate(SubType.CHIMERA));
diff --git a/Mage.Sets/src/mage/cards/b/BrownOuphe.java b/Mage.Sets/src/mage/cards/b/BrownOuphe.java
index 1810831dd07..06bc31afbfd 100644
--- a/Mage.Sets/src/mage/cards/b/BrownOuphe.java
+++ b/Mage.Sets/src/mage/cards/b/BrownOuphe.java
@@ -27,6 +27,7 @@
*/
package mage.cards.b;
+import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -35,17 +36,12 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AbilityType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.FilterStackObject;
-import mage.filter.predicate.Predicate;
-import mage.game.Game;
-import mage.game.stack.StackAbility;
-import mage.target.common.TargetActivatedOrTriggeredAbility;
-
-import java.util.UUID;
+import mage.filter.FilterAbility;
+import mage.filter.predicate.ability.ArtifactSourcePredicate;
+import mage.target.common.TargetActivatedAbility;
/**
*
@@ -53,7 +49,7 @@ import java.util.UUID;
*/
public class BrownOuphe extends CardImpl {
- private final static FilterStackObject filter = new FilterStackObject("activated ability from an artifact source");
+ private final static FilterAbility filter = new FilterAbility("activated ability from an artifact source");
static {
filter.add(new ArtifactSourcePredicate());
@@ -69,7 +65,7 @@ public class BrownOuphe extends CardImpl {
// {1}{G}, {tap}: Counter target activated ability from an artifact source.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl<>("{1}{G}"));
ability.addCost(new TapSourceCost());
- ability.addTarget(new TargetActivatedOrTriggeredAbility(filter));
+ ability.addTarget(new TargetActivatedAbility(filter));
this.addAbility(ability);
}
@@ -82,22 +78,3 @@ public class BrownOuphe extends CardImpl {
return new BrownOuphe(this);
}
}
-
-class ArtifactSourcePredicate implements Predicate {
-
- public ArtifactSourcePredicate() {
- }
-
- @Override
- public boolean apply(Ability input, Game game) {
- if (input instanceof StackAbility) {
- return input.getSourceObject(game).isArtifact() && input.getAbilityType() == AbilityType.ACTIVATED;
- }
- return false;
- }
-
- @Override
- public String toString() {
- return "Source(Artifact)";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/c/CallToGlory.java b/Mage.Sets/src/mage/cards/c/CallToGlory.java
index 9d678be5157..b2c31e6112d 100644
--- a/Mage.Sets/src/mage/cards/c/CallToGlory.java
+++ b/Mage.Sets/src/mage/cards/c/CallToGlory.java
@@ -28,21 +28,16 @@
package mage.cards.c;
import java.util.UUID;
-import mage.abilities.Ability;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.UntapAllEffect;
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.constants.SubType;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
/**
* @author Loki
@@ -57,8 +52,9 @@ public class CallToGlory extends CardImpl {
public CallToGlory(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
-
- this.getSpellAbility().addEffect(new CalltoGloryFirstEffect());
+
+ //Untap all creatures you control. Samurai creatures you control get +1/+1 until end of turn.
+ this.getSpellAbility().addEffect(new UntapAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURE));
this.getSpellAbility().addEffect(new BoostControlledEffect(1, 1, Duration.EndOfTurn, filter, false));
}
@@ -70,35 +66,4 @@ public class CallToGlory extends CardImpl {
public CallToGlory copy() {
return new CallToGlory(this);
}
-
-}
-
-class CalltoGloryFirstEffect extends OneShotEffect {
-
- public CalltoGloryFirstEffect() {
- super(Outcome.Untap);
- staticText = "Untap all creatures you control";
- }
-
- public CalltoGloryFirstEffect(final CalltoGloryFirstEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- for (Permanent creature : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), game)) {
- creature.untap(game);
- }
- return true;
- }
- return false;
- }
-
- @Override
- public CalltoGloryFirstEffect copy() {
- return new CalltoGloryFirstEffect(this);
- }
-
}
diff --git a/Mage.Sets/src/mage/cards/c/CityOfSolitude.java b/Mage.Sets/src/mage/cards/c/CityOfSolitude.java
index 03cef0637f7..dbcc7129ba6 100644
--- a/Mage.Sets/src/mage/cards/c/CityOfSolitude.java
+++ b/Mage.Sets/src/mage/cards/c/CityOfSolitude.java
@@ -28,6 +28,7 @@
package mage.cards.c;
import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
@@ -48,7 +49,7 @@ import mage.game.events.GameEvent.EventType;
public class CityOfSolitude extends CardImpl {
public CityOfSolitude(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
// Players can cast spells and activate abilities only during their own turns.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CityOfSolitudeEffect()));
@@ -74,12 +75,22 @@ class CityOfSolitudeEffect extends ContinuousRuleModifyingEffectImpl {
CityOfSolitudeEffect(final CityOfSolitudeEffect effect) {
super(effect);
}
-
+
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.CAST_SPELL || event.getType() == EventType.ACTIVATE_ABILITY;
}
-
+
+ @Override
+ public String getInfoMessage(Ability source, GameEvent event, Game game) {
+ MageObject sourceObject = game.getObject(source.getSourceId());
+ MageObject eventObject = game.getObject(event.getSourceId());
+ if (sourceObject != null && eventObject != null) {
+ return "You can cast or activate anability of " + eventObject.getIdName() + " only during your own turns (" + sourceObject.getIdName() + "). ";
+ }
+ return null;
+ }
+
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return !game.getActivePlayerId().equals(event.getPlayerId());
@@ -89,4 +100,4 @@ class CityOfSolitudeEffect extends ContinuousRuleModifyingEffectImpl {
public CityOfSolitudeEffect copy() {
return new CityOfSolitudeEffect(this);
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/c/CoffinQueen.java b/Mage.Sets/src/mage/cards/c/CoffinQueen.java
index ca66fe8f4a0..c7ea4503d51 100644
--- a/Mage.Sets/src/mage/cards/c/CoffinQueen.java
+++ b/Mage.Sets/src/mage/cards/c/CoffinQueen.java
@@ -41,9 +41,9 @@ import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffec
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
@@ -60,7 +60,7 @@ import mage.target.targetpointer.FixedTarget;
public class CoffinQueen extends CardImpl {
public CoffinQueen(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(1);
@@ -68,14 +68,14 @@ public class CoffinQueen extends CardImpl {
// You may choose not to untap Coffin Queen during your untap step.
this.addAbility(new SkipUntapOptionalAbility());
-
+
// {2}{B}, {tap}: Put target creature card from a graveyard onto the battlefield under your control. When Coffin Queen becomes untapped or you lose control of Coffin Queen, exile that creature.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), new ManaCostsImpl("{2}{B}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard")));
- ability.addEffect(new CoffinQueenCreateDelayedTriggerEffect());
+ ability.addEffect(new CoffinQueenCreateDelayedTriggerEffect());
this.addAbility(ability);
-
+
}
public CoffinQueen(final CoffinQueen card) {
@@ -87,33 +87,30 @@ public class CoffinQueen extends CardImpl {
return new CoffinQueen(this);
}
}
+
class CoffinQueenCreateDelayedTriggerEffect extends OneShotEffect {
-
+
public CoffinQueenCreateDelayedTriggerEffect() {
super(Outcome.Detriment);
- this.staticText = "When Coffin Queen becomes untapped or you lose control of Coffin Queen, exile that creature";
+ this.staticText = "When {this} becomes untapped or you lose control of {this}, exile that creature.";
}
-
+
public CoffinQueenCreateDelayedTriggerEffect(final CoffinQueenCreateDelayedTriggerEffect effect) {
super(effect);
}
-
+
@Override
public CoffinQueenCreateDelayedTriggerEffect copy() {
return new CoffinQueenCreateDelayedTriggerEffect(this);
}
-
+
@Override
public boolean apply(Game game, Ability source) {
Permanent controlledCreature = game.getPermanent(source.getFirstTarget());
if (controlledCreature != null) {
DelayedTriggeredAbility delayedAbility = new CoffinQueenDelayedTriggeredAbility();
- delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(controlledCreature.getId()));
- delayedAbility.setSourceId(source.getSourceId());
- delayedAbility.setControllerId(source.getControllerId());
- delayedAbility.setSourceObject(source.getSourceObject(game), game);
- delayedAbility.init(game);
- game.addDelayedTriggeredAbility(delayedAbility);
+ delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(controlledCreature, game));
+ game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
return false;
@@ -123,7 +120,7 @@ class CoffinQueenCreateDelayedTriggerEffect extends OneShotEffect {
class CoffinQueenDelayedTriggeredAbility extends DelayedTriggeredAbility {
CoffinQueenDelayedTriggeredAbility() {
- super(new ExileTargetEffect(), Duration.EndOfGame, true);
+ super(new ExileTargetEffect(), Duration.EndOfGame, true);
}
CoffinQueenDelayedTriggeredAbility(CoffinQueenDelayedTriggeredAbility ability) {
@@ -136,7 +133,6 @@ class CoffinQueenDelayedTriggeredAbility extends DelayedTriggeredAbility {
|| event.getType() == EventType.UNTAPPED;
}
-
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (EventType.LOST_CONTROL == event.getType()
@@ -146,14 +142,14 @@ class CoffinQueenDelayedTriggeredAbility extends DelayedTriggeredAbility {
return EventType.UNTAPPED == event.getType()
&& event.getTargetId() != null && event.getTargetId().equals(getSourceId());
}
-
+
@Override
public CoffinQueenDelayedTriggeredAbility copy() {
return new CoffinQueenDelayedTriggeredAbility(this);
}
-
+
@Override
public String getRule() {
- return "When {this} becomes untapped or you lose control of {this}, exile that creature";
+ return "When {this} becomes untapped or you lose control of {this}, exile that creature.";
}
}
diff --git a/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java b/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java
index b24a933ae8b..5ea158c1f41 100644
--- a/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java
+++ b/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java
@@ -81,7 +81,7 @@ public class ConduitOfRuin extends CardImpl {
// The first creature spell you cast each turn costs {2} less to cast.
Effect effect = new SpellsCostReductionControllerEffect(filterCost, 2);
- effect.setText("The first creature spell you cast each turn costs {2} less to cast");
+ effect.setText("The first creature spell you cast each turn costs {2} less to cast.");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new ConduitOfRuinWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/c/Conflagrate.java b/Mage.Sets/src/mage/cards/c/Conflagrate.java
index 11e5cf6b274..70289727353 100644
--- a/Mage.Sets/src/mage/cards/c/Conflagrate.java
+++ b/Mage.Sets/src/mage/cards/c/Conflagrate.java
@@ -30,7 +30,6 @@ package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
-import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.costs.common.DiscardXTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.DynamicValue;
@@ -82,8 +81,8 @@ class ConflagrateVariableValue implements DynamicValue {
public int calculate(Game game, Ability sourceAbility, Effect effect) {
int xValue = sourceAbility.getManaCostsToPay().getX();
for (Cost cost : sourceAbility.getCosts()) {
- if (cost instanceof DiscardTargetCost) {
- xValue = ((DiscardTargetCost) cost).getCards().size();
+ if (cost instanceof DiscardXTargetCost) {
+ xValue = ((DiscardXTargetCost) cost).getAmount();
}
}
return xValue;
diff --git a/Mage.Sets/src/mage/cards/c/CruelFate.java b/Mage.Sets/src/mage/cards/c/CruelFate.java
new file mode 100644
index 00000000000..ce16987c8f5
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/CruelFate.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.c;
+
+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.cards.Cards;
+import mage.cards.CardsImpl;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.TargetCard;
+import mage.target.common.TargetOpponent;
+
+/**
+ *
+ * @author TheElk801 & L_J
+ */
+public class CruelFate extends CardImpl {
+
+ public CruelFate(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U}");
+
+ // Look at the top five cards of target opponent's library. Put one of those cards into that player's graveyard and the rest on top of his or her library in any order.
+ this.getSpellAbility().addEffect(new CruelFateEffect());
+ this.getSpellAbility().addTarget(new TargetOpponent());
+
+ }
+
+ public CruelFate(final CruelFate card) {
+ super(card);
+ }
+
+ @Override
+ public CruelFate copy() {
+ return new CruelFate(this);
+ }
+}
+
+class CruelFateEffect extends OneShotEffect {
+
+ public CruelFateEffect() {
+ super(Outcome.DrawCard);
+ this.staticText = "Look at the top five cards of target opponent's library. Put one of those cards into that player's graveyard and the rest on top of his or her library in any order";
+ }
+
+ public CruelFateEffect(final CruelFateEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public CruelFateEffect copy() {
+ return new CruelFateEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Card sourceCard = game.getCard(source.getSourceId());
+ if (sourceCard != null) {
+ Player you = game.getPlayer(source.getControllerId());
+ Player player = game.getPlayer(source.getFirstTarget());
+ if (player != null && you != null) {
+ Cards cards = new CardsImpl();
+ int count = Math.min(player.getLibrary().size(), 5);
+ for (int i = 0; i < count; i++) {
+ Card card = player.getLibrary().removeFromTop(game);
+ if (card != null) {
+ cards.add(card);
+ }
+ }
+
+ you.lookAtCards(sourceCard.getIdName(), cards, game);
+
+ // card to put into opponent's graveyard
+ TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCard("card to put into target opponent's graveyard"));
+ if (player.canRespond()) {
+ if (cards.size() > 1) {
+ you.choose(Outcome.Detriment, cards, target, game);
+ Card card = cards.get(target.getFirstTarget(), game);
+ if (card != null) {
+ cards.remove(card);
+ card.moveToZone(Zone.GRAVEYARD, source.getSourceId(), game, true);
+ }
+ }
+ else if (cards.size() == 1) {
+ Card card = cards.get(cards.iterator().next(), game);
+ card.moveToZone(Zone.GRAVEYARD, source.getSourceId(), game, true);
+ }
+ }
+ // cards to put on the top of opponent's library
+ TargetCard target2 = new TargetCard(Zone.LIBRARY, new FilterCard("card to put on the top of target opponent's library"));
+ while (player.canRespond() && cards.size() > 1) {
+ you.choose(Outcome.Neutral, cards, target2, game);
+ Card card = cards.get(target2.getFirstTarget(), game);
+ if (card != null) {
+ cards.remove(card);
+ card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
+ }
+ target2.clearChosen();
+ }
+ if (cards.size() == 1) {
+ Card card = cards.get(cards.iterator().next(), game);
+ card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/d/DeepWood.java b/Mage.Sets/src/mage/cards/d/DeepWood.java
new file mode 100644
index 00000000000..bb1d3a14051
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/d/DeepWood.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.d;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
+import mage.abilities.condition.common.AttackedThisStepCondition;
+import mage.abilities.effects.PreventionEffectImpl;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.PhaseStep;
+import mage.constants.TurnPhase;
+import mage.filter.common.FilterAttackingCreature;
+import mage.game.Game;
+import mage.game.events.DamagePlayerEvent;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.watchers.common.PlayerAttackedStepWatcher;
+
+/**
+ *
+ * @author L_J
+ */
+public class DeepWood extends CardImpl {
+
+ public DeepWood(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}");
+
+ // Cast Deep Wood only during the declare attackers step and only if you've been attacked this step.
+ Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
+ TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
+ "Cast {this} only during the declare attackers step and only if you've been attacked this step."
+ );
+ ability.addWatcher(new PlayerAttackedStepWatcher());
+ this.addAbility(ability);
+
+ // Prevent all damage that would be dealt to you this turn by attacking creatures.
+ this.getSpellAbility().addEffect(new DeepWoodEffect());
+ }
+
+ public DeepWood(final DeepWood card) {
+ super(card);
+ }
+
+ @Override
+ public DeepWood copy() {
+ return new DeepWood(this);
+ }
+}
+
+class DeepWoodEffect extends PreventionEffectImpl {
+
+ private static final FilterAttackingCreature filter = new FilterAttackingCreature();
+
+ DeepWoodEffect() {
+ super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
+ staticText = "Prevent all damage that would be dealt to you this turn by attacking creatures";
+ }
+
+ DeepWoodEffect(final DeepWoodEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public DeepWoodEffect copy() {
+ return new DeepWoodEffect(this);
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (super.applies(event, source, game) && event instanceof DamagePlayerEvent && event.getAmount() > 0) {
+ DamagePlayerEvent damageEvent = (DamagePlayerEvent) event;
+ if (event.getTargetId().equals(source.getControllerId())) {
+ Permanent permanent = game.getPermanentOrLKIBattlefield(damageEvent.getSourceId());
+ if (permanent != null && filter.match(permanent, game)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/d/DefiantVanguard.java b/Mage.Sets/src/mage/cards/d/DefiantVanguard.java
index 3b28b8d6dc4..0a5c3decb5f 100644
--- a/Mage.Sets/src/mage/cards/d/DefiantVanguard.java
+++ b/Mage.Sets/src/mage/cards/d/DefiantVanguard.java
@@ -124,7 +124,7 @@ class DefiantVanguardEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- Permanent thisCreature = game.getPermanentOrLKIBattlefield(source.getId());
+ Permanent thisCreature = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (controller != null && thisCreature != null) {
BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName());
if (watcher != null) {
@@ -136,10 +136,10 @@ class DefiantVanguardEffect extends OneShotEffect {
}
}
}
+ thisCreature.destroy(source.getSourceId(), game, false);
for (Permanent creature : toDestroy) {
creature.destroy(source.getSourceId(), game, false);
}
- thisCreature.destroy(source.getSourceId(), game, false);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DiamondKaleidoscope.java b/Mage.Sets/src/mage/cards/d/DiamondKaleidoscope.java
index 1676e4475b2..53d804be964 100644
--- a/Mage.Sets/src/mage/cards/d/DiamondKaleidoscope.java
+++ b/Mage.Sets/src/mage/cards/d/DiamondKaleidoscope.java
@@ -68,8 +68,7 @@ public class DiamondKaleidoscope extends CardImpl {
this.addAbility(ability);
// Sacrifice a Prism token: Add one mana of any color to your mana pool.
- ability = new AnyColorManaAbility();
- ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
+ ability = new AnyColorManaAbility(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/d/DinosaurHunter.java b/Mage.Sets/src/mage/cards/d/DinosaurHunter.java
index 9711eb8b515..3e763804225 100644
--- a/Mage.Sets/src/mage/cards/d/DinosaurHunter.java
+++ b/Mage.Sets/src/mage/cards/d/DinosaurHunter.java
@@ -28,17 +28,14 @@
package mage.cards.d;
import java.util.UUID;
-
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
-import mage.filter.common.*;
-import mage.filter.predicate.mageobject.SubtypePredicate;
-import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
+import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
@@ -48,12 +45,6 @@ import mage.target.targetpointer.FixedTarget;
*/
public class DinosaurHunter extends CardImpl {
- private static final FilterControlledCreaturePermanent filterAnotherDino = new FilterControlledCreaturePermanent();
- static {
- filterAnotherDino.add(new AnotherPredicate());
- filterAnotherDino.add(new SubtypePredicate(SubType.DINOSAUR));
- }
-
public DinosaurHunter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
@@ -78,11 +69,6 @@ public class DinosaurHunter extends CardImpl {
class DinosaurHunterAbility extends TriggeredAbilityImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
- static {
- filter.add(new SubtypePredicate(SubType.DINOSAUR));
- }
-
DinosaurHunterAbility() {
super(Zone.BATTLEFIELD, new DestroyTargetEffect());
}
@@ -103,11 +89,13 @@ class DinosaurHunterAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- Permanent sourcePermanet = game.getPermanent(event.getSourceId());
- Permanent targetPermanet = game.getPermanent(event.getTargetId());
- if (sourcePermanet != null && targetPermanet != null && event.getSourceId().equals(sourceId) && filter.match(targetPermanet, game)) {
- getEffects().get(0).setTargetPointer(new FixedTarget(event.getTargetId()));
- return true;
+ if (((DamageEvent) event).isCombatDamage()
+ && event.getSourceId().equals(getSourceId())) {
+ Permanent targetPermanet = game.getPermanentOrLKIBattlefield(event.getTargetId());
+ if (targetPermanet.hasSubtype(SubType.DINOSAUR, game)) {
+ getEffects().get(0).setTargetPointer(new FixedTarget(targetPermanet, game));
+ return true;
+ }
}
return false;
}
@@ -116,4 +104,4 @@ class DinosaurHunterAbility extends TriggeredAbilityImpl {
public String getRule() {
return "Whenever {this} deals combat damage to a Dinosaur, destroy that creature.";
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/d/DjinnIlluminatus.java b/Mage.Sets/src/mage/cards/d/DjinnIlluminatus.java
index 94c30a7febe..4eb5d4f1f04 100644
--- a/Mage.Sets/src/mage/cards/d/DjinnIlluminatus.java
+++ b/Mage.Sets/src/mage/cards/d/DjinnIlluminatus.java
@@ -108,7 +108,8 @@ class DjinnIlluminatusGainReplicateEffect extends ContinuousEffectImpl {
if ((stackObject instanceof Spell)
&& !stackObject.isCopy()
&& stackObject.getControllerId().equals(source.getControllerId())
- && djinn.getControllerId().equals(source.getControllerId())) { // verify that the controller of the djinn cast that spell
+ && djinn.getControllerId().equals(source.getControllerId()) // verify that the controller of the djinn cast that spell
+ && !stackObject.getManaCost().isEmpty()) { //handle cases like Ancestral Vision
Spell spell = (Spell) stackObject;
if (filter.match(stackObject, game)) {
ReplicateAbility replicateAbility = replicateAbilities.computeIfAbsent(spell.getId(), k -> new ReplicateAbility(spell.getCard(), spell.getSpellAbility().getManaCosts().getText()));
diff --git a/Mage.Sets/src/mage/cards/d/DreadCharge.java b/Mage.Sets/src/mage/cards/d/DreadCharge.java
new file mode 100644
index 00000000000..e7c8819cbf9
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/d/DreadCharge.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.d;
+
+import java.util.UUID;
+import mage.ObjectColor;
+import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesAllEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.TargetController;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.ColorPredicate;
+import mage.filter.predicate.permanent.ControllerPredicate;
+
+/**
+ *
+ * @author L_J
+ */
+public class DreadCharge extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Black creatures you control");
+ private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("except by black creatures");
+
+ static {
+ filter.add(new ColorPredicate(ObjectColor.BLACK));
+ filter2.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK)));
+ filter.add(new ControllerPredicate(TargetController.YOU));
+ }
+
+ public DreadCharge(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}");
+
+ // Black creatures you control can't be blocked this turn except by black creatures.
+ this.getSpellAbility().addEffect(new CantBeBlockedByCreaturesAllEffect(filter, filter2, Duration.EndOfTurn));
+ }
+
+ public DreadCharge(final DreadCharge card) {
+ super(card);
+ }
+
+ @Override
+ public DreadCharge copy() {
+ return new DreadCharge(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/d/DreamThief.java b/Mage.Sets/src/mage/cards/d/DreamThief.java
index 79338e861ce..d8d5364b3f8 100644
--- a/Mage.Sets/src/mage/cards/d/DreamThief.java
+++ b/Mage.Sets/src/mage/cards/d/DreamThief.java
@@ -27,6 +27,7 @@
*/
package mage.cards.d;
+import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
@@ -52,7 +53,7 @@ public class DreamThief extends CardImpl {
private static final String rule = "draw a card if you've cast another blue spell this turn";
public DreamThief(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.FAERIE);
this.subtype.add(SubType.ROGUE);
@@ -84,9 +85,12 @@ class CastBlueSpellThisTurnCondition implements Condition {
public boolean apply(Game game, Ability source) {
SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getSimpleName());
if (watcher != null) {
- for (Spell spell : watcher.getSpellsCastThisTurn(source.getControllerId())) {
- if (!spell.getSourceId().equals(source.getSourceId()) && spell.getColor(game).isBlue()) {
- return true;
+ List spells = watcher.getSpellsCastThisTurn(source.getControllerId());
+ if (spells != null) {
+ for (Spell spell : spells) {
+ if (!spell.getSourceId().equals(source.getSourceId()) && spell.getColor(game).isBlue()) {
+ return true;
+ }
}
}
}
diff --git a/Mage.Sets/src/mage/cards/e/EunuchsIntrigues.java b/Mage.Sets/src/mage/cards/e/EunuchsIntrigues.java
new file mode 100644
index 00000000000..7592c517448
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/e/EunuchsIntrigues.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.e;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.RestrictionEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.permanent.ControllerIdPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.Target;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetOpponent;
+
+/**
+ *
+ * @author TheElk801 & L_J
+ */
+public class EunuchsIntrigues extends CardImpl {
+
+ public EunuchsIntrigues(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
+
+ // Target opponent chooses a creature he or she controls. Other creatures he or she controls can't block this turn.
+ this.getSpellAbility().addEffect(new EunuchsIntriguesEffect());
+ this.getSpellAbility().addTarget(new TargetOpponent());
+ }
+
+ public EunuchsIntrigues(final EunuchsIntrigues card) {
+ super(card);
+ }
+
+ @Override
+ public EunuchsIntrigues copy() {
+ return new EunuchsIntrigues(this);
+ }
+}
+
+class EunuchsIntriguesEffect extends OneShotEffect {
+
+ EunuchsIntriguesEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "Target opponent chooses a creature he or she controls. Other creatures he or she controls can't block this turn.";
+ }
+
+ EunuchsIntriguesEffect(final EunuchsIntriguesEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public EunuchsIntriguesEffect copy() {
+ return new EunuchsIntriguesEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getFirstTarget());
+ if (player == null) {
+ return false;
+ }
+ FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control");
+ filter.add(new ControllerIdPredicate(player.getId()));
+ Target target = new TargetPermanent(1, 1, filter, true);
+ if (target.canChoose(source.getSourceId(), player.getId(), game)) {
+ while (!target.isChosen() && target.canChoose(player.getId(), game) && player.canRespond()) {
+ player.chooseTarget(Outcome.DestroyPermanent, target, source, game);
+ }
+ Permanent permanent = game.getPermanent(target.getFirstTarget());
+ if (permanent != null) {
+ game.informPlayers(player.getLogName() + " has chosen " + permanent.getLogName() + " as his only creature able to block this turn");
+ }
+ }
+ game.addEffect(new EunuchsIntriguesRestrictionEffect(target.getFirstTarget()), source);
+ return true;
+ }
+}
+
+class EunuchsIntriguesRestrictionEffect extends RestrictionEffect {
+
+ protected UUID targetId;
+
+ public EunuchsIntriguesRestrictionEffect(UUID targetId) {
+ super(Duration.EndOfTurn);
+ this.targetId = targetId;
+ }
+
+ public EunuchsIntriguesRestrictionEffect(final EunuchsIntriguesRestrictionEffect effect) {
+ super(effect);
+ targetId = effect.targetId;
+ }
+
+ @Override
+ public EunuchsIntriguesRestrictionEffect copy() {
+ return new EunuchsIntriguesRestrictionEffect(this);
+ }
+
+ @Override
+ public boolean applies(Permanent permanent, Ability source, Game game) {
+ if (permanent.getControllerId().equals(source.getFirstTarget())) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) {
+ if (targetId != null && blocker.getId().equals(targetId)) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/e/ExaltedDragon.java b/Mage.Sets/src/mage/cards/e/ExaltedDragon.java
index 55ee01bf792..941f15b0e4c 100644
--- a/Mage.Sets/src/mage/cards/e/ExaltedDragon.java
+++ b/Mage.Sets/src/mage/cards/e/ExaltedDragon.java
@@ -80,7 +80,7 @@ class ExaltedDragonCostToAttackBlockEffect extends PayCostToAttackBlockEffectImp
ExaltedDragonCostToAttackBlockEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.ATTACK,
new SacrificeTargetCost(new TargetControlledPermanent(new FilterControlledLandPermanent("a land"))));
- staticText = "{this} can't attack unless you sacrifice a land (This cost is paid as attackers are declared.)";
+ staticText = "{this} can't attack unless you sacrifice a land. (This cost is paid as attackers are declared.)";
}
ExaltedDragonCostToAttackBlockEffect(ExaltedDragonCostToAttackBlockEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/e/EyeForAnEye.java b/Mage.Sets/src/mage/cards/e/EyeForAnEye.java
index 08245b25ab3..9c62933fbf9 100644
--- a/Mage.Sets/src/mage/cards/e/EyeForAnEye.java
+++ b/Mage.Sets/src/mage/cards/e/EyeForAnEye.java
@@ -28,24 +28,22 @@
package mage.cards.e;
import java.util.UUID;
-import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.TriggeredAbilityImpl;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.Duration;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
+import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.players.Player;
-import mage.target.targetpointer.FixedTarget;
+import mage.target.TargetSource;
/**
- *
- * @author MarcoMarin
+ *
+ * @author L_J
*/
public class EyeForAnEye extends CardImpl {
@@ -53,8 +51,7 @@ public class EyeForAnEye extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}{W}");
// The next time a source of your choice would deal damage to you this turn, instead that source deals that much damage to you and Eye for an Eye deals that much damage to that source's controller.
- this.addAbility(new EyeForAnEyeTriggeredAbility(new EyeForAnEyeEffect()));
-
+ this.getSpellAbility().addEffect(new EyeForAnEyeEffect());
}
public EyeForAnEye(final EyeForAnEye card) {
@@ -67,48 +64,19 @@ public class EyeForAnEye extends CardImpl {
}
}
-class EyeForAnEyeTriggeredAbility extends TriggeredAbilityImpl {
+class EyeForAnEyeEffect extends ReplacementEffectImpl {
- public EyeForAnEyeTriggeredAbility(Effect effect) {
- super(Zone.BATTLEFIELD, effect);
- }
-
- public EyeForAnEyeTriggeredAbility(final EyeForAnEyeTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public EyeForAnEyeTriggeredAbility copy() {
- return new EyeForAnEyeTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- MageObject sourceObject = game.getObject(event.getSourceId());
- this.getEffects().get(0).setValue("damageAmount", event.getAmount());
- this.getEffects().get(0).setTargetPointer(new FixedTarget(game.getControllerId(sourceObject.getId())));
- return true;
- }
-
- @Override
- public String getRule() {
- return "The next time a source of your choice would deal damage to you this turn, instead that source deals that much damage to you and {this} deals that much damage to that source's controller.";
- }
-}
-
-class EyeForAnEyeEffect extends OneShotEffect {
+ private final TargetSource damageSource;
public EyeForAnEyeEffect() {
- super(Outcome.Damage);
+ super(Duration.EndOfTurn, Outcome.RedirectDamage);
+ staticText = "The next time a source of your choice would deal damage to you this turn, instead that source deals that much damage to you and {this} deals that much damage to that source's controller";
+ this.damageSource = new TargetSource();
}
public EyeForAnEyeEffect(final EyeForAnEyeEffect effect) {
super(effect);
+ this.damageSource = effect.damageSource.copy();
}
@Override
@@ -116,15 +84,48 @@ class EyeForAnEyeEffect extends OneShotEffect {
return new EyeForAnEyeEffect(this);
}
+ @Override
+ public void init(Ability source, Game game) {
+ this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
+ super.init(source, game);
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
+ }
+
@Override
public boolean apply(Game game, Ability source) {
- Integer damageAmount = (Integer) this.getValue("damageAmount");
- UUID targetId = this.targetPointer.getFirst(game, source);
- if (damageAmount != null && targetId != null) {
- Player player = game.getPlayer(targetId);
- if (player != null) {
- player.damage(damageAmount, targetId, game, false, true);
+ return true;
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ Player controller = game.getPlayer(source.getControllerId());
+ DamageEvent damageEvent = (DamageEvent) event;
+ if (controller != null) {
+ controller.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects());
+ UUID sourceControllerId = game.getControllerId(damageEvent.getSourceId());
+ if (sourceControllerId != null) {
+ Player sourceController = game.getPlayer(sourceControllerId);
+ if (sourceController != null) {
+ sourceController.damage(damageEvent.getAmount(), source.getSourceId(), game, false, true);
return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ Player controller = game.getPlayer(source.getControllerId());
+ DamageEvent damageEvent = (DamageEvent) event;
+ if (controller != null) {
+ if (controller.getId() == damageEvent.getTargetId() && damageEvent.getSourceId().equals(damageSource.getFirstTarget())) {
+ this.discard();
+ return true;
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/f/FalseOrders.java b/Mage.Sets/src/mage/cards/f/FalseOrders.java
index 8d35c683fa5..c2dccd0b35e 100644
--- a/Mage.Sets/src/mage/cards/f/FalseOrders.java
+++ b/Mage.Sets/src/mage/cards/f/FalseOrders.java
@@ -175,20 +175,41 @@ class FalseOrdersUnblockEffect extends OneShotEffect {
// Relevant ruling for Balduvian Warlord:
// 7/15/2006 If an attacking creature has an ability that triggers “When this creature becomes blocked,”
// it triggers when a creature blocks it due to the Warlord’s ability only if it was unblocked at that point.
-
boolean notYetBlocked = chosenGroup.getBlockers().isEmpty();
- chosenGroup.addBlocker(permanent.getId(), controller.getId(), game);
+ chosenGroup.addBlockerToGroup(permanent.getId(), controller.getId(), game);
+ game.getCombat().addBlockingGroup(permanent.getId(), chosenPermanent.getId(), controller.getId(), game); // 702.21h
if (notYetBlocked) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, chosenPermanent.getId(), null));
+ for (UUID bandedId : chosenPermanent.getBandedCards()) {
+ CombatGroup bandedGroup = game.getCombat().findGroup(bandedId);
+ if (bandedGroup != null && chosenGroup.getBlockers().size() == 1) {
+ game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, bandedId, null));
+ }
+ }
}
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, chosenPermanent.getId(), permanent.getId(), permanent.getControllerId()));
}
+ CombatGroup blockGroup = findBlockingGroup(permanent, game); // a new blockingGroup is formed, so it's necessary to find it again
+ if (blockGroup != null) {
+ blockGroup.pickAttackerOrder(permanent.getControllerId(), game);
+ }
}
}
- }
+ }
return true;
}
}
return false;
}
+
+ private CombatGroup findBlockingGroup(Permanent blocker, Game game) {
+ if (game.getCombat().blockingGroupsContains(blocker.getId())) { // if (blocker.getBlocking() > 1) {
+ for (CombatGroup group : game.getCombat().getBlockingGroups()) {
+ if (group.getBlockers().contains(blocker.getId())) {
+ return group;
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/Mage.Sets/src/mage/cards/f/Foreshadow.java b/Mage.Sets/src/mage/cards/f/Foreshadow.java
new file mode 100644
index 00000000000..54db6503045
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/f/Foreshadow.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.f;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.NameACardEffect;
+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.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetOpponent;
+
+/**
+ *
+ * @author Quercitron & L_J
+ */
+public class Foreshadow extends CardImpl {
+
+ public Foreshadow(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
+
+ // Choose a card name, then target opponent puts the top card of his or her library into his or her graveyard. If that card has the chosen name, you draw a card.
+ this.getSpellAbility().addEffect(new NameACardEffect(NameACardEffect.TypeOfName.ALL));
+ this.getSpellAbility().addEffect(new ForeshadowEffect());
+ this.getSpellAbility().addTarget(new TargetOpponent());
+
+ // Draw a card at the beginning of the next turn's upkeep.
+ this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
+ new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1)), false));
+ }
+
+ public Foreshadow(final Foreshadow card) {
+ super(card);
+ }
+
+ @Override
+ public Foreshadow copy() {
+ return new Foreshadow(this);
+ }
+}
+
+class ForeshadowEffect extends OneShotEffect {
+
+ public ForeshadowEffect() {
+ super(Outcome.DrawCard);
+ this.staticText = ", then target opponent puts the top card of his or her library into his or her graveyard. If that card has the chosen name, you draw a card";
+ }
+
+ public ForeshadowEffect(final ForeshadowEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ForeshadowEffect copy() {
+ return new ForeshadowEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ Player targetPlayer = game.getPlayer(source.getFirstTarget());
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
+ if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) {
+ Card card = targetPlayer.getLibrary().getFromTop(game);
+ if (card != null) {
+ controller.moveCards(card, Zone.GRAVEYARD, source, game);
+ if (card.getName().equals(cardName)) {
+ controller.drawCards(1, game);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java b/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java
index ca7d2159fdc..33c2702a8bd 100644
--- a/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java
+++ b/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java
@@ -27,10 +27,13 @@
*/
package mage.cards.g;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.RegenerateTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -43,10 +46,6 @@ import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.BlockedAttackerWatcher;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
/**
*
* @author LevelX2
@@ -60,8 +59,7 @@ public class GazeOfTheGorgon extends CardImpl {
// Regenerate target creature. At end of combat, destroy all creatures that blocked or were blocked by that creature this turn.
this.getSpellAbility().addEffect(new RegenerateTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
- this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
- new AtTheEndOfCombatDelayedTriggeredAbility(new GazeOfTheGorgonEffect())));
+ this.getSpellAbility().addEffect(new GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect());
this.getSpellAbility().addWatcher(new BlockedAttackerWatcher());
}
@@ -75,15 +73,46 @@ public class GazeOfTheGorgon extends CardImpl {
}
}
-class GazeOfTheGorgonEffect extends OneShotEffect {
+class GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect extends OneShotEffect {
- public GazeOfTheGorgonEffect() {
+ public GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "At this turn's next end of combat, destroy all creatures that blocked or were blocked by it this turn";
+ }
+
+ public GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect(final GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect copy() {
+ return new GazeOfTheGorgonCreateDelayedTriggeredAbilityEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ if (!source.getTargets().isEmpty() && source.getFirstTarget() != null) {
+ MageObjectReference mor = new MageObjectReference(source.getFirstTarget(), game);
+ AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new GazeOfTheGorgonEffect(mor));
+ game.addDelayedTriggeredAbility(delayedAbility, source);
+ return true;
+ }
+ return false;
+ }
+}
+
+class GazeOfTheGorgonEffect extends OneShotEffect {
+
+ MageObjectReference targetCreature;
+
+ public GazeOfTheGorgonEffect(MageObjectReference targetCreature) {
super(Outcome.DestroyPermanent);
- this.staticText = "destroy all creatures that blocked or were blocked by that creature this turn";
+ this.targetCreature = targetCreature;
}
public GazeOfTheGorgonEffect(final GazeOfTheGorgonEffect effect) {
super(effect);
+ targetCreature = effect.targetCreature;
}
@Override
@@ -94,14 +123,13 @@ class GazeOfTheGorgonEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- Permanent targetCreature = game.getPermanentOrLKIBattlefield(source.getTargets().getFirstTarget());
if (controller != null && targetCreature != null) {
BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName());
if (watcher != null) {
List toDestroy = new ArrayList<>();
for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) {
- if (!creature.getId().equals(targetCreature.getId())) {
- if (watcher.creatureHasBlockedAttacker(creature, targetCreature, game) || watcher.creatureHasBlockedAttacker(targetCreature, creature, game)) {
+ if (!creature.getId().equals(targetCreature.getSourceId())) {
+ if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature, game) || watcher.creatureHasBlockedAttacker(targetCreature, new MageObjectReference(creature, game), game)) {
toDestroy.add(creature);
}
}
diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java b/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java
new file mode 100644
index 00000000000..748661c0a08
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.g;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import mage.MageObjectReference;
+import mage.abilities.Ability;
+import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.InfoEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Outcome;
+import mage.filter.StaticFilters;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.SubtypePredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.common.TargetCreaturePermanent;
+import mage.watchers.common.BlockedAttackerWatcher;
+
+/**
+ *
+ * @author LevelX2 & L_J
+ */
+public class GlyphOfDoom extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Wall creature");
+
+ static {
+ filter.add(new SubtypePredicate(SubType.WALL));
+ }
+
+ public GlyphOfDoom(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
+
+ // Choose target Wall creature. At this turn's next end of combat, destroy all creatures that were blocked by that creature this turn.
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
+ this.getSpellAbility().addEffect(new InfoEffect("Choose target Wall creature"));
+ this.getSpellAbility().addEffect(new GlyphOfDoomCreateDelayedTriggeredAbilityEffect());
+ this.getSpellAbility().addWatcher(new BlockedAttackerWatcher());
+ }
+
+ public GlyphOfDoom(final GlyphOfDoom card) {
+ super(card);
+ }
+
+ @Override
+ public GlyphOfDoom copy() {
+ return new GlyphOfDoom(this);
+ }
+}
+
+class GlyphOfDoomCreateDelayedTriggeredAbilityEffect extends OneShotEffect {
+
+ public GlyphOfDoomCreateDelayedTriggeredAbilityEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "At this turn's next end of combat, destroy all creatures that were blocked by that creature this turn";
+ }
+
+ public GlyphOfDoomCreateDelayedTriggeredAbilityEffect(final GlyphOfDoomCreateDelayedTriggeredAbilityEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public GlyphOfDoomCreateDelayedTriggeredAbilityEffect copy() {
+ return new GlyphOfDoomCreateDelayedTriggeredAbilityEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ if (!source.getTargets().isEmpty() && source.getFirstTarget() != null) {
+ MageObjectReference mor = new MageObjectReference(source.getFirstTarget(), game);
+ AtTheEndOfCombatDelayedTriggeredAbility delayedAbility = new AtTheEndOfCombatDelayedTriggeredAbility(new GlyphOfDoomEffect(mor));
+ game.addDelayedTriggeredAbility(delayedAbility, source);
+ return true;
+ }
+ return false;
+ }
+}
+
+class GlyphOfDoomEffect extends OneShotEffect {
+
+ MageObjectReference targetCreature;
+
+ public GlyphOfDoomEffect(MageObjectReference targetCreature) {
+ super(Outcome.DestroyPermanent);
+ this.targetCreature = targetCreature;
+ }
+
+ public GlyphOfDoomEffect(final GlyphOfDoomEffect effect) {
+ super(effect);
+ targetCreature = effect.targetCreature;
+ }
+
+ @Override
+ public GlyphOfDoomEffect copy() {
+ return new GlyphOfDoomEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null && targetCreature != null) {
+ BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get(BlockedAttackerWatcher.class.getSimpleName());
+ if (watcher != null) {
+ List toDestroy = new ArrayList<>();
+ for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) {
+ if (!creature.getId().equals(targetCreature.getSourceId())) {
+ if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature, game)) {
+ toDestroy.add(creature);
+ }
+ }
+ }
+ for (Permanent creature : toDestroy) {
+ creature.destroy(source.getSourceId(), game, false);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GoblinWarCry.java b/Mage.Sets/src/mage/cards/g/GoblinWarCry.java
new file mode 100644
index 00000000000..a1d6a1939af
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GoblinWarCry.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.g;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.RestrictionEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.permanent.ControllerIdPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.Target;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetOpponent;
+
+/**
+ *
+ * @author TheElk801 & L_J
+ */
+public class GoblinWarCry extends CardImpl {
+
+ public GoblinWarCry(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
+
+ // Target opponent chooses a creature he or she controls. Other creatures he or she controls can't block this turn.
+ this.getSpellAbility().addEffect(new GoblinWarCryEffect());
+ this.getSpellAbility().addTarget(new TargetOpponent());
+ }
+
+ public GoblinWarCry(final GoblinWarCry card) {
+ super(card);
+ }
+
+ @Override
+ public GoblinWarCry copy() {
+ return new GoblinWarCry(this);
+ }
+}
+
+class GoblinWarCryEffect extends OneShotEffect {
+
+ GoblinWarCryEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "Target opponent chooses a creature he or she controls. Other creatures he or she controls can't block this turn.";
+ }
+
+ GoblinWarCryEffect(final GoblinWarCryEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public GoblinWarCryEffect copy() {
+ return new GoblinWarCryEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getFirstTarget());
+ if (player == null) {
+ return false;
+ }
+ FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control");
+ filter.add(new ControllerIdPredicate(player.getId()));
+ Target target = new TargetPermanent(1, 1, filter, true);
+ if (target.canChoose(source.getSourceId(), player.getId(), game)) {
+ while (!target.isChosen() && target.canChoose(player.getId(), game) && player.canRespond()) {
+ player.chooseTarget(Outcome.DestroyPermanent, target, source, game);
+ }
+ Permanent permanent = game.getPermanent(target.getFirstTarget());
+ if (permanent != null) {
+ game.informPlayers(player.getLogName() + " has chosen " + permanent.getLogName() + " as his only creature able to block this turn");
+ }
+ }
+ game.addEffect(new GoblinWarCryRestrictionEffect(target.getFirstTarget()), source);
+ return true;
+ }
+}
+
+class GoblinWarCryRestrictionEffect extends RestrictionEffect {
+
+ protected UUID targetId;
+
+ public GoblinWarCryRestrictionEffect(UUID targetId) {
+ super(Duration.EndOfTurn);
+ this.targetId = targetId;
+ }
+
+ public GoblinWarCryRestrictionEffect(final GoblinWarCryRestrictionEffect effect) {
+ super(effect);
+ targetId = effect.targetId;
+ }
+
+ @Override
+ public GoblinWarCryRestrictionEffect copy() {
+ return new GoblinWarCryRestrictionEffect(this);
+ }
+
+ @Override
+ public boolean applies(Permanent permanent, Ability source, Game game) {
+ if (permanent.getControllerId().equals(source.getFirstTarget())) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) {
+ if (targetId != null && blocker.getId().equals(targetId)) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HarshJustice.java b/Mage.Sets/src/mage/cards/h/HarshJustice.java
new file mode 100644
index 00000000000..bfbf9c70af7
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/HarshJustice.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.h;
+
+import java.util.UUID;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.DelayedTriggeredAbility;
+import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
+import mage.abilities.condition.common.AttackedThisStepCondition;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.PhaseStep;
+import mage.constants.TurnPhase;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.permanent.AttackingPredicate;
+import mage.game.Game;
+import mage.game.events.DamagedPlayerEvent;
+import mage.game.events.GameEvent;
+import mage.game.events.GameEvent.EventType;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.watchers.common.PlayerAttackedStepWatcher;
+
+/**
+ *
+ * @author LevelX2 & L_J
+ */
+public class HarshJustice extends CardImpl {
+
+ public HarshJustice(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
+
+ // Cast Harsh Justice only during the declare attackers step and only if you've been attacked this step.
+ Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
+ TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
+ "Cast {this} only during the declare attackers step and only if you've been attacked this step."
+ );
+ ability.addWatcher(new PlayerAttackedStepWatcher());
+ this.addAbility(ability);
+
+ // This turn, whenever an attacking creature deals combat damage to you, it deals that much damage to its controller.
+ this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new HarshJusticeTriggeredAbility()));
+ }
+
+ public HarshJustice(final HarshJustice card) {
+ super(card);
+ }
+
+ @Override
+ public HarshJustice copy() {
+ return new HarshJustice(this);
+ }
+}
+
+class HarshJusticeTriggeredAbility extends DelayedTriggeredAbility {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature");
+
+ static {
+ filter.add(new AttackingPredicate());
+ }
+
+ public HarshJusticeTriggeredAbility() {
+ super(new HarshJusticeEffect(), Duration.EndOfTurn, false);
+ }
+
+ public HarshJusticeTriggeredAbility(final HarshJusticeTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public HarshJusticeTriggeredAbility copy() {
+ return new HarshJusticeTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.DAMAGED_PLAYER;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ Player controller = game.getPlayer(this.getControllerId());
+ DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event;
+ Permanent damagePermanent = game.getPermanentOrLKIBattlefield(damageEvent.getSourceId());
+ if (controller != null && damagePermanent != null) {
+ if (damageEvent.isCombatDamage() && controller.getId().equals(damageEvent.getTargetId()) && filter.match(damagePermanent, game)) {
+ for (Effect effect : this.getEffects()) {
+ effect.setValue("damage", damageEvent.getAmount());
+ effect.setValue("sourceId", damageEvent.getSourceId());
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "This turn, whenever an attacking creature deals combat damage to you, " + super.getRule();
+ }
+}
+
+class HarshJusticeEffect extends OneShotEffect {
+
+ public HarshJusticeEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "it deals that much damage to its controller";
+ }
+
+ public HarshJusticeEffect(final HarshJusticeEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public HarshJusticeEffect copy() {
+ return new HarshJusticeEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ int damage = (Integer) this.getValue("damage");
+ UUID sourceId = (UUID) this.getValue("sourceId");
+ MageObject sourceObject = game.getObject(source.getSourceId());
+ if (sourceObject != null && damage > 0 && sourceId != null) {
+ Permanent targetObject = game.getPermanentOrLKIBattlefield(sourceId);
+ if (targetObject != null) {
+ Player controller = game.getPlayer(targetObject.getControllerId());
+ if (controller != null) {
+ game.informPlayers(sourceObject.getLogName() + ": " + targetObject.getLogName() + " deals " + damage + " damage to " + controller.getLogName());
+ controller.damage(damage, sourceId, game, false, true);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HeavyFog.java b/Mage.Sets/src/mage/cards/h/HeavyFog.java
new file mode 100644
index 00000000000..e69e57ebf07
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/HeavyFog.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.h;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
+import mage.abilities.condition.common.AttackedThisStepCondition;
+import mage.abilities.effects.PreventionEffectImpl;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.PhaseStep;
+import mage.constants.TurnPhase;
+import mage.filter.common.FilterAttackingCreature;
+import mage.game.Game;
+import mage.game.events.DamagePlayerEvent;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.watchers.common.PlayerAttackedStepWatcher;
+
+/**
+ *
+ * @author L_J
+ */
+public class HeavyFog extends CardImpl {
+
+ public HeavyFog(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}");
+
+ // Cast Deep Wood only during the declare attackers step and only if you've been attacked this step.
+ Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
+ TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
+ "Cast {this} only during the declare attackers step and only if you've been attacked this step."
+ );
+ ability.addWatcher(new PlayerAttackedStepWatcher());
+ this.addAbility(ability);
+
+ // Prevent all damage that would be dealt to you this turn by attacking creatures.
+ this.getSpellAbility().addEffect(new HeavyFogEffect());
+ }
+
+ public HeavyFog(final HeavyFog card) {
+ super(card);
+ }
+
+ @Override
+ public HeavyFog copy() {
+ return new HeavyFog(this);
+ }
+}
+
+class HeavyFogEffect extends PreventionEffectImpl {
+
+ private static final FilterAttackingCreature filter = new FilterAttackingCreature();
+
+ HeavyFogEffect() {
+ super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
+ staticText = "Prevent all damage that would be dealt to you this turn by attacking creatures";
+ }
+
+ HeavyFogEffect(final HeavyFogEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public HeavyFogEffect copy() {
+ return new HeavyFogEffect(this);
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (super.applies(event, source, game) && event instanceof DamagePlayerEvent && event.getAmount() > 0) {
+ DamagePlayerEvent damageEvent = (DamagePlayerEvent) event;
+ if (event.getTargetId().equals(source.getControllerId())) {
+ Permanent permanent = game.getPermanentOrLKIBattlefield(damageEvent.getSourceId());
+ if (permanent != null && filter.match(permanent, game)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HellcarverDemon.java b/Mage.Sets/src/mage/cards/h/HellcarverDemon.java
index 1032ae1f699..af8462e4b7e 100644
--- a/Mage.Sets/src/mage/cards/h/HellcarverDemon.java
+++ b/Mage.Sets/src/mage/cards/h/HellcarverDemon.java
@@ -27,35 +27,34 @@
*/
package mage.cards.h;
+import java.util.HashSet;
import java.util.Objects;
+import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
-import mage.abilities.effects.AsThoughEffectImpl;
-import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
+import mage.filter.FilterCard;
import mage.filter.common.FilterControlledPermanent;
-import mage.filter.common.FilterNonlandCard;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
-import mage.target.common.TargetCardInExile;
-import mage.target.targetpointer.FixedTarget;
+import mage.target.TargetCard;
/**
*
- * @author jeffwadsworth
+ * @author jeffwadsworth & L_J
*/
public class HellcarverDemon extends CardImpl {
@@ -84,9 +83,6 @@ public class HellcarverDemon extends CardImpl {
class HellcarverDemonEffect extends OneShotEffect {
- private static final FilterControlledPermanent filterPermanents = new FilterControlledPermanent("Permanent");
- private static FilterNonlandCard filter = new FilterNonlandCard("nonland card exiled with Hellcarver Demon");
-
public HellcarverDemonEffect() {
super(Outcome.PlayForFree);
staticText = "sacrifice all other permanents you control and discard your hand. Exile the top six cards of your library. You may cast any number of nonland cards exiled this way without paying their mana costs.";
@@ -99,41 +95,43 @@ class HellcarverDemonEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- Permanent hellcarverDemon = game.getPermanent(source.getSourceId());
-
- for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanents, source.getControllerId(), game)) {
- if (!Objects.equals(permanent, hellcarverDemon)) {
- permanent.sacrifice(source.getSourceId(), game);
- }
- }
-
- if (controller != null && !controller.getHand().isEmpty()) {
- int cardsInHand = controller.getHand().size();
- controller.discard(cardsInHand, false, source, game);
- }
-
- for (int i = 0; i < 6; i++) {
- if (controller != null
- && controller.getLibrary().hasCards()) {
- Card topCard = controller.getLibrary().getFromTop(game);
- topCard.moveToExile(source.getSourceId(), "Cards exiled by Hellcarver Demon", source.getSourceId(), game);
- }
- }
-
- while (controller != null
- && controller.canRespond()
- && controller.chooseUse(Outcome.PlayForFree, controller.getLogName() + " can cast another nonland card exiled with Hellcarver Demon without paying that card's mana cost.", source, game)) {
- TargetCardInExile target = new TargetCardInExile(filter, source.getSourceId());
- while (controller.chooseUse(Outcome.PlayForFree, "Cast another spell exiled by Hellcarver Demon?", source, game)) {
- controller.choose(Outcome.PlayForFree, game.getExile().getExileZone(source.getSourceId()), target, game);
- Card card = game.getCard(target.getFirstTarget());
- if (card != null) {
- ContinuousEffect effect = new HellcarverDemonCastFromExileEffect();
- effect.setTargetPointer(new FixedTarget(card.getId()));
- game.addEffect(effect, source);
- controller.cast(card.getSpellAbility(), game, true);
+ Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
+ if (controller != null && sourceObject != null) {
+ for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
+ if (!Objects.equals(permanent, sourceObject)) {
+ permanent.sacrifice(source.getSourceId(), game);
+ }
+ }
+ if (!controller.getHand().isEmpty()) {
+ int cardsInHand = controller.getHand().size();
+ controller.discard(cardsInHand, false, source, game);
+ }
+ // move cards from library to exile
+ Set currentExiledCards = new HashSet<>();
+ currentExiledCards.addAll(controller.getLibrary().getTopCards(game, 6));
+ controller.moveCardsToExile(currentExiledCards, source, game, true, source.getSourceId(), sourceObject.getIdName());
+
+ // cast the possible cards without paying the mana
+ Cards cardsToCast = new CardsImpl();
+ cardsToCast.addAll(currentExiledCards);
+ boolean alreadyCast = false;
+ while (!cardsToCast.isEmpty()
+ && controller.canRespond()) {
+ if (!controller.chooseUse(outcome, "Cast a" + (alreadyCast ? "nother" : "" ) + " card exiled with " + sourceObject.getLogName() + " without paying its mana cost?", source, game)) {
+ break;
+ }
+ TargetCard targetCard = new TargetCard(1, Zone.EXILED, new FilterCard("nonland card to cast for free"));
+ if (controller.choose(Outcome.PlayForFree, cardsToCast, targetCard, game)) {
+ alreadyCast = true;
+ Card card = game.getCard(targetCard.getFirstTarget());
+ if (card != null) {
+ if (controller.cast(card.getSpellAbility(), game, true)) {
+ cardsToCast.remove(card);
+ } else {
+ game.informPlayer(controller, "You're not able to cast " + card.getIdName() + " or you canceled the casting.");
+ }
+ }
}
- target.clearChosen();
}
return true;
}
@@ -145,33 +143,3 @@ class HellcarverDemonEffect extends OneShotEffect {
return new HellcarverDemonEffect(this);
}
}
-
-class HellcarverDemonCastFromExileEffect extends AsThoughEffectImpl {
-
- public HellcarverDemonCastFromExileEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
- staticText = "You may play the card from exile without paying its mana cost";
- }
-
- public HellcarverDemonCastFromExileEffect(final HellcarverDemonCastFromExileEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public HellcarverDemonCastFromExileEffect copy() {
- return new HellcarverDemonCastFromExileEffect(this);
- }
-
- @Override
- public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
- if (targetPointer.getTargets(game, source).contains(sourceId)) {
- return game.getState().getZone(sourceId) == Zone.EXILED;
- }
- return false;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/h/HeraldOfThePantheon.java b/Mage.Sets/src/mage/cards/h/HeraldOfThePantheon.java
index 6c31a6de0a8..4fdc3378418 100644
--- a/Mage.Sets/src/mage/cards/h/HeraldOfThePantheon.java
+++ b/Mage.Sets/src/mage/cards/h/HeraldOfThePantheon.java
@@ -48,7 +48,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
*/
public class HeraldOfThePantheon extends CardImpl {
- private static final FilterCard filter = new FilterCard("enchantment spells");
+ private static final FilterCard filter = new FilterCard("Enchantment spells");
private static final FilterSpell filter2 = new FilterSpell("an enchantment spell");
static {
diff --git a/Mage.Sets/src/mage/cards/h/HonorablePassage.java b/Mage.Sets/src/mage/cards/h/HonorablePassage.java
new file mode 100644
index 00000000000..585d6256e09
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/HonorablePassage.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.h;
+
+import java.util.UUID;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.effects.PreventionEffectData;
+import mage.abilities.effects.common.PreventNextDamageFromChosenSourceToTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.players.Player;
+import mage.target.common.TargetCreatureOrPlayer;
+
+/**
+ *
+ * @author L_J
+ */
+public class HonorablePassage extends CardImpl {
+
+ public HonorablePassage(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}");
+
+ // The next time a source of your choice would deal damage to target creature or player this turn, prevent that damage. If damage from a red source is prevented this way, Honorable Passage deals that much damage to the source's controller.
+ this.getSpellAbility().addEffect(new HonorablePassageEffect());
+ this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
+ }
+
+ public HonorablePassage(final HonorablePassage card) {
+ super(card);
+ }
+
+ @Override
+ public HonorablePassage copy() {
+ return new HonorablePassage(this);
+ }
+}
+
+class HonorablePassageEffect extends PreventNextDamageFromChosenSourceToTargetEffect {
+
+ public HonorablePassageEffect() {
+ super(Duration.EndOfTurn);
+ }
+
+ public HonorablePassageEffect(final HonorablePassageEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public HonorablePassageEffect copy() {
+ return new HonorablePassageEffect(this);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ int damage = event.getAmount();
+ PreventionEffectData preventEffectData = preventDamageAction(event, source, game);
+ if (preventEffectData.getPreventedDamage() > 0) {
+ MageObject sourceObject = game.getObject(event.getSourceId());
+ if (sourceObject != null && sourceObject.getColor(game).isRed()) {
+ UUID sourceControllerId = game.getControllerId(event.getSourceId());
+ if (sourceControllerId != null) {
+ Player sourceController = game.getPlayer(sourceControllerId);
+ if (sourceController != null) {
+ sourceController.damage(damage, source.getSourceId(), game, false, true);
+ }
+ }
+ }
+ this.used = true;
+ }
+ return false;
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ return "The next time a source of your choice would deal damage to target creature or player this turn, prevent that damage. If damage from a red source is prevented this way, {this} deals that much damage to the source's controller";
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HostageTaker.java b/Mage.Sets/src/mage/cards/h/HostageTaker.java
index 92605814ab2..73bc0f278c1 100644
--- a/Mage.Sets/src/mage/cards/h/HostageTaker.java
+++ b/Mage.Sets/src/mage/cards/h/HostageTaker.java
@@ -41,10 +41,10 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.ManaType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
@@ -118,8 +118,8 @@ class HostageTakerExileEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Permanent card = game.getPermanent(targetPointer.getFirst(game, source));
- Permanent permanent = game.getPermanent(source.getSourceId());
+ Permanent card = game.getPermanent(getTargetPointer().getFirst(game, source));
+ Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (permanent != null && card != null) {
Player controller = game.getPlayer(card.getControllerId());
if (controller != null) {
diff --git a/Mage.Sets/src/mage/cards/h/HushwingGryff.java b/Mage.Sets/src/mage/cards/h/HushwingGryff.java
index b3316468dcc..97eac840847 100644
--- a/Mage.Sets/src/mage/cards/h/HushwingGryff.java
+++ b/Mage.Sets/src/mage/cards/h/HushwingGryff.java
@@ -31,6 +31,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
+import mage.abilities.TriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.keyword.FlashAbility;
@@ -39,9 +40,9 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityType;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
@@ -55,7 +56,7 @@ import mage.game.permanent.Permanent;
public class HushwingGryff extends CardImpl {
public HushwingGryff(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HIPPOGRIFF);
this.power = new MageInt(2);
@@ -92,10 +93,15 @@ class HushwingGryffEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
- MageObject mageObject = game.getObject(event.getSourceId());
+ MageObject enteringObject = game.getObject(event.getSourceId());
MageObject sourceObject = game.getObject(source.getSourceId());
- if (mageObject != null && sourceObject != null) {
- return sourceObject.getLogName() + " prevented ability of " + mageObject.getLogName() + " to trigger";
+ Ability ability = (Ability) getValue("targetAbility");
+ if (enteringObject != null && sourceObject != null && ability != null) {
+ MageObject abilitObject = game.getObject(ability.getSourceId());
+ if (abilitObject != null) {
+ return sourceObject.getLogName() + " prevented ability of " + abilitObject.getLogName()
+ + " to trigger for " + enteringObject.getLogName() + " entering the battlefield.";
+ }
}
return null;
}
@@ -111,7 +117,7 @@ class HushwingGryffEffect extends ContinuousRuleModifyingEffectImpl {
if (ability != null && ability.getAbilityType() == AbilityType.TRIGGERED) {
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
if (permanent != null && permanent.isCreature()) {
- return true;
+ return (((TriggeredAbility) ability).checkTrigger(event, game));
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/i/Interdict.java b/Mage.Sets/src/mage/cards/i/Interdict.java
index 5fcc1c52446..4ae659f513c 100644
--- a/Mage.Sets/src/mage/cards/i/Interdict.java
+++ b/Mage.Sets/src/mage/cards/i/Interdict.java
@@ -28,6 +28,7 @@
package mage.cards.i;
import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect;
@@ -88,7 +89,7 @@ class InterdictPredicate implements Predicate {
@Override
public boolean apply(Ability input, Game game) {
if (input instanceof StackAbility && input.getAbilityType() == AbilityType.ACTIVATED) {
- Permanent sourceObject = game.getPermanentOrLKIBattlefield(input.getSourceId());
+ MageObject sourceObject = input.getSourceObject(game);
if (sourceObject != null) {
return (sourceObject.isArtifact()
|| sourceObject.isEnchantment()
@@ -120,9 +121,12 @@ class InterdictCounterEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget());
if (stackObject != null && game.getStack().counter(source.getFirstTarget(), source.getSourceId(), game)) {
- InterdictCantActivateEffect effect = new InterdictCantActivateEffect();
- effect.setTargetPointer(new FixedTarget(stackObject.getSourceId()));
- game.getContinuousEffects().addEffect(effect, source);
+ Permanent sourcePermanent = stackObject.getStackAbility().getSourcePermanentIfItStillExists(game);
+ if (sourcePermanent != null) {
+ InterdictCantActivateEffect effect = new InterdictCantActivateEffect();
+ effect.setTargetPointer(new FixedTarget(sourcePermanent, game));
+ game.getContinuousEffects().addEffect(effect, source);
+ }
return true;
}
return false;
@@ -143,7 +147,7 @@ class InterdictCantActivateEffect extends RestrictionEffect {
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
- return getTargetPointer().getFirst(game, source).equals(permanent.getId());
+ return permanent.getId().equals(getTargetPointer().getFirst(game, source));
}
@Override
diff --git a/Mage.Sets/src/mage/cards/j/JacesSanctum.java b/Mage.Sets/src/mage/cards/j/JacesSanctum.java
index 717038e90b0..0acd517e84e 100644
--- a/Mage.Sets/src/mage/cards/j/JacesSanctum.java
+++ b/Mage.Sets/src/mage/cards/j/JacesSanctum.java
@@ -48,7 +48,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
public class JacesSanctum extends CardImpl {
- private static final FilterCard filter = new FilterCard("instant and sorcery spells");
+ private static final FilterCard filter = new FilterCard("Instant and sorcery spells");
private static final FilterSpell filter2 = new FilterSpell("an instant or sorcery spell");
diff --git a/Mage.Sets/src/mage/cards/j/JustFate.java b/Mage.Sets/src/mage/cards/j/JustFate.java
new file mode 100644
index 00000000000..214396cd316
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/j/JustFate.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.j;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
+import mage.abilities.condition.common.AttackedThisStepCondition;
+import mage.abilities.effects.common.DestroyTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.PhaseStep;
+import mage.constants.TurnPhase;
+import mage.target.common.TargetAttackingCreature;
+import mage.watchers.common.PlayerAttackedStepWatcher;
+
+/**
+ *
+ * @author TheElk801
+ */
+public class JustFate extends CardImpl {
+
+ public JustFate(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
+
+ // Cast Just Fate only during the declare attackers step and only if you've been attacked this step.
+ Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
+ TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
+ "Cast {this} only during the declare attackers step and only if you've been attacked this step."
+ );
+ ability.addWatcher(new PlayerAttackedStepWatcher());
+ this.addAbility(ability);
+
+ // Destroy target attacking creature.
+ this.getSpellAbility().addEffect(new DestroyTargetEffect());
+ this.getSpellAbility().addTarget(new TargetAttackingCreature());
+ }
+
+ public JustFate(final JustFate card) {
+ super(card);
+ }
+
+ @Override
+ public JustFate copy() {
+ return new JustFate(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/k/KaerveksSpite.java b/Mage.Sets/src/mage/cards/k/KaerveksSpite.java
index bc0c37007de..8602a8c41be 100644
--- a/Mage.Sets/src/mage/cards/k/KaerveksSpite.java
+++ b/Mage.Sets/src/mage/cards/k/KaerveksSpite.java
@@ -12,25 +12,24 @@ import mage.filter.common.FilterControlledPermanent;
public class KaerveksSpite extends CardImpl {
- private FilterControlledPermanent permanentsYouControl = new FilterControlledPermanent("all permanents you control");
-
public KaerveksSpite(UUID ownerId, CardSetInfo cardSetInfo) {
super(ownerId, cardSetInfo, new CardType[]{CardType.INSTANT}, "{B}{B}{B}");
- //As an additional cost to cast Kaervek's Spite, sacrifice all permanents you control and discard your hand.
- this.getSpellAbility().addCost(new SacrificeAllCost(permanentsYouControl));
+ // As an additional cost to cast Kaervek's Spite, sacrifice all permanents you control and discard your hand.
+ this.getSpellAbility().addCost(new SacrificeAllCost(new FilterControlledPermanent("permanents you control")));
this.getSpellAbility().addCost(new DiscardHandCost());
- //Target player loses 5 life.
+ // Target player loses 5 life.
Effect effect = new LoseLifeTargetEffect(5);
this.getSpellAbility().addEffect(effect);
}
- public KaerveksSpite(final KaerveksSpite other){
+ public KaerveksSpite(final KaerveksSpite other) {
super(other);
}
- public KaerveksSpite copy(){
+ @Override
+ public KaerveksSpite copy() {
return new KaerveksSpite(this);
}
}
diff --git a/Mage.Sets/src/mage/cards/k/KaronasZealot.java b/Mage.Sets/src/mage/cards/k/KaronasZealot.java
new file mode 100644
index 00000000000..6e07f81e71d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/k/KaronasZealot.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.k;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.RedirectDamageFromSourceToTargetEffect;
+import mage.abilities.keyword.MorphAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Duration;
+import mage.target.common.TargetCreaturePermanent;
+
+/**
+ *
+ * @author L_J
+ */
+public class KaronasZealot extends CardImpl {
+
+ public KaronasZealot(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}");
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(5);
+
+ // Morph {3}{W}{W}
+ this.addAbility(new MorphAbility(this, new ManaCostsImpl("{3}{W}{W}")));
+
+ // When Karona's Zealot is turned face up, all damage that would be dealt to it this turn is dealt to target creature instead.
+ Ability ability = new TurnedFaceUpSourceTriggeredAbility(new RedirectDamageFromSourceToTargetEffect(Duration.EndOfTurn, Integer.MAX_VALUE, false)
+ .setText("all damage that would be dealt to it this turn is dealt to target creature instead"));
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ }
+
+ public KaronasZealot(final KaronasZealot card) {
+ super(card);
+ }
+
+ @Override
+ public KaronasZealot copy() {
+ return new KaronasZealot(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/k/KongmingsContraptions.java b/Mage.Sets/src/mage/cards/k/KongmingsContraptions.java
new file mode 100644
index 00000000000..d03db0bfd11
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/k/KongmingsContraptions.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.k;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.condition.CompoundCondition;
+import mage.abilities.condition.common.AttackedThisStepCondition;
+import mage.abilities.condition.common.IsStepCondition;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.decorator.ConditionalActivatedAbility;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import mage.filter.common.FilterAttackingCreature;
+import mage.target.TargetPermanent;
+import mage.watchers.common.PlayerAttackedStepWatcher;
+
+/**
+ *
+ * @author L_J
+ */
+public class KongmingsContraptions extends CardImpl {
+
+ public KongmingsContraptions(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.SOLDIER);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(4);
+
+ // {T}: Kongming's Contraptions deals 2 damage to target attacking creature. Activate this ability only during the declare attackers step and only if you've been attacked this step.
+ Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new TapSourceCost(),
+ new CompoundCondition("during the declare attackers step and only if you've been attacked this step",
+ new IsStepCondition(PhaseStep.DECLARE_ATTACKERS, false), AttackedThisStepCondition.instance)
+ );
+ ability.addTarget(new TargetPermanent(new FilterAttackingCreature()));
+ this.addAbility(ability, new PlayerAttackedStepWatcher());
+ }
+
+ public KongmingsContraptions(final KongmingsContraptions card) {
+ super(card);
+ }
+
+ @Override
+ public KongmingsContraptions copy() {
+ return new KongmingsContraptions(this);
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/k/KrosanDrover.java b/Mage.Sets/src/mage/cards/k/KrosanDrover.java
index b8237a2bebd..7bd3c7d3411 100644
--- a/Mage.Sets/src/mage/cards/k/KrosanDrover.java
+++ b/Mage.Sets/src/mage/cards/k/KrosanDrover.java
@@ -30,6 +30,7 @@ package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -61,7 +62,9 @@ public class KrosanDrover extends CardImpl {
this.toughness = new MageInt(2);
// Creature spells you cast with converted mana cost 6 or greater cost {2} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 2)));
+ Effect effect = new SpellsCostReductionControllerEffect(filter, 2);
+ effect.setText("Creature spells you cast with converted mana cost 6 or greater cost {2} less to cast.");
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public KrosanDrover(final KrosanDrover card) {
diff --git a/Mage.Sets/src/mage/cards/l/LaquatussChampion.java b/Mage.Sets/src/mage/cards/l/LaquatussChampion.java
index 0e91897a874..909d6a62314 100644
--- a/Mage.Sets/src/mage/cards/l/LaquatussChampion.java
+++ b/Mage.Sets/src/mage/cards/l/LaquatussChampion.java
@@ -35,7 +35,6 @@ import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.AdjustingSourceCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeTargetEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.effects.common.RegenerateSourceEffect;
@@ -58,7 +57,7 @@ import mage.util.CardUtil;
public class LaquatussChampion extends CardImpl {
public LaquatussChampion(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}");
this.subtype.add(SubType.NIGHTMARE);
this.subtype.add(SubType.HORROR);
@@ -126,9 +125,7 @@ class LaquatussChampionLeavesBattlefieldTriggeredAbility extends LeavesBattlefie
String key = CardUtil.getCardZoneString("targetPlayer", this.getSourceId(), game, true);
Object object = game.getState().getValue(key);
if (object instanceof UUID) {
- for (Effect effect : this.getEffects()) {
- effect.setTargetPointer(new FixedTarget((UUID) object));
- }
+ this.getEffects().setTargetPointer(new FixedTarget((UUID) object));
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/l/Leviathan.java b/Mage.Sets/src/mage/cards/l/Leviathan.java
index cf79670e671..7f5d4b1cb2f 100644
--- a/Mage.Sets/src/mage/cards/l/Leviathan.java
+++ b/Mage.Sets/src/mage/cards/l/Leviathan.java
@@ -118,7 +118,7 @@ class LeviathanCostToAttackBlockEffect extends PayCostToAttackBlockEffectImpl {
LeviathanCostToAttackBlockEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.ATTACK,
new SacrificeTargetCost(new TargetControlledPermanent(2, 2, filter, false)));
- staticText = "{this} can't attack unless you sacrifice two Islands (This cost is paid as attackers are declared.)";
+ staticText = "{this} can't attack unless you sacrifice two Islands. (This cost is paid as attackers are declared.)";
}
LeviathanCostToAttackBlockEffect(LeviathanCostToAttackBlockEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/l/LyevDecree.java b/Mage.Sets/src/mage/cards/l/LyevDecree.java
index c332e4bf099..70326ded261 100644
--- a/Mage.Sets/src/mage/cards/l/LyevDecree.java
+++ b/Mage.Sets/src/mage/cards/l/LyevDecree.java
@@ -47,7 +47,7 @@ import mage.target.common.TargetCreaturePermanent;
public class LyevDecree extends CardImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures your opponent controls");
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures your opponents control");
static {
filter.add(new ControllerPredicate(TargetController.OPPONENT));
}
@@ -56,7 +56,7 @@ public class LyevDecree extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{W}");
- // Detain up to two target creatures your opponent controls.
+ // Detain up to two target creatures your opponents control.
this.getSpellAbility().addEffect(new DetainTargetEffect());
Target target = new TargetCreaturePermanent(0,2,filter,false);
this.getSpellAbility().addTarget(target);
diff --git a/Mage.Sets/src/mage/cards/m/ManaMatrix.java b/Mage.Sets/src/mage/cards/m/ManaMatrix.java
index e2e0fac2c55..1777b831fd3 100644
--- a/Mage.Sets/src/mage/cards/m/ManaMatrix.java
+++ b/Mage.Sets/src/mage/cards/m/ManaMatrix.java
@@ -44,7 +44,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
*/
public class ManaMatrix extends CardImpl {
- private static final FilterCard filter = new FilterCard("instant and enchantment spells");
+ private static final FilterCard filter = new FilterCard("Instant and enchantment spells");
static {
filter.add(Predicates.or(
diff --git a/Mage.Sets/src/mage/cards/m/MercadiasDownfall.java b/Mage.Sets/src/mage/cards/m/MercadiasDownfall.java
new file mode 100644
index 00000000000..c905d973c03
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MercadiasDownfall.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.m;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.StaticValue;
+import mage.abilities.effects.Effect;
+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.SuperType;
+import mage.filter.common.FilterAttackingCreature;
+import mage.filter.common.FilterLandPermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.SupertypePredicate;
+import mage.game.Game;
+import mage.game.combat.CombatGroup;
+import mage.game.permanent.Permanent;
+
+/**
+ *
+ * @author jeffwadsworth
+ */
+public class MercadiasDownfall extends CardImpl {
+
+ private static String rule = "Each attacking creature gets +1/+0 until end of turn for each nonbasic land defending player controls";
+
+ public MercadiasDownfall(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
+
+ // Each attacking creature gets +1/+0 until end of turn for each nonbasic land defending player controls.
+ this.getSpellAbility().addEffect(new BoostAllEffect(new DefendersNonBasicLandCount(), new StaticValue(0), Duration.EndOfTurn, new FilterAttackingCreature(), true, rule));
+
+ }
+
+ public MercadiasDownfall(final MercadiasDownfall card) {
+ super(card);
+ }
+
+ @Override
+ public MercadiasDownfall copy() {
+ return new MercadiasDownfall(this);
+ }
+
+ class DefendersNonBasicLandCount implements DynamicValue {
+
+ UUID defenderId;
+
+ @Override
+ public int calculate(Game game, Ability sourceAbility, Effect effect) {
+ for (CombatGroup group : game.getCombat().getGroups()) {
+ defenderId = group.getDefenderId();
+ if (group.isDefenderIsPlaneswalker()) {
+ Permanent permanent = game.getPermanent(defenderId);
+ if (permanent != null) {
+ defenderId = permanent.getControllerId();
+ }
+ }
+ FilterLandPermanent filter = new FilterLandPermanent("nonbasic land");
+ filter.add(Predicates.not(new SupertypePredicate(SuperType.BASIC)));
+ System.out.println("The number of nonbasic lands is " + game.getBattlefield().countAll(filter, defenderId, game));
+ return game.getBattlefield().countAll(filter, defenderId, game);
+ }
+ return 0;
+ }
+
+ @Override
+ public DynamicValue copy() {
+ return new DefendersNonBasicLandCount();
+ }
+
+ @Override
+ public String toString() {
+ return "X";
+ }
+
+ @Override
+ public String getMessage() {
+ return "the number of nonbasic lands defending player controls";
+ }
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/m/MerfolkRaiders.java b/Mage.Sets/src/mage/cards/m/MerfolkRaiders.java
index 21611866db1..09e408b51b5 100644
--- a/Mage.Sets/src/mage/cards/m/MerfolkRaiders.java
+++ b/Mage.Sets/src/mage/cards/m/MerfolkRaiders.java
@@ -50,10 +50,10 @@ public class MerfolkRaiders extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(3);
- // Phasing
- this.addAbility(PhasingAbility.getInstance());
// Islandwalk
this.addAbility(new IslandwalkAbility());
+ // Phasing
+ this.addAbility(PhasingAbility.getInstance());
}
public MerfolkRaiders(final MerfolkRaiders card) {
diff --git a/Mage.Sets/src/mage/cards/m/MilitantInquisitor.java b/Mage.Sets/src/mage/cards/m/MilitantInquisitor.java
index 05df6afc78a..9b3e8127988 100644
--- a/Mage.Sets/src/mage/cards/m/MilitantInquisitor.java
+++ b/Mage.Sets/src/mage/cards/m/MilitantInquisitor.java
@@ -49,7 +49,7 @@ import mage.filter.predicate.mageobject.SubtypePredicate;
*/
public class MilitantInquisitor extends CardImpl {
- private static final FilterControlledPermanent filter = new FilterControlledPermanent("equipment you control");
+ private static final FilterControlledPermanent filter = new FilterControlledPermanent("Equipment you control");
static {
filter.add(new CardTypePredicate(CardType.ARTIFACT));
diff --git a/Mage.Sets/src/mage/cards/m/MimicVat.java b/Mage.Sets/src/mage/cards/m/MimicVat.java
index 8fd4c37ba9d..9f5b5636112 100644
--- a/Mage.Sets/src/mage/cards/m/MimicVat.java
+++ b/Mage.Sets/src/mage/cards/m/MimicVat.java
@@ -38,8 +38,8 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
+import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -122,7 +122,7 @@ class MimicVatTriggeredAbility extends TriggeredAbilityImpl {
&& !(permanent instanceof PermanentToken)
&& permanent.isCreature()) {
- getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId()));
+ getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId(), game));
return true;
}
return false;
@@ -152,22 +152,22 @@ class MimicVatEffect extends OneShotEffect {
if (controller == null || permanent == null) {
return false;
}
- // return older cards to graveyard
- Set toGraveyard = new HashSet<>();
- for (UUID imprintedId : permanent.getImprinted()) {
- Card card = game.getCard(imprintedId);
- if (card != null) {
- toGraveyard.add(card);
- }
- }
- controller.moveCards(toGraveyard, Zone.GRAVEYARD, source, game);
- permanent.clearImprinted(game);
-
// Imprint a new one
- Card card = game.getCard(getTargetPointer().getFirst(game, source));
- if (card != null) {
- controller.moveCardsToExile(card, source, game, true, source.getSourceId(), permanent.getName() + " (Imprint)");
- permanent.imprint(card.getId(), game);
+ Card newCard = game.getCard(getTargetPointer().getFirst(game, source));
+ if (newCard != null) {
+ // return older cards to graveyard
+ Set toGraveyard = new HashSet<>();
+ for (UUID imprintedId : permanent.getImprinted()) {
+ Card card = game.getCard(imprintedId);
+ if (card != null) {
+ toGraveyard.add(card);
+ }
+ }
+ controller.moveCards(toGraveyard, Zone.GRAVEYARD, source, game);
+ permanent.clearImprinted(game);
+
+ controller.moveCardsToExile(newCard, source, game, true, source.getSourceId(), permanent.getName() + " (Imprint)");
+ permanent.imprint(newCard.getId(), game);
}
return true;
diff --git a/Mage.Sets/src/mage/cards/m/MinionOfTheWastes.java b/Mage.Sets/src/mage/cards/m/MinionOfTheWastes.java
new file mode 100644
index 00000000000..2714adcea44
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MinionOfTheWastes.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.m;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.AsEntersBattlefieldAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.InfoEffect;
+import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubLayer;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.players.Player;
+
+/**
+ *
+ * @author L_J
+ */
+public class MinionOfTheWastes extends CardImpl {
+
+ public MinionOfTheWastes(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}{B}");
+ this.subtype.add(SubType.MINION);
+ this.power = new MageInt(0);
+ this.toughness = new MageInt(0);
+
+ // Trample
+ this.addAbility(TrampleAbility.getInstance());
+
+ // As Minion of the Wastes enters the battlefield, pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards.
+ this.addAbility(new AsEntersBattlefieldAbility(new MinionOfTheWastesEffect()));
+
+ // Minion of the Wastes's power and toughness are each equal to the life paid as it entered the battlefield.
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield")));
+ }
+
+ public MinionOfTheWastes(final MinionOfTheWastes card) {
+ super(card);
+ }
+
+ @Override
+ public MinionOfTheWastes copy() {
+ return new MinionOfTheWastes(this);
+ }
+}
+
+class MinionOfTheWastesEffect extends OneShotEffect {
+
+ public MinionOfTheWastesEffect() {
+ super(Outcome.LoseLife);
+ staticText = "pay any amount of life";
+ }
+
+ public MinionOfTheWastesEffect(final MinionOfTheWastesEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public MinionOfTheWastesEffect copy() {
+ return new MinionOfTheWastesEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ Card sourceCard = game.getCard(source.getSourceId());
+ int payAmount = controller.getAmount(0, controller.getLife(), "Pay any amount of life", game);
+ controller.loseLife(payAmount, game, false);
+ game.informPlayers(new StringBuilder(sourceCard.getLogName()).append(": ").append(controller.getLogName())
+ .append(" pays ").append(payAmount).append(" life").toString());
+ game.addEffect(new SetPowerToughnessSourceEffect(payAmount, payAmount, Duration.Custom, SubLayer.SetPT_7b), source);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/m/MistformWakecaster.java b/Mage.Sets/src/mage/cards/m/MistformWakecaster.java
new file mode 100644
index 00000000000..2bf1bfe4abb
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MistformWakecaster.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.m;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.BecomesChosenCreatureTypeSourceEffect;
+import mage.abilities.effects.common.continuous.BecomesCreatureTypeTargetEffect;
+import mage.constants.SubType;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.choices.Choice;
+import mage.choices.ChoiceCreatureType;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.targetpointer.FixedTarget;
+
+/**
+ *
+ * @author L_J
+ */
+public class MistformWakecaster extends CardImpl {
+
+ public MistformWakecaster(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}");
+ this.subtype.add(SubType.ILLUSION);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // {1}: Mistform Wakecaster becomes the creature type of your choice until end of turn.
+ this.addAbility(new SimpleActivatedAbility(new BecomesChosenCreatureTypeSourceEffect(), new ManaCostsImpl("{1}")));
+
+ // {2}{U}{U}, {T}: Choose a creature type. Each creature you control becomes that type until end of turn.
+ Ability ability = new SimpleActivatedAbility(new BecomesChosenCreatureTypeControlledEffect(), new ManaCostsImpl("{2}{U}{U}"));
+ ability.addCost(new TapSourceCost());
+ this.addAbility(ability);
+ }
+
+ public MistformWakecaster(final MistformWakecaster card) {
+ super(card);
+ }
+
+ @Override
+ public MistformWakecaster copy() {
+ return new MistformWakecaster(this);
+ }
+}
+
+class BecomesChosenCreatureTypeControlledEffect extends OneShotEffect {
+
+ public BecomesChosenCreatureTypeControlledEffect() {
+ super(Outcome.BoostCreature);
+ staticText = "Choose a creature type. Each creature you control becomes that type until end of turn";
+ }
+
+ public BecomesChosenCreatureTypeControlledEffect(final BecomesChosenCreatureTypeControlledEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ Card card = game.getCard(source.getSourceId());
+ String chosenType = "";
+ if (player != null && card != null) {
+ Choice typeChoice = new ChoiceCreatureType();
+ String msg = "Choose a creature type";
+ typeChoice.setMessage(msg);
+ while (!player.choose(Outcome.BoostCreature, typeChoice, game)) {
+ if (!player.canRespond()) {
+ return false;
+ }
+ }
+ game.informPlayers(card.getName() + ": " + player.getLogName() + " has chosen " + typeChoice.getChoice());
+ chosenType = typeChoice.getChoice();
+ if (chosenType != null && !chosenType.isEmpty()) {
+ for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game)) {
+ ContinuousEffect effect = new BecomesCreatureTypeTargetEffect(Duration.EndOfTurn, SubType.byDescription(chosenType));
+ effect.setTargetPointer(new FixedTarget(permanent.getId()));
+ game.addEffect(effect, source);
+ }
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ @Override
+ public Effect copy() {
+ return new BecomesChosenCreatureTypeControlledEffect(this);
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java b/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java
index 923d1f6a541..03a8a691cce 100644
--- a/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java
+++ b/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java
@@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
-
package mage.cards.m;
import java.io.Serializable;
@@ -50,9 +49,11 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
+import mage.game.permanent.Permanent;
import mage.game.permanent.token.MyrToken;
import mage.players.Player;
import mage.target.TargetPermanent;
+import mage.watchers.common.CreatureAttackedWhichPlayerWatcher;
/**
*
@@ -61,7 +62,7 @@ import mage.target.TargetPermanent;
public class MyrBattlesphere extends CardImpl {
public MyrBattlesphere(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{7}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}");
this.subtype.add(SubType.MYR);
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(4);
@@ -71,7 +72,8 @@ public class MyrBattlesphere extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new MyrToken(), 4), false));
// Whenever Myr Battlesphere attacks, you may tap X untapped Myr you control. If you do, Myr Battlesphere gets +X/+0 until end of turn and deals X damage to defending player.
- this.addAbility(new AttacksTriggeredAbility(new MyrBattlesphereEffect(), true));
+ this.addAbility(new AttacksTriggeredAbility(new MyrBattlesphereEffect(), true), new CreatureAttackedWhichPlayerWatcher());
+
}
public MyrBattlesphere(final MyrBattlesphere card) {
@@ -107,42 +109,46 @@ class MyrBattlesphereEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- int tappedAmount = 0;
- TargetPermanent target = new TargetPermanent(0,1,filter, false);
- while (true && controller.canRespond()) {
- target.clearChosen();
- if (target.canChoose(source.getControllerId(), game)) {
- Map options = new HashMap<>();
- options.put("UI.right.btn.text", "Myr tapping complete");
- controller.choose(outcome, target, source.getControllerId(), game, options);
- if (!target.getTargets().isEmpty()) {
- UUID creature = target.getFirstTarget();
- if (creature != null) {
- game.getPermanent(creature).tap(game);
- tappedAmount++;
+ CreatureAttackedWhichPlayerWatcher watcher = (CreatureAttackedWhichPlayerWatcher) game.getState().getWatchers().get(CreatureAttackedWhichPlayerWatcher.class.getSimpleName());
+ if (watcher != null) {
+ // even if the Myr Battlesphere is off the battlefield, it still does damage to the defender
+ Permanent myr = game.getPermanentOrLKIBattlefield(source.getSourceId());
+ UUID defenderId = watcher.getPlayerAttackedThisTurnByCreature(myr.getId());
+ Player defender = game.getPlayer(defenderId);
+ int tappedAmount = 0;
+ TargetPermanent target = new TargetPermanent(0, 1, filter, false);
+ while (true && controller.canRespond()) {
+ target.clearChosen();
+ if (target.canChoose(source.getControllerId(), game)) {
+ Map options = new HashMap<>();
+ options.put("UI.right.btn.text", "Myr tapping complete");
+ controller.choose(outcome, target, source.getControllerId(), game, options);
+ if (!target.getTargets().isEmpty()) {
+ UUID creature = target.getFirstTarget();
+ if (creature != null) {
+ game.getPermanent(creature).tap(game);
+ tappedAmount++;
+ }
+ } else {
+ break;
}
} else {
break;
}
}
- else {
- break;
- }
- }
- if (tappedAmount > 0) {
- game.informPlayers(new StringBuilder(controller.getLogName()).append(" taps ").append(tappedAmount).append(" Myrs").toString());
- // boost effect
- game.addEffect(new BoostSourceEffect(tappedAmount, 0, Duration.EndOfTurn), source);
- // damage to defender
- UUID defenderId = game.getCombat().getDefendingPlayerId(source.getSourceId(), game);
- Player defender = game.getPlayer(defenderId);
- if (defender != null) {
- defender.damage(tappedAmount, source.getSourceId(), game, false, true);
- return true;
- }
+ if (tappedAmount > 0) {
+ game.informPlayers(new StringBuilder(controller.getLogName()).append(" taps ").append(tappedAmount).append(" Myrs").toString());
+ // boost effect
+ game.addEffect(new BoostSourceEffect(tappedAmount, 0, Duration.EndOfTurn), source);
+ // damage to defender
+ if (defender != null) {
+ defender.damage(tappedAmount, myr.getId(), game, false, true);
+ return true;
+ }
+ }
+ return true;
}
- return true;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/n/NamelessRace.java b/Mage.Sets/src/mage/cards/n/NamelessRace.java
new file mode 100644
index 00000000000..615f1a48fc4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/n/NamelessRace.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.n;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.ObjectColor;
+import mage.abilities.Ability;
+import mage.abilities.common.AsEntersBattlefieldAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.InfoEffect;
+import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubLayer;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+import mage.filter.FilterPermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.ColorPredicate;
+import mage.filter.predicate.other.OwnerPredicate;
+import mage.filter.predicate.permanent.ControllerPredicate;
+import mage.filter.predicate.permanent.TokenPredicate;
+import mage.game.Game;
+import mage.players.Player;
+
+/**
+ *
+ * @author L_J
+ */
+public class NamelessRace extends CardImpl {
+
+ public NamelessRace(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
+ this.power = new MageInt(0);
+ this.toughness = new MageInt(0);
+
+ // Trample
+ this.addAbility(TrampleAbility.getInstance());
+
+ // As Nameless Race enters the battlefield, pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards.
+ this.addAbility(new AsEntersBattlefieldAbility(new NamelessRaceEffect()));
+
+ // Nameless Race's power and toughness are each equal to the life paid as it entered the battlefield.
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield")));
+ }
+
+ public NamelessRace(final NamelessRace card) {
+ super(card);
+ }
+
+ @Override
+ public NamelessRace copy() {
+ return new NamelessRace(this);
+ }
+}
+
+class NamelessRaceEffect extends OneShotEffect {
+
+ private static final FilterPermanent filter = new FilterPermanent("white nontoken permanents your opponents control");
+ private static final FilterCard filter2 = new FilterCard("white cards in their graveyards");
+
+ static {
+ filter.add(new ColorPredicate(ObjectColor.WHITE));
+ filter.add(Predicates.not(new TokenPredicate()));
+ filter.add(new ControllerPredicate(TargetController.OPPONENT));
+ filter2.add(new ColorPredicate(ObjectColor.WHITE));
+ filter2.add(new OwnerPredicate(TargetController.OPPONENT));
+ }
+
+ public NamelessRaceEffect() {
+ super(Outcome.LoseLife);
+ staticText = "pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards";
+ }
+
+ public NamelessRaceEffect(final NamelessRaceEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public NamelessRaceEffect copy() {
+ return new NamelessRaceEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ Card sourceCard = game.getCard(source.getSourceId());
+ int permanentsInPlay = new PermanentsOnBattlefieldCount(filter).calculate(game, source, null);
+ int cardsInGraveyards = new CardsInAllGraveyardsCount(filter2).calculate(game, source, null);
+ int maxAmount = Math.min(permanentsInPlay + cardsInGraveyards, controller.getLife());
+ int payAmount = controller.getAmount(0, maxAmount, "Pay up to " + maxAmount + " life", game);
+ controller.loseLife(payAmount, game, false);
+ game.informPlayers(new StringBuilder(sourceCard.getLogName()).append(": ").append(controller.getLogName())
+ .append(" pays ").append(payAmount).append(" life").toString());
+ game.addEffect(new SetPowerToughnessSourceEffect(payAmount, payAmount, Duration.Custom, SubLayer.SetPT_7b), source);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/n/NivMizzetTheFiremind.java b/Mage.Sets/src/mage/cards/n/NivMizzetTheFiremind.java
index e4b3cc805c8..486e8cfd29a 100644
--- a/Mage.Sets/src/mage/cards/n/NivMizzetTheFiremind.java
+++ b/Mage.Sets/src/mage/cards/n/NivMizzetTheFiremind.java
@@ -51,18 +51,23 @@ import mage.target.common.TargetCreatureOrPlayer;
public class NivMizzetTheFiremind extends CardImpl {
public NivMizzetTheFiremind(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{U}{R}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}{R}{R}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.DRAGON);
this.subtype.add(SubType.WIZARD);
-
this.power = new MageInt(4);
this.toughness = new MageInt(4);
+
+ // Flying
this.addAbility(FlyingAbility.getInstance());
+
+ // Whenever you draw a card, Niv-Mizzet, the Firemind deals 1 damage to target creature or player.
Ability ability = new DrawCardControllerTriggeredAbility(new DamageTargetEffect(1), false);
ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability);
+
+ // {T}: Draw a card.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new TapSourceCost()));
}
diff --git a/Mage.Sets/src/mage/cards/o/OrimsPrayer.java b/Mage.Sets/src/mage/cards/o/OrimsPrayer.java
new file mode 100644
index 00000000000..4ad6e297a70
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/o/OrimsPrayer.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.o;
+
+import java.util.UUID;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.dynamicvalue.common.AttackingCreatureCount;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.GameEvent.EventType;
+
+/**
+ *
+ * @author L_J
+ */
+public class OrimsPrayer extends CardImpl {
+
+ public OrimsPrayer(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}");
+
+ // Whenever one or more creatures attack you, you gain 1 life for each attacking creature.
+ this.addAbility(new OrimsPrayerTriggeredAbility());
+ }
+
+ public OrimsPrayer(final OrimsPrayer card) {
+ super(card);
+ }
+
+ @Override
+ public OrimsPrayer copy() {
+ return new OrimsPrayer(this);
+ }
+}
+
+class OrimsPrayerTriggeredAbility extends TriggeredAbilityImpl {
+
+ public OrimsPrayerTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new GainLifeEffect(new AttackingCreatureCount()));
+ }
+
+ public OrimsPrayerTriggeredAbility(final OrimsPrayerTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public OrimsPrayerTriggeredAbility copy() {
+ return new OrimsPrayerTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.DECLARED_ATTACKERS;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ return game.getCombat().getDefenders().contains(getControllerId());
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever one or more creatures attack you, " + super.getRule();
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/Panharmonicon.java b/Mage.Sets/src/mage/cards/p/Panharmonicon.java
index 4bade4472d6..26dfcafdf5e 100644
--- a/Mage.Sets/src/mage/cards/p/Panharmonicon.java
+++ b/Mage.Sets/src/mage/cards/p/Panharmonicon.java
@@ -50,7 +50,7 @@ import mage.game.events.NumberOfTriggersEvent;
public class Panharmonicon extends CardImpl {
public Panharmonicon(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PanharmoniconEffect()));
@@ -95,7 +95,9 @@ class PanharmoniconEffect extends ReplacementEffectImpl {
if (source.getControllerId().equals(event.getPlayerId())) {
GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent();
// Only EtB triggers
- if (sourceEvent.getType() == EventType.ENTERS_THE_BATTLEFIELD && sourceEvent instanceof EntersTheBattlefieldEvent) {
+ if (sourceEvent != null
+ && sourceEvent.getType() == EventType.ENTERS_THE_BATTLEFIELD
+ && sourceEvent instanceof EntersTheBattlefieldEvent) {
EntersTheBattlefieldEvent entersTheBattlefieldEvent = (EntersTheBattlefieldEvent) sourceEvent;
// Only for entering artifacts or creatures
if (entersTheBattlefieldEvent.getTarget().isArtifact()
@@ -116,4 +118,4 @@ class PanharmoniconEffect extends ReplacementEffectImpl {
event.setAmount(event.getAmount() + 1);
return false;
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/p/ParallelThoughts.java b/Mage.Sets/src/mage/cards/p/ParallelThoughts.java
new file mode 100644
index 00000000000..8a803ed86ff
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/ParallelThoughts.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.p;
+
+import java.util.Arrays;
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.ReplacementEffectImpl;
+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.Duration;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.GameEvent.EventType;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.common.TargetCardInLibrary;
+import mage.util.CardUtil;
+import mage.util.RandomUtil;
+
+/**
+ *
+ * @author jeffwadsworth
+ */
+public class ParallelThoughts extends CardImpl {
+
+ public ParallelThoughts(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}");
+
+ // When Parallel Thoughts enters the battlefield, search your library for seven cards, exile them in a face-down pile, and shuffle that pile. Then shuffle your library.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new ParallelThoughtsSearchEffect()));
+
+ // If you would draw a card, you may instead put the top card of the pile you exiled into your hand.
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ParallelThoughtsReplacementEffect()));
+
+ }
+
+ public ParallelThoughts(final ParallelThoughts card) {
+ super(card);
+ }
+
+ @Override
+ public ParallelThoughts copy() {
+ return new ParallelThoughts(this);
+ }
+}
+
+class ParallelThoughtsSearchEffect extends OneShotEffect {
+
+ ParallelThoughtsSearchEffect() {
+ super(Outcome.Neutral);
+ this.staticText = "search your library for seven cards, exile them in a face-down pile, and shuffle that pile. Then shuffle your library";
+ }
+
+ ParallelThoughtsSearchEffect(final ParallelThoughtsSearchEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ParallelThoughtsSearchEffect copy() {
+ return new ParallelThoughtsSearchEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
+ Cards cardsInExilePile = new CardsImpl();
+ if (controller != null
+ && permanent != null) {
+ TargetCardInLibrary target = new TargetCardInLibrary(7, new FilterCard());
+ if (controller.searchLibrary(target, game)) {
+ for (UUID targetId : target.getTargets()) {
+ Card card = controller.getLibrary().getCard(targetId, game);
+ if (card != null) {
+ cardsInExilePile.add(card);
+ }
+ }
+ // shuffle that exiled pile
+
+ UUID[] shuffled = cardsInExilePile.toArray(new UUID[0]);
+ for (int n = shuffled.length - 1; n > 0; n--) {
+ int r = RandomUtil.nextInt(n + 1);
+ UUID temp = shuffled[n];
+ shuffled[n] = shuffled[r];
+ shuffled[r] = temp;
+ }
+ cardsInExilePile.clear();
+ cardsInExilePile.addAll(Arrays.asList(shuffled));
+
+ // move to exile zone and turn face down
+
+ for (Card card : cardsInExilePile.getCards(game)) {
+ controller.moveCardsToExile(card, source, game, false, CardUtil.getCardExileZoneId(game, source), permanent.getLogName());
+ card.setFaceDown(true, game);
+ }
+
+ // shuffle controller library
+
+ controller.shuffleLibrary(source, game);
+ }
+ return true;
+ }
+ return false;
+ }
+}
+
+class ParallelThoughtsReplacementEffect extends ReplacementEffectImpl {
+
+ ParallelThoughtsReplacementEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.DrawCard);
+ staticText = "If you would draw a card, you may instead put the top card of the pile you exiled with Parallel Thoughts into your hand";
+ }
+
+ ParallelThoughtsReplacementEffect(final ParallelThoughtsReplacementEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ParallelThoughtsReplacementEffect copy() {
+ return new ParallelThoughtsReplacementEffect(this);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null
+ && !game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)).getCards(game).isEmpty()) {
+ Card card = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)).getCards(game).iterator().next();
+ if (card != null) {
+ controller.moveCards(card, Zone.HAND, source, game);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.DRAW_CARD;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ return source.getControllerId().equals(event.getPlayerId());
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/Penance.java b/Mage.Sets/src/mage/cards/p/Penance.java
new file mode 100644
index 00000000000..45616fedf34
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/Penance.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.p;
+
+import java.util.UUID;
+import mage.ObjectColor;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.PutCardFromHandOnTopOfLibraryCost;
+import mage.abilities.effects.PreventionEffectImpl;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.target.TargetSource;
+
+/**
+ *
+ * @author jeffwadsworth
+ */
+public class Penance extends CardImpl {
+
+ public Penance(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
+
+ // Put a card from your hand on top of your library: The next time a black or red source of your choice would deal damage this turn, prevent that damage.
+ this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PenanceEffect(), new PutCardFromHandOnTopOfLibraryCost()));
+
+ }
+
+ public Penance(final Penance card) {
+ super(card);
+ }
+
+ @Override
+ public Penance copy() {
+ return new Penance(this);
+ }
+}
+
+class PenanceEffect extends PreventionEffectImpl {
+
+ private final TargetSource target;
+
+ public PenanceEffect() {
+ super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
+ this.staticText = "The next time a black or red source of your choice would deal damage to you this turn, prevent that damage.";
+ this.target = new TargetSource();
+ }
+
+ public PenanceEffect(final PenanceEffect effect) {
+ super(effect);
+ this.target = effect.target.copy();
+ }
+
+ @Override
+ public PenanceEffect copy() {
+ return new PenanceEffect(this);
+ }
+
+ @Override
+ public void init(Ability source, Game game) {
+ this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
+ super.init(source, game);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ this.used = true;
+ this.discard(); // only one use
+ return true;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (!this.used
+ && super.applies(event, source, game)) {
+ if (event.getTargetId().equals(source.getControllerId())
+ && event.getSourceId().equals(target.getFirstTarget())) {
+ return (game.getObject(target.getFirstTarget()).getColor(game).contains(ObjectColor.BLACK)
+ || game.getObject(target.getFirstTarget()).getColor(game).contains(ObjectColor.RED));
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/p/PlanarGate.java b/Mage.Sets/src/mage/cards/p/PlanarGate.java
index 8ef656f71f7..42cea9d0df4 100644
--- a/Mage.Sets/src/mage/cards/p/PlanarGate.java
+++ b/Mage.Sets/src/mage/cards/p/PlanarGate.java
@@ -46,7 +46,7 @@ public class PlanarGate extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}");
// Creature spells you cast cost up to {2} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCreatureCard("creature spells"), 2, true)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCreatureCard("Creature spells"), 2, true)));
}
public PlanarGate(final PlanarGate card) {
diff --git a/Mage.Sets/src/mage/cards/p/PowerLeak.java b/Mage.Sets/src/mage/cards/p/PowerLeak.java
new file mode 100644
index 00000000000..4e4d9120885
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/PowerLeak.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.p;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.costs.mana.ManaCost;
+import mage.abilities.costs.mana.ManaCosts;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.AttachEffect;
+import mage.abilities.effects.common.PreventDamageByTargetEffect;
+import mage.abilities.keyword.EnchantAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetEnchantmentPermanent;
+import mage.target.targetpointer.FixedTarget;
+
+/**
+ *
+ * @author L_J
+ */
+public class PowerLeak extends CardImpl {
+
+ public PowerLeak(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}");
+ this.subtype.add(SubType.AURA);
+
+ // Enchant enchantment
+ TargetPermanent auraTarget = new TargetEnchantmentPermanent();
+ this.getSpellAbility().addTarget(auraTarget);
+ this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
+ this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
+
+ // At the beginning of the upkeep of enchanted enchantment's controller, that player may pay any amount of mana. Power Leak deals 2 damage to that player. Prevent X of that damage, where X is the amount of mana that player paid this way.
+ this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new PowerLeakEffect(), TargetController.CONTROLLER_ATTACHED_TO, false, true, "At the beginning of the upkeep of enchanted enchantment's controller, "));
+ }
+
+ public PowerLeak(final PowerLeak card) {
+ super(card);
+ }
+
+ @Override
+ public PowerLeak copy() {
+ return new PowerLeak(this);
+ }
+}
+
+class PowerLeakEffect extends OneShotEffect {
+
+ public PowerLeakEffect() {
+ super(Outcome.Detriment);
+ this.staticText = "that player may pay any amount of mana. {this} deals 2 damage to that player. Prevent X of that damage, where X is the amount of mana that player paid this way";
+ }
+
+ public PowerLeakEffect(final PowerLeakEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public PowerLeakEffect copy() {
+ return new PowerLeakEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(game.getActivePlayerId());
+ Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
+ if (player != null && permanent != null) {
+ ManaCosts cost = new ManaCostsImpl<>("{X}");
+ String message = "Pay {X} to prevent X damage from " + permanent.getLogName() + "?";
+ int xValue = 0;
+ if (player != null && player.chooseUse(Outcome.Neutral, message, source, game)) {
+ xValue = player.announceXMana(0, Integer.MAX_VALUE, "Choose the amount of mana to pay", game, source);
+ cost.add(new GenericManaCost(xValue));
+ if (cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) {
+ game.informPlayers(player.getLogName() + " paid {" + xValue + "} for " + permanent.getLogName());
+ } else {
+ game.informPlayers(player.getLogName() + " didn't pay {X} for " + permanent.getLogName());
+ }
+ } else {
+ game.informPlayers(player.getLogName() + " didn't pay {X} for " + permanent.getLogName());
+ }
+
+ PreventDamageByTargetEffect effect = new PreventDamageByTargetEffect(Duration.OneUse, xValue, false);
+ if (xValue != 0 && cost.isPaid()) {
+ effect.setTargetPointer(new FixedTarget(permanent.getId()));
+ game.addEffect(effect, source);
+ }
+ player.damage(2, source.getSourceId(), game, false, true);
+ effect.discard();
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/Progenitus.java b/Mage.Sets/src/mage/cards/p/Progenitus.java
index ecfc73fa509..afec039d10f 100644
--- a/Mage.Sets/src/mage/cards/p/Progenitus.java
+++ b/Mage.Sets/src/mage/cards/p/Progenitus.java
@@ -93,11 +93,6 @@ class ProgenitusProtectionAbility extends ProtectionAbility {
return new ProgenitusProtectionAbility(this);
}
- @Override
- public String getRule() {
- return "Protection from everything";
- }
-
@Override
public boolean canTarget(MageObject source, Game game) {
return false;
diff --git a/Mage.Sets/src/mage/cards/p/ProtectiveSphere.java b/Mage.Sets/src/mage/cards/p/ProtectiveSphere.java
new file mode 100644
index 00000000000..61b81042325
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/ProtectiveSphere.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.p;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import mage.Mana;
+import mage.ObjectColor;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.PayLifeCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.PreventionEffectImpl;
+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.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.TargetSource;
+import mage.util.CardUtil;
+
+/**
+ *
+ * @author jeffwadsworth
+ */
+public class ProtectiveSphere extends CardImpl {
+
+ public ProtectiveSphere(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
+
+ // {1}, Pay 1 life: Prevent all damage that would be dealt to you this turn by a source of your choice that shares a color with the mana spent on this activation cost.
+ Ability ability = new SimpleActivatedAbility(new ProtectiveSphereEffect(), new ManaCostsImpl("{1}"));
+ ability.addCost(new PayLifeCost(1));
+ this.addAbility(ability);
+
+ }
+
+ public ProtectiveSphere(final ProtectiveSphere card) {
+ super(card);
+ }
+
+ @Override
+ public ProtectiveSphere copy() {
+ return new ProtectiveSphere(this);
+ }
+}
+
+class ProtectiveSphereEffect extends PreventionEffectImpl {
+
+ private final TargetSource target;
+ private static Mana manaUsed;
+ private static List colorsOfChosenSource = new ArrayList<>();
+
+ public ProtectiveSphereEffect() {
+ super(Duration.EndOfTurn, Integer.MAX_VALUE, false, false);
+ this.staticText = "Prevent all damage that would be dealt to you this turn by a source of your choice that shares a color with the mana spent on this activation cost.";
+ this.target = new TargetSource();
+ }
+
+ public ProtectiveSphereEffect(final ProtectiveSphereEffect effect) {
+ super(effect);
+ this.target = effect.target.copy();
+ }
+
+ @Override
+ public ProtectiveSphereEffect copy() {
+ return new ProtectiveSphereEffect(this);
+ }
+
+ @Override
+ public void init(Ability source, Game game) {
+ target.setNotTarget(true);
+ target.setRequired(false);
+ Player controller = game.getPlayer(source.getControllerId());
+ Permanent protectiveSphere = game.getPermanent(source.getSourceId());
+ if (controller != null
+ && protectiveSphere != null) {
+ game.getState().setValue("ProtectiveSphere" + source.getSourceId().toString(), source.getManaCostsToPay().getUsedManaToPay()); //store the mana used to pay
+ protectiveSphere.addInfo("MANA USED", CardUtil.addToolTipMarkTags("Last mana used for protective ability: " + source.getManaCostsToPay().getUsedManaToPay()), game);
+ }
+ this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
+ super.init(source, game);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ return true;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ manaUsed = (Mana) game.getState().getValue("ProtectiveSphere" + source.getSourceId().toString());
+ if (super.applies(event, source, game)) {
+ if (event.getTargetId().equals(source.getControllerId())
+ && event.getSourceId().equals(target.getFirstTarget())) {
+ colorsOfChosenSource = game.getObject(target.getFirstTarget()).getColor(game).getColors();
+ if (colorsOfChosenSource.stream().anyMatch((c) -> (manaUsed.getColor(c.getColoredManaSymbol()) > 0))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/ProteusMachine.java b/Mage.Sets/src/mage/cards/p/ProteusMachine.java
new file mode 100644
index 00000000000..6fbff759cc3
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/ProteusMachine.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.p;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.continuous.BecomesChosenCreatureTypeSourceEffect;
+import mage.abilities.keyword.MorphAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+/**
+ *
+ * @author L_J
+ */
+public class ProteusMachine extends CardImpl {
+
+ public ProteusMachine(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{3}");
+ this.subtype.add(SubType.SHAPESHIFTER);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Morph {0}
+ this.addAbility(new MorphAbility(this, new ManaCostsImpl("{0}")));
+
+ // When Proteus Machine is turned face up, it becomes the creature type of your choice. (This effect lasts indefinitely.)
+ this.addAbility(new TurnedFaceUpSourceTriggeredAbility(new BecomesChosenCreatureTypeSourceEffect(false, Duration.Custom)));
+ }
+
+ public ProteusMachine(final ProteusMachine card) {
+ super(card);
+ }
+
+ @Override
+ public ProteusMachine copy() {
+ return new ProteusMachine(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/PutridCyclops.java b/Mage.Sets/src/mage/cards/p/PutridCyclops.java
new file mode 100644
index 00000000000..1dfe474b520
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/PutridCyclops.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.p;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.effects.keyword.ScryEffect;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.game.Game;
+import mage.players.Player;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class PutridCyclops extends CardImpl {
+
+ public PutridCyclops(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
+
+ this.subtype.add(SubType.ZOMBIE);
+ this.subtype.add(SubType.CYCLOPS);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // When Putrid Cyclops enters the battlefield, scry 1, then reveal the top card of your library. Putrid Cyclops gets -X/-X until end of turn, where X is that card's converted mana cost.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new PutridCyclopEffect()));
+ }
+
+ public PutridCyclops(final PutridCyclops card) {
+ super(card);
+ }
+
+ @Override
+ public PutridCyclops copy() {
+ return new PutridCyclops(this);
+ }
+}
+
+class PutridCyclopEffect extends OneShotEffect {
+
+ public PutridCyclopEffect() {
+ super(Outcome.Detriment);
+ this.staticText = "scry 1, then reveal the top card of your library. {this} gets -X/-X until end of turn, where X is that card's converted mana cost"
+ + " (To scry 1, look at the top card of your library, then you may put that card on the bottom of your library.)";
+ }
+
+ public PutridCyclopEffect(final PutridCyclopEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public PutridCyclopEffect copy() {
+ return new PutridCyclopEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ MageObject sourceObject = source.getSourceObject(game);
+ if (controller != null && sourceObject != null) {
+ new ScryEffect(1).apply(game, source);
+ Card card = controller.getLibrary().getFromTop(game);
+ if (card != null) {
+ controller.revealCards(sourceObject.getIdName(), new CardsImpl(card), game);
+ int unboost = card.getConvertedManaCost() * -1;
+ ContinuousEffect effect = new BoostSourceEffect(unboost, unboost, Duration.EndOfTurn);
+ game.addEffect(effect, source);
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/ReversePolarity.java b/Mage.Sets/src/mage/cards/r/ReversePolarity.java
new file mode 100644
index 00000000000..8e6766f700c
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/ReversePolarity.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.r;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.WatcherScope;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.watchers.Watcher;
+
+/**
+ *
+ * @author jeffwadsworth, MTGFan & L_J
+ */
+public class ReversePolarity extends CardImpl {
+
+ public ReversePolarity(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}{W}");
+
+ // You gain X life, where X is twice the damage dealt to you so far this turn by artifacts.
+ this.getSpellAbility().addEffect(new GainLifeEffect(new ReversePolarityAmount(), "You gain X life, where X is twice the damage dealt to you so far this turn by artifacts"));
+ this.getSpellAbility().addWatcher(new ReversePolarityWatcher());
+ }
+
+ public ReversePolarity(final ReversePolarity card) {
+ super(card);
+ }
+
+ @Override
+ public ReversePolarity copy() {
+ return new ReversePolarity(this);
+ }
+}
+
+class ReversePolarityAmount implements DynamicValue {
+
+ @Override
+ public int calculate(Game game, Ability source, Effect effect) {
+ ReversePolarityWatcher watcher = (ReversePolarityWatcher) game.getState().getWatchers().get(ReversePolarityWatcher.class.getSimpleName());
+ if(watcher != null) {
+ return watcher.getArtifactDamageReceivedThisTurn(source.getControllerId()) * 2;
+ }
+ return 0;
+ }
+
+ @Override
+ public ReversePolarityAmount copy() {
+ return new ReversePolarityAmount();
+ }
+
+ @Override
+ public String getMessage() {
+ return "";
+ }
+}
+
+class ReversePolarityWatcher extends Watcher {
+
+ private final Map artifactDamageReceivedThisTurn = new HashMap<>();
+
+ public ReversePolarityWatcher() {
+ super(ReversePolarityWatcher.class.getSimpleName(), WatcherScope.GAME);
+ }
+
+ public ReversePolarityWatcher(final ReversePolarityWatcher watcher) {
+ super(watcher);
+ for (Entry entry : watcher.artifactDamageReceivedThisTurn.entrySet()) {
+ artifactDamageReceivedThisTurn.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) {
+ UUID playerId = event.getTargetId();
+ if (playerId != null) {
+ Permanent permanent = game.getPermanent(event.getSourceId());
+ if (permanent != null && permanent.isArtifact()) {
+ artifactDamageReceivedThisTurn.putIfAbsent(playerId, 0);
+ artifactDamageReceivedThisTurn.compute(playerId, (k, v) -> v + event.getAmount());
+ }
+ }
+ }
+ }
+
+ public int getArtifactDamageReceivedThisTurn(UUID playerId) {
+ return artifactDamageReceivedThisTurn.getOrDefault(playerId, 0);
+ }
+
+ @Override
+ public void reset() {
+ artifactDamageReceivedThisTurn.clear();
+ }
+
+ @Override
+ public ReversePolarityWatcher copy() {
+ return new ReversePolarityWatcher(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/Runesword.java b/Mage.Sets/src/mage/cards/r/Runesword.java
new file mode 100644
index 00000000000..a5ece841531
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/Runesword.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.r;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.SacrificeTargetEffect;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.effects.common.replacement.DealtDamageToCreatureBySourceDies;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.GameEvent.EventType;
+import mage.game.permanent.Permanent;
+import mage.target.common.TargetAttackingCreature;
+import mage.target.targetpointer.FixedTarget;
+import mage.watchers.common.DamagedByWatcher;
+
+/**
+ *
+ * @author L_J
+ */
+public class Runesword extends CardImpl {
+
+ public Runesword(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}");
+
+ // {3}, {T}: Target attacking creature gets +2/+0 until end of turn.
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(2, 0, Duration.EndOfTurn), new GenericManaCost(3));
+ // When that creature leaves the battlefield this turn, sacrifice Runesword.
+ ability.addEffect(new RuneswordCreateTriggeredAbilityEffect());
+ // If the creature deals damage to a creature this turn, the creature dealt damage can't be regenerated this turn.
+ ability.addEffect(new RuneswordCantBeRegeneratedEffect());
+ // If a creature dealt damage by the targeted creature would die this turn, exile that creature instead.
+ SimpleStaticAbility ability2 = new SimpleStaticAbility(Zone.BATTLEFIELD, new DealtDamageToCreatureBySourceDies(this, Duration.Custom));
+ ability2.addWatcher(new DamagedByWatcher());
+ ability2.setRuleVisible(false);
+ ability.addEffect(new GainAbilityTargetEffect(ability2, Duration.EndOfTurn, null, false).setText(
+ "If a creature dealt damage by the targeted creature would die this turn, exile that creature instead"));
+ ability.addCost(new TapSourceCost());
+ ability.addTarget(new TargetAttackingCreature());
+ this.addAbility(ability);
+ }
+
+ public Runesword(final Runesword card) {
+ super(card);
+ }
+
+ @Override
+ public Runesword copy() {
+ return new Runesword(this);
+ }
+}
+
+class RuneswordCreateTriggeredAbilityEffect extends OneShotEffect {
+
+ public RuneswordCreateTriggeredAbilityEffect() {
+ super(Outcome.PutCreatureInPlay);
+ staticText = "When that creature leaves the battlefield this turn, sacrifice {this}";
+ }
+
+ public RuneswordCreateTriggeredAbilityEffect(final RuneswordCreateTriggeredAbilityEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent sourceObject = game.getPermanentOrLKIBattlefield(source.getSourceId());
+ Permanent targetObject = game.getPermanent(this.getTargetPointer().getFirst(game, source));
+ if (sourceObject != null && targetObject != null) {
+ Effect sacrificeEffect = new SacrificeTargetEffect("sacrifice " + sourceObject.getName());
+ sacrificeEffect.setTargetPointer(new FixedTarget(sourceObject, game));
+ LeavesBattlefieldTriggeredAbility triggerAbility = new LeavesBattlefieldTriggeredAbility(sacrificeEffect, false);
+ triggerAbility.setRuleVisible(false);
+ ContinuousEffect continuousEffect = new GainAbilityTargetEffect(triggerAbility, Duration.EndOfTurn);
+ continuousEffect.setTargetPointer(new FixedTarget(targetObject, game));
+ game.addEffect(continuousEffect, source);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public RuneswordCreateTriggeredAbilityEffect copy() {
+ return new RuneswordCreateTriggeredAbilityEffect(this);
+ }
+}
+
+class RuneswordCantBeRegeneratedEffect extends ContinuousRuleModifyingEffectImpl {
+
+ private UUID targetCreatureId;
+
+ public RuneswordCantBeRegeneratedEffect() {
+ super(Duration.EndOfTurn, Outcome.Benefit, false, false);
+ this.staticText = "If the creature deals damage to a creature this turn, the creature dealt damage can't be regenerated this turn";
+ }
+
+ public RuneswordCantBeRegeneratedEffect(final RuneswordCantBeRegeneratedEffect effect) {
+ super(effect);
+ targetCreatureId = effect.targetCreatureId;
+ }
+
+ @Override
+ public RuneswordCantBeRegeneratedEffect copy() {
+ return new RuneswordCantBeRegeneratedEffect(this);
+ }
+
+ public void init(Ability source, Game game) {
+ targetCreatureId = getTargetPointer().getFirst(game, source);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.REGENERATE;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (targetCreatureId != null) {
+ DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get(DamagedByWatcher.class.getSimpleName(), targetCreatureId);
+ if (watcher != null) {
+ return watcher.wasDamaged(event.getTargetId(), game);
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/r/Rust.java b/Mage.Sets/src/mage/cards/r/Rust.java
index 21dd121bf95..9bf2bac561a 100644
--- a/Mage.Sets/src/mage/cards/r/Rust.java
+++ b/Mage.Sets/src/mage/cards/r/Rust.java
@@ -28,17 +28,13 @@
package mage.cards.r;
import java.util.UUID;
-import mage.abilities.Ability;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AbilityType;
import mage.constants.CardType;
-import mage.filter.FilterStackObject;
-import mage.filter.predicate.Predicate;
-import mage.game.Game;
-import mage.game.stack.StackAbility;
-import mage.target.common.TargetActivatedOrTriggeredAbility;
+import mage.filter.FilterAbility;
+import mage.filter.predicate.ability.ArtifactSourcePredicate;
+import mage.target.common.TargetActivatedAbility;
/**
*
@@ -46,7 +42,7 @@ import mage.target.common.TargetActivatedOrTriggeredAbility;
*/
public class Rust extends CardImpl {
- private final static FilterStackObject filter = new FilterStackObject("activated ability from an artifact source");
+ private final static FilterAbility filter = new FilterAbility("activated ability from an artifact source");
static {
filter.add(new ArtifactSourcePredicate());
@@ -57,7 +53,7 @@ public class Rust extends CardImpl {
// Counter target activated ability from an artifact source.
this.getSpellAbility().addEffect(new CounterTargetEffect());
- this.getSpellAbility().addTarget(new TargetActivatedOrTriggeredAbility(filter));
+ this.getSpellAbility().addTarget(new TargetActivatedAbility(filter));
}
public Rust(final Rust card) {
@@ -69,22 +65,3 @@ public class Rust extends CardImpl {
return new Rust(this);
}
}
-
-class ArtifactSourcePredicate implements Predicate {
-
- public ArtifactSourcePredicate() {
- }
-
- @Override
- public boolean apply(Ability input, Game game) {
- if (input instanceof StackAbility) {
- return input.getSourceObject(game).isArtifact() && input.getAbilityType() == AbilityType.ACTIVATED;
- }
- return false;
- }
-
- @Override
- public String toString() {
- return "Source(Artifact)";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/s/ShahOfNaarIsle.java b/Mage.Sets/src/mage/cards/s/ShahOfNaarIsle.java
new file mode 100644
index 00000000000..0dc5a2fcc2e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/ShahOfNaarIsle.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.s;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.keyword.EchoAbility;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.players.Player;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class ShahOfNaarIsle extends CardImpl {
+
+ public ShahOfNaarIsle(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
+
+ this.subtype.add(SubType.EFREET);
+ this.power = new MageInt(6);
+ this.toughness = new MageInt(6);
+
+ // Trample
+ this.addAbility(TrampleAbility.getInstance());
+
+ // Echo {0}
+ this.addAbility(new EchoAbility("{0}"));
+
+ // When Shah of Naar Isle's echo cost is paid, each opponent may draw up to three cards.
+ this.addAbility(new ShahOfNaarIsleTriggeredAbility());
+ }
+
+ public ShahOfNaarIsle(final ShahOfNaarIsle card) {
+ super(card);
+ }
+
+ @Override
+ public ShahOfNaarIsle copy() {
+ return new ShahOfNaarIsle(this);
+ }
+}
+
+class ShahOfNaarIsleTriggeredAbility extends TriggeredAbilityImpl {
+
+ public ShahOfNaarIsleTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new ShahOfNaarIsleEffect(), false);
+ }
+
+ public ShahOfNaarIsleTriggeredAbility(final ShahOfNaarIsleTriggeredAbility effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ECHO_PAID;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ return getSourceId().equals(event.getSourceId());
+ }
+
+ @Override
+ public ShahOfNaarIsleTriggeredAbility copy() {
+ return new ShahOfNaarIsleTriggeredAbility(this);
+ }
+
+ @Override
+ public String getRule() {
+ return "When {this}'s echo cost is paid, " + super.getRule();
+ }
+}
+
+class ShahOfNaarIsleEffect extends OneShotEffect {
+
+ public ShahOfNaarIsleEffect() {
+ super(Outcome.DrawCard);
+ this.staticText = "each opponent may draw up to three cards";
+ }
+
+ public ShahOfNaarIsleEffect(final ShahOfNaarIsleEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ShahOfNaarIsleEffect copy() {
+ return new ShahOfNaarIsleEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ for (UUID playerId : game.getOpponents(controller.getId())) {
+ Player opponent = game.getPlayer(playerId);
+ if (opponent != null) {
+ int number = opponent.getAmount(0, 3, "Draw how many cards?", game);
+ opponent.drawCards(number, game);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/Soulblast.java b/Mage.Sets/src/mage/cards/s/Soulblast.java
index 1c9d495fcab..c6391096b60 100644
--- a/Mage.Sets/src/mage/cards/s/Soulblast.java
+++ b/Mage.Sets/src/mage/cards/s/Soulblast.java
@@ -36,7 +36,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@@ -48,14 +48,12 @@ import mage.target.common.TargetCreatureOrPlayer;
*/
public class Soulblast extends CardImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures you control");
-
public Soulblast(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R}{R}{R}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}{R}{R}");
// As an additional cost to cast Soulblast, sacrifice all creatures you control.
- this.getSpellAbility().addCost(new SacrificeAllCost(filter));
+ this.getSpellAbility().addCost(new SacrificeAllCost(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED));
+
// Soulblast deals damage to target creature or player equal to the total power of the sacrificed creatures.
this.getSpellAbility().addEffect(new SoulblastEffect());
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
@@ -90,7 +88,7 @@ class SoulblastEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
int power = 0;
- for (Cost cost :source.getCosts()) {
+ for (Cost cost : source.getCosts()) {
if (cost instanceof SacrificeAllCost) {
for (Permanent permanent : ((SacrificeAllCost) cost).getPermanents()) {
power += permanent.getPower().getValue();
diff --git a/Mage.Sets/src/mage/cards/s/SpireTracer.java b/Mage.Sets/src/mage/cards/s/SpireTracer.java
index 8c36e4d18c3..7846832cbf4 100644
--- a/Mage.Sets/src/mage/cards/s/SpireTracer.java
+++ b/Mage.Sets/src/mage/cards/s/SpireTracer.java
@@ -76,7 +76,7 @@ class CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect extends RestrictionE
public CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect() {
super(Duration.WhileOnBattlefield);
- staticText = "Can't be blocked except by creatures with flying or reach";
+ staticText = "{this} can't be blocked except by creatures with flying or reach";
}
public CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect(final CantBeBlockedExceptByCreaturesWithFlyingOrReachEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/s/SpiritCairn.java b/Mage.Sets/src/mage/cards/s/SpiritCairn.java
index 0153958df44..1d1f92e0b46 100644
--- a/Mage.Sets/src/mage/cards/s/SpiritCairn.java
+++ b/Mage.Sets/src/mage/cards/s/SpiritCairn.java
@@ -51,7 +51,7 @@ public class SpiritCairn extends CardImpl {
// Whenever a player discards a card, you may pay {W}. If you do, create a 1/1 white Spirit creature token with flying.
this.addAbility(new SimpleTriggeredAbility(Zone.BATTLEFIELD, GameEvent.EventType.DISCARDED_CARD,
new DoIfCostPaid(new CreateTokenEffect(new SpiritWhiteToken()), new ManaCostsImpl("{W}")),
- "Whenever a player discards a card, you ",
+ "Whenever a player discards a card, ",
false, false));
}
diff --git a/Mage.Sets/src/mage/cards/s/SpiritMirror.java b/Mage.Sets/src/mage/cards/s/SpiritMirror.java
index 77edaee3128..e9c03b254c6 100644
--- a/Mage.Sets/src/mage/cards/s/SpiritMirror.java
+++ b/Mage.Sets/src/mage/cards/s/SpiritMirror.java
@@ -66,7 +66,7 @@ public class SpiritMirror extends CardImpl {
this.addAbility(new ConditionalTriggeredAbility(
new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new ReflectionToken()), TargetController.YOU, false),
new PermanentsOnTheBattlefieldCondition(filterToken, ComparisonType.EQUAL_TO, 0, false),
- "At the beginning of your upkeep, if there are no Reflection tokens on the battlefield, create a 2/2 white Reflection creature token"));
+ "At the beginning of your upkeep, if there are no Reflection tokens on the battlefield, create a 2/2 white Reflection creature token."));
// {0}: Destroy target Reflection.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new GenericManaCost(0));
diff --git a/Mage.Sets/src/mage/cards/s/SteamfloggerBoss.java b/Mage.Sets/src/mage/cards/s/SteamfloggerBoss.java
new file mode 100644
index 00000000000..d613079e9a1
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SteamfloggerBoss.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.s;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.InfoEffect;
+import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
+import mage.abilities.keyword.HasteAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.filter.common.FilterCreaturePermanent;
+import static mage.filter.predicate.permanent.ControllerControlsIslandPredicate.filter;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class SteamfloggerBoss extends CardImpl {
+
+ public SteamfloggerBoss(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
+
+ this.subtype.add(SubType.GOBLIN);
+ this.subtype.add(SubType.RIGGER);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Other Rigger creatures you control get +1/+0 and have haste.
+ Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new BoostControlledEffect(1, 0, Duration.WhileOnBattlefield, new FilterCreaturePermanent(SubType.RIGGER, "Rigger creatures"), true));
+ Effect effect = new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter);
+ effect.setText("and have haste");
+ ability.addEffect(effect);
+ this.addAbility(ability);
+
+ // If a Rigger you control would assemble a Contraption, it assembles two Contraptions instead.
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("If a Rigger you control would assemble a Contraption, it assembles two Contraptions instead. (NOT IMPLEMENTED)")));
+
+ }
+
+ public SteamfloggerBoss(final SteamfloggerBoss card) {
+ super(card);
+ }
+
+ @Override
+ public SteamfloggerBoss copy() {
+ return new SteamfloggerBoss(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/StuffyDoll.java b/Mage.Sets/src/mage/cards/s/StuffyDoll.java
index 5a7a8986ac9..99f01cfe7ee 100644
--- a/Mage.Sets/src/mage/cards/s/StuffyDoll.java
+++ b/Mage.Sets/src/mage/cards/s/StuffyDoll.java
@@ -41,8 +41,8 @@ import mage.abilities.keyword.IndestructibleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -56,7 +56,7 @@ import mage.players.Player;
public class StuffyDoll extends CardImpl {
public StuffyDoll(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{5}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}");
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(0);
this.toughness = new MageInt(1);
@@ -67,7 +67,7 @@ public class StuffyDoll extends CardImpl {
this.addAbility(IndestructibleAbility.getInstance());
// Whenever Stuffy Doll is dealt damage, it deals that much damage to the chosen player.
this.addAbility(new StuffyDollTriggeredAbility());
- // {tap}: Stuffy Doll deals 1 damage to itself.
+ // {T}: Stuffy Doll deals 1 damage to itself.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageSelfEffect(1), new TapSourceCost()));
}
diff --git a/Mage.Sets/src/mage/cards/s/SultaiAscendancy.java b/Mage.Sets/src/mage/cards/s/SultaiAscendancy.java
index d516d565ad5..053e802bbd3 100644
--- a/Mage.Sets/src/mage/cards/s/SultaiAscendancy.java
+++ b/Mage.Sets/src/mage/cards/s/SultaiAscendancy.java
@@ -46,8 +46,7 @@ import mage.filter.FilterCard;
public class SultaiAscendancy extends CardImpl {
public SultaiAscendancy(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}{G}{U}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{G}{U}");
// At the beginning of your upkeep, look at the top two cards of your library. Put any number of them into your graveyard and the rest on top of your library in any order.
Effect effect = new LookLibraryAndPickControllerEffect(
diff --git a/Mage.Sets/src/mage/cards/t/TeferisProtection.java b/Mage.Sets/src/mage/cards/t/TeferisProtection.java
index 98701104c96..ec5de97c6b7 100644
--- a/Mage.Sets/src/mage/cards/t/TeferisProtection.java
+++ b/Mage.Sets/src/mage/cards/t/TeferisProtection.java
@@ -141,12 +141,7 @@ class TeferisProtectionAbility extends ProtectionAbility {
public TeferisProtectionAbility copy() {
return new TeferisProtectionAbility(this);
}
-
- @Override
- public String getRule() {
- return "Protection from everything";
- }
-
+
@Override
public boolean canTarget(MageObject source, Game game) {
return false;
diff --git a/Mage.Sets/src/mage/cards/t/TelekineticBonds.java b/Mage.Sets/src/mage/cards/t/TelekineticBonds.java
new file mode 100644
index 00000000000..7f77b779872
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TelekineticBonds.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.t;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.DiscardsACardPlayerTriggeredAbility;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.MayTapOrUntapTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.target.TargetPermanent;
+
+/**
+ *
+ * @author jeffwadsworth
+ */
+public class TelekineticBonds extends CardImpl {
+
+ public TelekineticBonds(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}{U}");
+
+
+ // Whenever a player discards a card, you may pay {1}{U}. If you do, you may tap or untap target permanent.
+ Ability ability = new DiscardsACardPlayerTriggeredAbility(new DoIfCostPaid(new MayTapOrUntapTargetEffect(), new ManaCostsImpl("{1}{U}")), true);
+ ability.addTarget(new TargetPermanent());
+ this.addAbility(ability);
+
+ }
+
+ public TelekineticBonds(final TelekineticBonds card) {
+ super(card);
+ }
+
+ @Override
+ public TelekineticBonds copy() {
+ return new TelekineticBonds(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/t/TemporaryTruce.java b/Mage.Sets/src/mage/cards/t/TemporaryTruce.java
new file mode 100644
index 00000000000..0efb4ea8dd1
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TemporaryTruce.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.t;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.players.Player;
+
+/**
+ *
+ * @author L_J
+ */
+public class TemporaryTruce extends CardImpl {
+
+ public TemporaryTruce(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{W}");
+
+ // Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life.
+ this.getSpellAbility().addEffect(new TemporaryTruceEffect());
+ }
+
+ public TemporaryTruce(final TemporaryTruce card) {
+ super(card);
+ }
+
+ @Override
+ public TemporaryTruce copy() {
+ return new TemporaryTruce(this);
+ }
+}
+
+class TemporaryTruceEffect extends OneShotEffect {
+
+ TemporaryTruceEffect() {
+ super(Outcome.DrawCard);
+ this.staticText = "Each player may draw up to two cards. For each card less than two a player draws this way, that player gains 2 life";
+ }
+
+ TemporaryTruceEffect(final TemporaryTruceEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public TemporaryTruceEffect copy() {
+ return new TemporaryTruceEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player != null) {
+ int cardsToDraw = player.getAmount(0, 2, "Draw how many cards?", game);
+ player.drawCards(cardsToDraw, game);
+ player.gainLife((2 - cardsToDraw) * 2, game);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TheFallen.java b/Mage.Sets/src/mage/cards/t/TheFallen.java
new file mode 100644
index 00000000000..ab009381c6d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TheFallen.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.t;
+
+import java.util.*;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Outcome;
+import mage.constants.TargetController;
+import mage.constants.WatcherScope;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.watchers.Watcher;
+
+/**
+ *
+ * @author L_J
+ */
+public class TheFallen extends CardImpl {
+
+ public TheFallen(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}{B}");
+ this.subtype.add(SubType.ZOMBIE);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // At the beginning of your upkeep, The Fallen deals 1 damage to each opponent it has dealt damage to this game.
+ this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TheFallenEffect(), TargetController.YOU, false), new TheFallenWatcher());
+ }
+
+ public TheFallen(final TheFallen card) {
+ super(card);
+ }
+
+ @Override
+ public TheFallen copy() {
+ return new TheFallen(this);
+ }
+}
+
+class TheFallenEffect extends OneShotEffect {
+
+ public TheFallenEffect() {
+ super(Outcome.Damage);
+ this.staticText = "{this} deals 1 damage to each opponent it has dealt damage to this game";
+ }
+
+ public TheFallenEffect(final TheFallenEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public TheFallenEffect copy() {
+ return new TheFallenEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ TheFallenWatcher watcher = (TheFallenWatcher) game.getState().getWatchers().get(TheFallenWatcher.class.getSimpleName());
+ if (watcher != null && watcher.getPlayerDealtDamageThisGame(source.getSourceId()) != null) {
+ for (UUID playerId : watcher.getPlayerDealtDamageThisGame(source.getSourceId())) {
+ if (!source.getControllerId().equals(playerId)) {
+ Player player = game.getPlayer(playerId);
+ if (player != null) {
+ player.damage(1, source.getSourceId(), game, false, true);
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+}
+
+class TheFallenWatcher extends Watcher {
+
+ private Map> playersDealtDamageThisGame = new HashMap<>(); // Map>
+
+ public TheFallenWatcher() {
+ super(TheFallenWatcher.class.getSimpleName(), WatcherScope.GAME);
+ }
+
+ public TheFallenWatcher(final TheFallenWatcher watcher) {
+ super(watcher);
+ playersDealtDamageThisGame = new HashMap<>(watcher.playersDealtDamageThisGame);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) {
+ Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
+ if (permanent != null) {
+ Set toAdd;
+ if (playersDealtDamageThisGame.get(event.getSourceId()) == null) {
+ toAdd = new HashSet<>();
+ } else {
+ toAdd = playersDealtDamageThisGame.get(event.getSourceId());
+ }
+ toAdd.add(event.getPlayerId());
+ playersDealtDamageThisGame.put(event.getSourceId(), toAdd);
+ }
+ }
+ }
+
+ public Set getPlayerDealtDamageThisGame(UUID creatureId) {
+ return playersDealtDamageThisGame.get(creatureId);
+ }
+
+ @Override
+ public TheFallenWatcher copy() {
+ return new TheFallenWatcher(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TheImmortalSun.java b/Mage.Sets/src/mage/cards/t/TheImmortalSun.java
index 4b1fa19c8a7..8b303e3e38e 100644
--- a/Mage.Sets/src/mage/cards/t/TheImmortalSun.java
+++ b/Mage.Sets/src/mage/cards/t/TheImmortalSun.java
@@ -68,7 +68,7 @@ public class TheImmortalSun extends CardImpl {
this.addAbility(new BeginningOfDrawTriggeredAbility(new DrawCardSourceControllerEffect(1)
.setText("draw an additional card"), TargetController.YOU, false));
// Spells you cast cost {1} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCard("Spells you cast"), 1)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCard("Spells"), 1)));
// Creatures you control get +1/+1.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield)));
}
diff --git a/Mage.Sets/src/mage/cards/t/ThunderbladeCharge.java b/Mage.Sets/src/mage/cards/t/ThunderbladeCharge.java
new file mode 100644
index 00000000000..658c9920ecd
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/ThunderbladeCharge.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.t;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DoIfCostPaid;
+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.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetCreatureOrPlayer;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class ThunderbladeCharge extends CardImpl {
+
+ public ThunderbladeCharge(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}{R}");
+
+ // Thunderblade Charge deals 3 damage to target creature or player.
+ this.getSpellAbility().addEffect(new DamageTargetEffect(3));
+ this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
+
+ // Whenever one or more creatures you control deal combat damage to a player, if Thunderblade Charge is in your graveyard, you may pay {2}{R}{R}{R}. If you do, you may cast it without paying its mana cost.
+ this.addAbility(new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(Zone.GRAVEYARD,
+ new DoIfCostPaid(new ThunderbladeChargeCastEffect(), new ManaCostsImpl("{2}{R}{R}{R}"))
+ .setText("if {this} is in your graveyard, you may pay {2}{R}{R}{R}. If you do, you may cast it without paying its mana cost")));
+ }
+
+ public ThunderbladeCharge(final ThunderbladeCharge card) {
+ super(card);
+ }
+
+ @Override
+ public ThunderbladeCharge copy() {
+ return new ThunderbladeCharge(this);
+ }
+}
+
+class ThunderbladeChargeCastEffect extends OneShotEffect {
+
+ public ThunderbladeChargeCastEffect() {
+ super(Outcome.PutCreatureInPlay);
+ this.staticText = "you may cast {this} without paying its mana cost";
+ }
+
+ public ThunderbladeChargeCastEffect(final ThunderbladeChargeCastEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ThunderbladeChargeCastEffect copy() {
+ return new ThunderbladeChargeCastEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ Card sourceCard = game.getCard(source.getSourceId());
+ if (controller != null
+ && sourceCard != null
+ && Zone.GRAVEYARD == game.getState().getZone(sourceCard.getId())) {
+ controller.cast(sourceCard.getSpellAbility(), game, true);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java
index 504c68648cc..79e9e389ec3 100644
--- a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java
+++ b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java
@@ -86,7 +86,7 @@ class TormentOfHailfireEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int repeat = source.getManaCostsToPay().getX();
- for (int i = 0; i < repeat; i++) {
+ for (int i = 1; i <= repeat; i++) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
Player opponent = game.getPlayer(opponentId);
if (opponent != null) {
@@ -97,8 +97,9 @@ class TormentOfHailfireEffect extends OneShotEffect {
if (opponent.choose(outcome, target, source.getSourceId(), game)) {
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null) {
- permanent.sacrifice(source.getSourceId(), game);
- continue;
+ if (permanent.sacrifice(source.getSourceId(), game)) {
+ continue;
+ }
}
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TorporOrb.java b/Mage.Sets/src/mage/cards/t/TorporOrb.java
index 8aafc5c2971..8375b7c62af 100644
--- a/Mage.Sets/src/mage/cards/t/TorporOrb.java
+++ b/Mage.Sets/src/mage/cards/t/TorporOrb.java
@@ -30,6 +30,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
+import mage.abilities.TriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.cards.CardImpl;
@@ -51,7 +52,7 @@ import mage.game.permanent.Permanent;
public class TorporOrb extends CardImpl {
public TorporOrb(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// Creatures entering the battlefield don't cause abilities to trigger.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TorporOrbEffect()));
@@ -89,7 +90,7 @@ class TorporOrbEffect extends ContinuousRuleModifyingEffectImpl {
if (ability != null && ability.getAbilityType() == AbilityType.TRIGGERED) {
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
if (permanent != null && permanent.isCreature()) {
- return true;
+ return (((TriggeredAbility) ability).checkTrigger(event, game));
}
}
return false;
@@ -97,10 +98,15 @@ class TorporOrbEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
- MageObject mageObject = game.getObject(event.getSourceId());
+ MageObject enteringObject = game.getObject(event.getSourceId());
MageObject sourceObject = game.getObject(source.getSourceId());
- if (mageObject != null && sourceObject != null) {
- return sourceObject.getLogName() + " prevented ability of " + mageObject.getLogName() + " to trigger";
+ Ability ability = (Ability) getValue("targetAbility");
+ if (enteringObject != null && sourceObject != null && ability != null) {
+ MageObject abilitObject = game.getObject(ability.getSourceId());
+ if (abilitObject != null) {
+ return sourceObject.getLogName() + " prevented ability of " + abilitObject.getLogName()
+ + " to trigger for " + enteringObject.getLogName() + " entering the battlefield.";
+ }
}
return null;
}
diff --git a/Mage.Sets/src/mage/cards/t/TreacherousPitDweller.java b/Mage.Sets/src/mage/cards/t/TreacherousPitDweller.java
index aeb1ccac8f9..16429b4734f 100644
--- a/Mage.Sets/src/mage/cards/t/TreacherousPitDweller.java
+++ b/Mage.Sets/src/mage/cards/t/TreacherousPitDweller.java
@@ -29,6 +29,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.ContinuousEffectImpl;
@@ -49,7 +50,7 @@ import mage.target.common.TargetOpponent;
public class TreacherousPitDweller extends CardImpl {
public TreacherousPitDweller(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}");
this.subtype.add(SubType.DEMON);
this.power = new MageInt(4);
@@ -77,24 +78,24 @@ class TreacherousPitDwellerTriggeredAbility extends TriggeredAbilityImpl {
private static final String ruleText = "When {this} enters the battlefield from a graveyard, ";
public TreacherousPitDwellerTriggeredAbility() {
- super(Zone.BATTLEFIELD, new TreacherousPitDwellerEffect(),false);
+ super(Zone.BATTLEFIELD, new TreacherousPitDwellerEffect(), false);
addTarget(new TargetOpponent());
}
public TreacherousPitDwellerTriggeredAbility(final TreacherousPitDwellerTriggeredAbility ability) {
super(ability);
}
-
+
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
-
+
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- return event.getTargetId().equals(getSourceId()) && ((EntersTheBattlefieldEvent) event).getFromZone() == Zone.GRAVEYARD;
- }
-
+ return event.getTargetId().equals(getSourceId()) && ((EntersTheBattlefieldEvent) event).getFromZone() == Zone.GRAVEYARD;
+ }
+
@Override
public TreacherousPitDwellerTriggeredAbility copy() {
return new TreacherousPitDwellerTriggeredAbility(this);
@@ -104,7 +105,7 @@ class TreacherousPitDwellerTriggeredAbility extends TriggeredAbilityImpl {
public String getRule() {
return ruleText + super.getRule();
}
-
+
}
class TreacherousPitDwellerEffect extends ContinuousEffectImpl {
@@ -125,10 +126,12 @@ class TreacherousPitDwellerEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
- Permanent permanent = (Permanent) source.getSourceObjectIfItStillExists(game);
+ MageObject permanent = source.getSourceObjectIfItStillExists(game); // it can also return Card object
Player targetOpponent = game.getPlayer(source.getFirstTarget());
- if (permanent != null && targetOpponent != null) {
- return permanent.changeControllerId(targetOpponent.getId(), game);
+ if (permanent != null
+ && (permanent instanceof Permanent)
+ && targetOpponent != null) {
+ return ((Permanent) permanent).changeControllerId(targetOpponent.getId(), game);
} else {
discard();
}
diff --git a/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java b/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java
new file mode 100644
index 00000000000..68cbfa766db
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/v/VodalianWarMachine.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.v;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.UUID;
+import mage.MageInt;
+import mage.MageObjectReference;
+import mage.abilities.Ability;
+import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.Cost;
+import mage.abilities.costs.common.TapTargetCost;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.keyword.DefenderAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.WatcherScope;
+import mage.constants.Zone;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.SubtypePredicate;
+import mage.filter.predicate.permanent.TappedPredicate;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.ZoneChangeEvent;
+import mage.game.permanent.Permanent;
+import mage.game.stack.StackAbility;
+import mage.target.common.TargetControlledCreaturePermanent;
+import mage.watchers.Watcher;
+
+/**
+ *
+ * @author L_J
+ */
+public class VodalianWarMachine extends CardImpl {
+
+ private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Merfolk you control");
+
+ static {
+ filter.add(Predicates.not(new TappedPredicate()));
+ filter.add(new SubtypePredicate(SubType.MERFOLK));
+ }
+
+ public VodalianWarMachine(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}");
+ this.subtype.add(SubType.WALL);
+ this.power = new MageInt(0);
+ this.toughness = new MageInt(4);
+
+ // Defender
+ this.addAbility(DefenderAbility.getInstance());
+
+ // Tap an untapped Merfolk you control: Vodalian War Machine can attack this turn as though it didn't have defender.
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true)));
+ this.addAbility(ability);
+
+ // Tap an untapped Merfolk you control: Vodalian War Machine gets +2/+1 until end of turn.
+ this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(2, 1, Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))));
+
+ // When Vodalian War Machine dies, destroy all Merfolk tapped this turn to pay for its abilities.
+ this.addAbility(new VodalianWarMachineTriggeredAbility(), new VodalianWarMachineWatcher());
+ }
+
+ public VodalianWarMachine(final VodalianWarMachine card) {
+ super(card);
+ }
+
+ @Override
+ public VodalianWarMachine copy() {
+ return new VodalianWarMachine(this);
+ }
+}
+
+class VodalianWarMachineTriggeredAbility extends DiesTriggeredAbility {
+
+ public VodalianWarMachineTriggeredAbility() {
+ super(new VodalianWarMachineEffect(), false);
+ }
+
+ public VodalianWarMachineTriggeredAbility(VodalianWarMachineTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public VodalianWarMachineTriggeredAbility copy() {
+ return new VodalianWarMachineTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ Permanent before = ((ZoneChangeEvent) event).getTarget();
+ if (before == null) {
+ return false;
+ }
+ if (super.checkTrigger(event, game)) {
+ ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
+ if (zEvent.getTarget().isTransformable()) {
+ if (!zEvent.getTarget().getAbilities().contains(this)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+}
+
+class VodalianWarMachineEffect extends OneShotEffect {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Merfolk tapped this turn to pay for its abilities");
+
+ static {
+ filter.add(new SubtypePredicate(SubType.MERFOLK));
+ }
+
+ public VodalianWarMachineEffect() {
+ super(Outcome.Detriment);
+ staticText = "destroy all " + filter.getMessage();
+ }
+
+ public VodalianWarMachineEffect(final VodalianWarMachineEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public VodalianWarMachineEffect copy() {
+ return new VodalianWarMachineEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
+ if (sourcePermanent != null) {
+ VodalianWarMachineWatcher watcher = (VodalianWarMachineWatcher) game.getState().getWatchers().get(VodalianWarMachineWatcher.class.getSimpleName());
+ if (watcher != null && watcher.getTappedMerfolkIds(sourcePermanent, game) != null) {
+ for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
+ if (watcher.getTappedMerfolkIds(sourcePermanent, game).contains(new MageObjectReference(permanent, game))) {
+ permanent.destroy(source.getSourceId(), game, false);
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
+
+class VodalianWarMachineWatcher extends Watcher {
+
+ public Map> tappedMerfolkIds = new HashMap<>();
+
+ public VodalianWarMachineWatcher() {
+ super(VodalianWarMachineWatcher.class.getSimpleName(), WatcherScope.GAME);
+ }
+
+ public VodalianWarMachineWatcher(final VodalianWarMachineWatcher watcher) {
+ super(watcher);
+ // We have for sure to use copied collections, but there is no need to copy the MageObjectReference objects.
+ for (Entry> entry : watcher.tappedMerfolkIds.entrySet()) {
+ this.tappedMerfolkIds.put(entry.getKey(), new HashSet<>(entry.getValue()));
+ }
+ }
+
+ @Override
+ public VodalianWarMachineWatcher copy() {
+ return new VodalianWarMachineWatcher(this);
+ }
+
+ public Set getTappedMerfolkIds(Permanent permanent, Game game) {
+ return tappedMerfolkIds.get(new MageObjectReference(permanent, game));
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() == GameEvent.EventType.ACTIVATED_ABILITY) {
+ if (event.getSourceId() != null) {
+ Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
+ if (sourcePermanent != null) {
+ StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
+ if (stackAbility != null) {
+ Ability ability = stackAbility.getStackAbility();
+ if (ability != null) {
+ for (Cost cost : ability.getCosts()) {
+ if (cost instanceof TapTargetCost && cost.isPaid()) {
+ TapTargetCost tapCost = (TapTargetCost) cost;
+ if (tapCost.getTarget().isChosen()) {
+ MageObjectReference mor = new MageObjectReference(sourcePermanent.getId(), sourcePermanent.getZoneChangeCounter(game), game);
+ Set toAdd;
+ if (tappedMerfolkIds.get(mor) == null) {
+ toAdd = new HashSet<>();
+ } else {
+ toAdd = tappedMerfolkIds.get(mor);
+ }
+ for (UUID targetId : tapCost.getTarget().getTargets()) {
+ toAdd.add(new MageObjectReference(targetId, game));
+ }
+ tappedMerfolkIds.put(mor, toAdd);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ tappedMerfolkIds.clear();
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/w/WarriorsStand.java b/Mage.Sets/src/mage/cards/w/WarriorsStand.java
new file mode 100644
index 00000000000..52b4327e479
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/w/WarriorsStand.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.w;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
+import mage.abilities.condition.common.AttackedThisStepCondition;
+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.PhaseStep;
+import mage.constants.TurnPhase;
+import mage.filter.StaticFilters;
+import mage.watchers.common.PlayerAttackedStepWatcher;
+/**
+ *
+ * @author L_J
+ */
+public class WarriorsStand extends CardImpl {
+
+ public WarriorsStand(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
+
+ // Cast Warrior's Stand only during the declare attackers step and only if you've been attacked this step.
+ Ability ability = new CastOnlyDuringPhaseStepSourceAbility(
+ TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance,
+ "Cast {this} only during the declare attackers step and only if you've been attacked this step."
+ );
+ ability.addWatcher(new PlayerAttackedStepWatcher());
+ this.addAbility(ability);
+
+ // Creatures you control get +2/+2 until end of turn.
+ this.getSpellAbility().addEffect(new BoostControlledEffect(2, 2, Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE, false));
+ }
+
+ public WarriorsStand(final WarriorsStand card) {
+ super(card);
+ }
+
+ @Override
+ public WarriorsStand copy() {
+ return new WarriorsStand(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/w/WhipgrassEntangler.java b/Mage.Sets/src/mage/cards/w/WhipgrassEntangler.java
new file mode 100644
index 00000000000..d026b9cd903
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/w/WhipgrassEntangler.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.w;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.mana.ManaCosts;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.effects.common.combat.CantAttackBlockUnlessPaysSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Duration;
+import mage.constants.Zone;
+import mage.filter.FilterPermanent;
+import mage.filter.predicate.mageobject.SubtypePredicate;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.target.common.TargetCreaturePermanent;
+
+/**
+ *
+ * @author emerald000 & L_J
+ */
+public class WhipgrassEntangler extends CardImpl {
+
+ public WhipgrassEntangler(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(3);
+
+ // {1}{W}: Until end of turn, target creature gains "This creature can't attack or block unless its controller pays {1} for each Cleric on the battlefield."
+ Ability abilityToGain = new SimpleStaticAbility(Zone.BATTLEFIELD, new WhipgrassEntanglerCantAttackUnlessYouPayEffect());
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
+ new GainAbilityTargetEffect(abilityToGain, Duration.EndOfTurn).setText("Until end of turn, target creature gains \"This creature can't attack or block unless its controller pays {1} for each Cleric on the battlefield.\""),
+ new ManaCostsImpl("{1}{W}"));
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+
+ }
+
+ public WhipgrassEntangler(final WhipgrassEntangler card) {
+ super(card);
+ }
+
+ @Override
+ public WhipgrassEntangler copy() {
+ return new WhipgrassEntangler(this);
+ }
+}
+
+class WhipgrassEntanglerCantAttackUnlessYouPayEffect extends CantAttackBlockUnlessPaysSourceEffect {
+
+ private static final FilterPermanent filter = new FilterPermanent("Cleric on the battlefield");
+
+ static {
+ filter.add(new SubtypePredicate(SubType.CLERIC));
+ }
+
+ WhipgrassEntanglerCantAttackUnlessYouPayEffect() {
+ super(new ManaCostsImpl("{0}"), RestrictType.ATTACK_AND_BLOCK);
+ staticText = "This creature can't attack or block unless its controller pays {1} for each Cleric on the battlefield";
+ }
+
+ WhipgrassEntanglerCantAttackUnlessYouPayEffect(WhipgrassEntanglerCantAttackUnlessYouPayEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ return source.getSourceId().equals(event.getSourceId());
+ }
+
+ @Override
+ public ManaCosts getManaCostToPay(GameEvent event, Ability source, Game game) {
+ Permanent sourceObject = game.getPermanent(source.getSourceId());
+ if (sourceObject != null) {
+ int payment = new PermanentsOnBattlefieldCount(filter).calculate(game, source, this);
+ if (payment > 0) {
+ return new ManaCostsImpl<>("{" + payment + '}');
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public WhipgrassEntanglerCantAttackUnlessYouPayEffect copy() {
+ return new WhipgrassEntanglerCantAttackUnlessYouPayEffect(this);
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/w/WickedReward.java b/Mage.Sets/src/mage/cards/w/WickedReward.java
index 90499a3f4a8..9261954c8de 100644
--- a/Mage.Sets/src/mage/cards/w/WickedReward.java
+++ b/Mage.Sets/src/mage/cards/w/WickedReward.java
@@ -8,6 +8,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.common.TargetControlledCreaturePermanent;
+import mage.target.common.TargetCreaturePermanent;
public class WickedReward extends CardImpl {
@@ -19,6 +20,7 @@ public class WickedReward extends CardImpl {
//Target creature gets +4/+2 until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(4, 2, Duration.EndOfTurn));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
public WickedReward(WickedReward other){
diff --git a/Mage.Sets/src/mage/cards/w/WindShear.java b/Mage.Sets/src/mage/cards/w/WindShear.java
new file mode 100644
index 00000000000..4d70f93c00f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/w/WindShear.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.w;
+
+import java.util.UUID;
+import mage.abilities.effects.common.continuous.BoostAllEffect;
+import mage.abilities.effects.common.continuous.LoseAbilityAllEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.filter.common.FilterAttackingCreature;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+
+/**
+ *
+ * @author L_J
+ */
+public class WindShear extends CardImpl {
+
+ private static final FilterAttackingCreature filter = new FilterAttackingCreature("Attacking creatures with flying");
+
+ static {
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ }
+
+ public WindShear(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{G}");
+
+ // Attacking creatures with flying get -2/-2 and lose flying until end of turn.
+ this.getSpellAbility().addEffect(new BoostAllEffect(-2, -2, Duration.EndOfTurn, filter, false).setText("Attacking creatures with flying get -2/-2"));
+ this.getSpellAbility().addEffect(new LoseAbilityAllEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, filter).setText("and lose flying until end of turn"));
+ }
+
+ public WindShear(final WindShear card) {
+ super(card);
+ }
+
+ @Override
+ public WindShear copy() {
+ return new WindShear(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/w/WoodElemental.java b/Mage.Sets/src/mage/cards/w/WoodElemental.java
new file mode 100644
index 00000000000..ac6bc424c7e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/w/WoodElemental.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.cards.w;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.AsEntersBattlefieldAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.InfoEffect;
+import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubLayer;
+import mage.constants.Zone;
+import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.SubtypePredicate;
+import mage.filter.predicate.permanent.TappedPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.Target;
+import mage.target.common.TargetControlledPermanent;
+
+/**
+ *
+ * @author L_J
+ */
+public class WoodElemental extends CardImpl {
+
+ public WoodElemental(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
+ this.subtype.add(SubType.ELEMENTAL);
+ this.power = new MageInt(0);
+ this.toughness = new MageInt(0);
+
+ // As Wood Elemental enters the battlefield, sacrifice any number of untapped Forests.
+ this.addAbility(new AsEntersBattlefieldAbility(new WoodElementalEffect()));
+
+ // Wood Elemental's power and toughness are each equal to the number of Forests sacrificed as it entered the battlefield.
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the number of Forests sacrificed as it entered the battlefield")));
+ }
+
+ public WoodElemental(final WoodElemental card) {
+ super(card);
+ }
+
+ @Override
+ public WoodElemental copy() {
+ return new WoodElemental(this);
+ }
+}
+
+class WoodElementalEffect extends OneShotEffect {
+
+ private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Forests you control");
+
+ static {
+ filter.add(Predicates.not(new TappedPredicate()));
+ filter.add(new SubtypePredicate(SubType.FOREST));
+ }
+
+ public WoodElementalEffect() {
+ super(Outcome.Sacrifice);
+ staticText = "sacrifice any number of untapped Forests";
+ }
+
+ public WoodElementalEffect(final WoodElementalEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public WoodElementalEffect copy() {
+ return new WoodElementalEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ Card sourceCard = game.getCard(source.getSourceId());
+ if (controller != null && sourceCard != null) {
+ Target target = new TargetControlledPermanent(0, Integer.MAX_VALUE, filter, true);
+ if (target.canChoose(source.getSourceId(), source.getControllerId(), game)
+ && controller.chooseTarget(Outcome.Detriment, target, source, game)) {
+ if (!target.getTargets().isEmpty()) {
+ int sacrificedForests = target.getTargets().size();
+ game.informPlayers(controller.getLogName() + " sacrifices " + sacrificedForests + " untapped Forests for " + sourceCard.getLogName());
+ for (UUID targetId : target.getTargets()) {
+ Permanent targetPermanent = game.getPermanent(targetId);
+ if (targetPermanent != null) {
+ targetPermanent.sacrifice(source.getSourceId(), game);
+ }
+ }
+ game.addEffect(new SetPowerToughnessSourceEffect(sacrificedForests, sacrificedForests, Duration.Custom, SubLayer.SetPT_7b), source);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/sets/Antiquities.java b/Mage.Sets/src/mage/sets/Antiquities.java
index e64f3108eaa..80b2acc03fe 100644
--- a/Mage.Sets/src/mage/sets/Antiquities.java
+++ b/Mage.Sets/src/mage/sets/Antiquities.java
@@ -111,6 +111,7 @@ public class Antiquities extends ExpansionSet {
cards.add(new SetCardInfo("Primal Clay", 26, Rarity.UNCOMMON, mage.cards.p.PrimalClay.class));
cards.add(new SetCardInfo("Rakalite", 27, Rarity.UNCOMMON, mage.cards.r.Rakalite.class));
cards.add(new SetCardInfo("Reconstruction", 56, Rarity.COMMON, mage.cards.r.Reconstruction.class));
+ cards.add(new SetCardInfo("Reverse Polarity", 100, Rarity.COMMON, mage.cards.r.ReversePolarity.class));
cards.add(new SetCardInfo("Rocket Launcher", 28, Rarity.UNCOMMON, mage.cards.r.RocketLauncher.class));
cards.add(new SetCardInfo("Sage of Lat-Nam", 57, Rarity.COMMON, mage.cards.s.SageOfLatNam.class));
cards.add(new SetCardInfo("Shapeshifter", 29, Rarity.RARE, mage.cards.s.Shapeshifter.class));
diff --git a/Mage.Sets/src/mage/sets/Chronicles.java b/Mage.Sets/src/mage/sets/Chronicles.java
index 44a3c47cfea..75eb7d6636c 100644
--- a/Mage.Sets/src/mage/sets/Chronicles.java
+++ b/Mage.Sets/src/mage/sets/Chronicles.java
@@ -128,6 +128,7 @@ public class Chronicles extends ExpansionSet {
cards.add(new SetCardInfo("Repentant Blacksmith", 67, Rarity.COMMON, mage.cards.r.RepentantBlacksmith.class));
cards.add(new SetCardInfo("Revelation", 40, Rarity.RARE, mage.cards.r.Revelation.class));
cards.add(new SetCardInfo("Rubinia Soulsinger", 118, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class));
+ cards.add(new SetCardInfo("Runesword", 86, Rarity.COMMON, mage.cards.r.Runesword.class));
cards.add(new SetCardInfo("Safe Haven", 93, Rarity.RARE, mage.cards.s.SafeHaven.class));
cards.add(new SetCardInfo("Scavenger Folk", 41, Rarity.COMMON, mage.cards.s.ScavengerFolk.class));
cards.add(new SetCardInfo("Sentinel", 87, Rarity.RARE, mage.cards.s.Sentinel.class));
@@ -139,6 +140,7 @@ public class Chronicles extends ExpansionSet {
cards.add(new SetCardInfo("Stangg", 121, Rarity.RARE, mage.cards.s.Stangg.class));
cards.add(new SetCardInfo("Storm Seeker", 42, Rarity.UNCOMMON, mage.cards.s.StormSeeker.class));
cards.add(new SetCardInfo("Teleport", 26, Rarity.RARE, mage.cards.t.Teleport.class));
+ cards.add(new SetCardInfo("The Fallen", 10, Rarity.UNCOMMON, mage.cards.t.TheFallen.class));
cards.add(new SetCardInfo("The Wretched", 11, Rarity.RARE, mage.cards.t.TheWretched.class));
cards.add(new SetCardInfo("Tobias Andrion", 122, Rarity.UNCOMMON, mage.cards.t.TobiasAndrion.class));
cards.add(new SetCardInfo("Tormod's Crypt", 89, Rarity.COMMON, mage.cards.t.TormodsCrypt.class));
diff --git a/Mage.Sets/src/mage/sets/Exodus.java b/Mage.Sets/src/mage/sets/Exodus.java
index 851bd916498..7c4066522ad 100644
--- a/Mage.Sets/src/mage/sets/Exodus.java
+++ b/Mage.Sets/src/mage/sets/Exodus.java
@@ -123,6 +123,7 @@ public class Exodus extends ExpansionSet {
cards.add(new SetCardInfo("Pandemonium", 93, Rarity.RARE, mage.cards.p.Pandemonium.class));
cards.add(new SetCardInfo("Peace of Mind", 13, Rarity.UNCOMMON, mage.cards.p.PeaceOfMind.class));
cards.add(new SetCardInfo("Pegasus Stampede", 14, Rarity.UNCOMMON, mage.cards.p.PegasusStampede.class));
+ cards.add(new SetCardInfo("Penance", 15, Rarity.UNCOMMON, mage.cards.p.Penance.class));
cards.add(new SetCardInfo("Pit Spawn", 70, Rarity.RARE, mage.cards.p.PitSpawn.class));
cards.add(new SetCardInfo("Plaguebearer", 71, Rarity.RARE, mage.cards.p.Plaguebearer.class));
cards.add(new SetCardInfo("Plated Rootwalla", 116, Rarity.COMMON, mage.cards.p.PlatedRootwalla.class));
diff --git a/Mage.Sets/src/mage/sets/FallenEmpires.java b/Mage.Sets/src/mage/sets/FallenEmpires.java
index 224a0628318..a6a5870493a 100644
--- a/Mage.Sets/src/mage/sets/FallenEmpires.java
+++ b/Mage.Sets/src/mage/sets/FallenEmpires.java
@@ -268,6 +268,7 @@ public class FallenEmpires extends ExpansionSet {
cards.add(new SetCardInfo("Vodalian Soldiers", 63, Rarity.COMMON, VodalianSoldiers.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Vodalian Soldiers", 64, Rarity.COMMON, VodalianSoldiers.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Vodalian Soldiers", 65, Rarity.COMMON, VodalianSoldiers.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Vodalian War Machine", 66, Rarity.RARE, mage.cards.v.VodalianWarMachine.class));
cards.add(new SetCardInfo("Zelyon Sword", 176, Rarity.RARE, mage.cards.z.ZelyonSword.class));
}
}
diff --git a/Mage.Sets/src/mage/sets/FourthEdition.java b/Mage.Sets/src/mage/sets/FourthEdition.java
index 3b5f2616571..0b5d5d5f421 100644
--- a/Mage.Sets/src/mage/sets/FourthEdition.java
+++ b/Mage.Sets/src/mage/sets/FourthEdition.java
@@ -142,6 +142,7 @@ public class FourthEdition extends ExpansionSet {
cards.add(new SetCardInfo("Phantasmal Terrain", 89, Rarity.COMMON, mage.cards.p.PhantasmalTerrain.class));
cards.add(new SetCardInfo("Phantom Monster", 90, Rarity.UNCOMMON, mage.cards.p.PhantomMonster.class));
cards.add(new SetCardInfo("Pirate Ship", 91, Rarity.RARE, mage.cards.p.PirateShip.class));
+ cards.add(new SetCardInfo("Power Leak", 92, Rarity.COMMON, mage.cards.p.PowerLeak.class));
cards.add(new SetCardInfo("Power Sink", 93, Rarity.COMMON, mage.cards.p.PowerSink.class));
cards.add(new SetCardInfo("Prodigal Sorcerer", 94, Rarity.COMMON, mage.cards.p.ProdigalSorcerer.class));
cards.add(new SetCardInfo("Psionic Entity", 95, Rarity.RARE, mage.cards.p.PsionicEntity.class));
@@ -263,6 +264,7 @@ public class FourthEdition extends ExpansionSet {
cards.add(new SetCardInfo("Giant Strength", 196, Rarity.COMMON, mage.cards.g.GiantStrength.class));
cards.add(new SetCardInfo("Goblin Balloon Brigade", 197, Rarity.UNCOMMON, mage.cards.g.GoblinBalloonBrigade.class));
cards.add(new SetCardInfo("Goblin King", 198, Rarity.RARE, mage.cards.g.GoblinKing.class));
+ cards.add(new SetCardInfo("Goblin Rock Sled", 199, Rarity.COMMON, mage.cards.g.GoblinRockSled.class));
cards.add(new SetCardInfo("Gray Ogre", 200, Rarity.COMMON, mage.cards.g.GrayOgre.class));
cards.add(new SetCardInfo("Hill Giant", 201, Rarity.COMMON, mage.cards.h.HillGiant.class));
cards.add(new SetCardInfo("Hurloon Minotaur", 202, Rarity.COMMON, mage.cards.h.HurloonMinotaur.class));
diff --git a/Mage.Sets/src/mage/sets/FutureSight.java b/Mage.Sets/src/mage/sets/FutureSight.java
index 9f578ac5ff6..f1ff59de3c8 100644
--- a/Mage.Sets/src/mage/sets/FutureSight.java
+++ b/Mage.Sets/src/mage/sets/FutureSight.java
@@ -171,6 +171,7 @@ public class FutureSight extends ExpansionSet {
cards.add(new SetCardInfo("Petrified Plating", 133, Rarity.COMMON, mage.cards.p.PetrifiedPlating.class));
cards.add(new SetCardInfo("Phosphorescent Feast", 149, Rarity.UNCOMMON, mage.cards.p.PhosphorescentFeast.class));
cards.add(new SetCardInfo("Pooling Venom", 74, Rarity.UNCOMMON, mage.cards.p.PoolingVenom.class));
+ cards.add(new SetCardInfo("Putrid Cyclops", 75, Rarity.COMMON, mage.cards.p.PutridCyclops.class));
cards.add(new SetCardInfo("Pyromancer's Swath", 104, Rarity.RARE, mage.cards.p.PyromancersSwath.class));
cards.add(new SetCardInfo("Quagnoth", 150, Rarity.RARE, mage.cards.q.Quagnoth.class));
cards.add(new SetCardInfo("Quiet Disrepair", 134, Rarity.COMMON, mage.cards.q.QuietDisrepair.class));
@@ -189,6 +190,7 @@ public class FutureSight extends ExpansionSet {
cards.add(new SetCardInfo("Scout's Warning", 16, Rarity.RARE, mage.cards.s.ScoutsWarning.class));
cards.add(new SetCardInfo("Second Wind", 57, Rarity.UNCOMMON, mage.cards.s.SecondWind.class));
cards.add(new SetCardInfo("Seht's Tiger", 31, Rarity.RARE, mage.cards.s.SehtsTiger.class));
+ cards.add(new SetCardInfo("Shah of Naar Isle", 119, Rarity.RARE, mage.cards.s.ShahOfNaarIsle.class));
cards.add(new SetCardInfo("Shapeshifter's Marrow", 58, Rarity.RARE, mage.cards.s.ShapeshiftersMarrow.class));
cards.add(new SetCardInfo("Shimian Specter", 76, Rarity.RARE, mage.cards.s.ShimianSpecter.class));
cards.add(new SetCardInfo("Shivan Sand-Mage", 108, Rarity.UNCOMMON, mage.cards.s.ShivanSandMage.class));
@@ -206,6 +208,7 @@ public class FutureSight extends ExpansionSet {
cards.add(new SetCardInfo("Spirit en-Dal", 17, Rarity.UNCOMMON, mage.cards.s.SpiritEnDal.class));
cards.add(new SetCardInfo("Sporoloth Ancient", 152, Rarity.COMMON, mage.cards.s.SporolothAncient.class));
cards.add(new SetCardInfo("Sprout Swarm", 138, Rarity.COMMON, mage.cards.s.SproutSwarm.class));
+ cards.add(new SetCardInfo("Steamflogger Boss", 121, Rarity.RARE, mage.cards.s.SteamfloggerBoss.class));
cards.add(new SetCardInfo("Storm Entity", 122, Rarity.UNCOMMON, mage.cards.s.StormEntity.class));
cards.add(new SetCardInfo("Street Wraith", 90, Rarity.UNCOMMON, mage.cards.s.StreetWraith.class));
cards.add(new SetCardInfo("Stronghold Rats", 79, Rarity.UNCOMMON, mage.cards.s.StrongholdRats.class));
@@ -215,6 +218,7 @@ public class FutureSight extends ExpansionSet {
cards.add(new SetCardInfo("Tarmogoyf", 153, Rarity.RARE, mage.cards.t.Tarmogoyf.class));
cards.add(new SetCardInfo("Tarox Bladewing", 123, Rarity.RARE, mage.cards.t.TaroxBladewing.class));
cards.add(new SetCardInfo("Thornweald Archer", 154, Rarity.COMMON, mage.cards.t.ThornwealdArcher.class));
+ cards.add(new SetCardInfo("Thunderblade Charge", 124, Rarity.RARE, mage.cards.t.ThunderbladeCharge.class));
cards.add(new SetCardInfo("Tolaria West", 173, Rarity.UNCOMMON, mage.cards.t.TolariaWest.class));
cards.add(new SetCardInfo("Tombstalker", 91, Rarity.RARE, mage.cards.t.Tombstalker.class));
cards.add(new SetCardInfo("Unblinking Bleb", 45, Rarity.COMMON, mage.cards.u.UnblinkingBleb.class));
diff --git a/Mage.Sets/src/mage/sets/Invasion.java b/Mage.Sets/src/mage/sets/Invasion.java
index 5e88651b8ff..8e7acf64f84 100644
--- a/Mage.Sets/src/mage/sets/Invasion.java
+++ b/Mage.Sets/src/mage/sets/Invasion.java
@@ -1,387 +1,388 @@
-/*
- * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of BetaSteward_at_googlemail.com.
- */
-package mage.sets;
-
-import mage.cards.ExpansionSet;
-import mage.constants.Rarity;
-import mage.constants.SetType;
-
-/**
- *
- * @author North
- */
-public class Invasion extends ExpansionSet {
-
- private static final Invasion instance = new Invasion();
-
- public static Invasion getInstance() {
- return instance;
- }
-
- private Invasion() {
- super("Invasion", "INV", ExpansionSet.buildDate(2000, 9, 2), SetType.EXPANSION);
- this.blockName = "Invasion";
- this.hasBoosters = true;
- this.numBoosterLands = 0;
- this.numBoosterCommon = 11;
- this.numBoosterUncommon = 3;
- this.numBoosterRare = 1;
- this.ratioBoosterMythic = 0;
- cards.add(new SetCardInfo("Absorb", 226, Rarity.RARE, mage.cards.a.Absorb.class));
- cards.add(new SetCardInfo("Addle", 91, Rarity.UNCOMMON, mage.cards.a.Addle.class));
- cards.add(new SetCardInfo("Aether Rift", 227, Rarity.RARE, mage.cards.a.AetherRift.class));
- cards.add(new SetCardInfo("Aggressive Urge", 181, Rarity.COMMON, mage.cards.a.AggressiveUrge.class));
- cards.add(new SetCardInfo("Agonizing Demise", 92, Rarity.COMMON, mage.cards.a.AgonizingDemise.class));
- cards.add(new SetCardInfo("Alabaster Leech", 1, Rarity.RARE, mage.cards.a.AlabasterLeech.class));
- cards.add(new SetCardInfo("Alloy Golem", 297, Rarity.UNCOMMON, mage.cards.a.AlloyGolem.class));
- cards.add(new SetCardInfo("Ancient Kavu", 136, Rarity.COMMON, mage.cards.a.AncientKavu.class));
- cards.add(new SetCardInfo("Ancient Spring", 319, Rarity.COMMON, mage.cards.a.AncientSpring.class));
- cards.add(new SetCardInfo("Andradite Leech", 93, Rarity.RARE, mage.cards.a.AndraditeLeech.class));
- cards.add(new SetCardInfo("Angelic Shield", 228, Rarity.UNCOMMON, mage.cards.a.AngelicShield.class));
- cards.add(new SetCardInfo("Angel of Mercy", 2, Rarity.UNCOMMON, mage.cards.a.AngelOfMercy.class));
- cards.add(new SetCardInfo("Annihilate", 94, Rarity.UNCOMMON, mage.cards.a.Annihilate.class));
- cards.add(new SetCardInfo("Archaeological Dig", 320, Rarity.UNCOMMON, mage.cards.a.ArchaeologicalDig.class));
- cards.add(new SetCardInfo("Ardent Soldier", 3, Rarity.COMMON, mage.cards.a.ArdentSoldier.class));
- cards.add(new SetCardInfo("Armadillo Cloak", 229, Rarity.COMMON, mage.cards.a.ArmadilloCloak.class));
- cards.add(new SetCardInfo("Armored Guardian", 230, Rarity.RARE, mage.cards.a.ArmoredGuardian.class));
- cards.add(new SetCardInfo("Artifact Mutation", 231, Rarity.RARE, mage.cards.a.ArtifactMutation.class));
- cards.add(new SetCardInfo("Assault // Battery", 295, Rarity.UNCOMMON, mage.cards.a.AssaultBattery.class));
- cards.add(new SetCardInfo("Atalya, Samite Master", 4, Rarity.RARE, mage.cards.a.AtalyaSamiteMaster.class));
- cards.add(new SetCardInfo("Aura Mutation", 232, Rarity.RARE, mage.cards.a.AuraMutation.class));
- cards.add(new SetCardInfo("Aura Shards", 233, Rarity.UNCOMMON, mage.cards.a.AuraShards.class));
- cards.add(new SetCardInfo("Backlash", 234, Rarity.UNCOMMON, mage.cards.b.Backlash.class));
- cards.add(new SetCardInfo("Barrin's Spite", 235, Rarity.RARE, mage.cards.b.BarrinsSpite.class));
- cards.add(new SetCardInfo("Barrin's Unmaking", 46, Rarity.COMMON, mage.cards.b.BarrinsUnmaking.class));
- cards.add(new SetCardInfo("Benalish Emissary", 5, Rarity.UNCOMMON, mage.cards.b.BenalishEmissary.class));
- cards.add(new SetCardInfo("Benalish Heralds", 6, Rarity.UNCOMMON, mage.cards.b.BenalishHeralds.class));
- cards.add(new SetCardInfo("Benalish Lancer", 7, Rarity.COMMON, mage.cards.b.BenalishLancer.class));
- cards.add(new SetCardInfo("Benalish Trapper", 8, Rarity.COMMON, mage.cards.b.BenalishTrapper.class));
- cards.add(new SetCardInfo("Bind", 182, Rarity.RARE, mage.cards.b.Bind.class));
- cards.add(new SetCardInfo("Blazing Specter", 236, Rarity.RARE, mage.cards.b.BlazingSpecter.class));
- cards.add(new SetCardInfo("Blinding Light", 9, Rarity.UNCOMMON, mage.cards.b.BlindingLight.class));
- cards.add(new SetCardInfo("Blind Seer", 47, Rarity.RARE, mage.cards.b.BlindSeer.class));
- cards.add(new SetCardInfo("Bloodstone Cameo", 298, Rarity.UNCOMMON, mage.cards.b.BloodstoneCameo.class));
- cards.add(new SetCardInfo("Blurred Mongoose", 183, Rarity.RARE, mage.cards.b.BlurredMongoose.class));
- cards.add(new SetCardInfo("Bog Initiate", 95, Rarity.COMMON, mage.cards.b.BogInitiate.class));
- cards.add(new SetCardInfo("Breaking Wave", 48, Rarity.RARE, mage.cards.b.BreakingWave.class));
- cards.add(new SetCardInfo("Breath of Darigaaz", 138, Rarity.UNCOMMON, mage.cards.b.BreathOfDarigaaz.class));
- cards.add(new SetCardInfo("Callous Giant", 139, Rarity.RARE, mage.cards.c.CallousGiant.class));
- cards.add(new SetCardInfo("Canopy Surge", 184, Rarity.UNCOMMON, mage.cards.c.CanopySurge.class));
- cards.add(new SetCardInfo("Capashen Unicorn", 10, Rarity.COMMON, mage.cards.c.CapashenUnicorn.class));
- cards.add(new SetCardInfo("Captain Sisay", 237, Rarity.RARE, mage.cards.c.CaptainSisay.class));
- cards.add(new SetCardInfo("Cauldron Dance", 238, Rarity.UNCOMMON, mage.cards.c.CauldronDance.class));
- cards.add(new SetCardInfo("Chaotic Strike", 140, Rarity.UNCOMMON, mage.cards.c.ChaoticStrike.class));
- cards.add(new SetCardInfo("Charging Troll", 239, Rarity.UNCOMMON, mage.cards.c.ChargingTroll.class));
- cards.add(new SetCardInfo("Chromatic Sphere", 299, Rarity.UNCOMMON, mage.cards.c.ChromaticSphere.class));
- cards.add(new SetCardInfo("Cinder Shade", 240, Rarity.UNCOMMON, mage.cards.c.CinderShade.class));
- cards.add(new SetCardInfo("Coalition Victory", 241, Rarity.RARE, mage.cards.c.CoalitionVictory.class));
- cards.add(new SetCardInfo("Coastal Tower", 321, Rarity.UNCOMMON, mage.cards.c.CoastalTower.class));
- cards.add(new SetCardInfo("Collapsing Borders", 141, Rarity.RARE, mage.cards.c.CollapsingBorders.class));
- cards.add(new SetCardInfo("Collective Restraint", 49, Rarity.RARE, mage.cards.c.CollectiveRestraint.class));
- cards.add(new SetCardInfo("Cremate", 96, Rarity.UNCOMMON, mage.cards.c.Cremate.class));
- cards.add(new SetCardInfo("Crimson Acolyte", 11, Rarity.COMMON, mage.cards.c.CrimsonAcolyte.class));
- cards.add(new SetCardInfo("Crosis's Attendant", 300, Rarity.UNCOMMON, mage.cards.c.CrosissAttendant.class));
- cards.add(new SetCardInfo("Crosis, the Purger", 242, Rarity.RARE, mage.cards.c.CrosisThePurger.class));
- cards.add(new SetCardInfo("Crown of Flames", 142, Rarity.COMMON, mage.cards.c.CrownOfFlames.class));
- cards.add(new SetCardInfo("Crusading Knight", 12, Rarity.RARE, mage.cards.c.CrusadingKnight.class));
- cards.add(new SetCardInfo("Crypt Angel", 97, Rarity.RARE, mage.cards.c.CryptAngel.class));
- cards.add(new SetCardInfo("Cursed Flesh", 98, Rarity.COMMON, mage.cards.c.CursedFlesh.class));
- cards.add(new SetCardInfo("Darigaaz's Attendant", 301, Rarity.UNCOMMON, mage.cards.d.DarigaazsAttendant.class));
- cards.add(new SetCardInfo("Darigaaz, the Igniter", 243, Rarity.RARE, mage.cards.d.DarigaazTheIgniter.class));
- cards.add(new SetCardInfo("Defiling Tears", 99, Rarity.UNCOMMON, mage.cards.d.DefilingTears.class));
- cards.add(new SetCardInfo("Devouring Strossus", 101, Rarity.RARE, mage.cards.d.DevouringStrossus.class));
- cards.add(new SetCardInfo("Dismantling Blow", 14, Rarity.COMMON, mage.cards.d.DismantlingBlow.class));
- cards.add(new SetCardInfo("Disrupt", 51, Rarity.UNCOMMON, mage.cards.d.Disrupt.class));
- cards.add(new SetCardInfo("Distorting Wake", 52, Rarity.RARE, mage.cards.d.DistortingWake.class));
- cards.add(new SetCardInfo("Divine Presence", 15, Rarity.RARE, mage.cards.d.DivinePresence.class));
- cards.add(new SetCardInfo("Do or Die", 102, Rarity.RARE, mage.cards.d.DoOrDie.class));
- cards.add(new SetCardInfo("Drake-Skull Cameo", 302, Rarity.UNCOMMON, mage.cards.d.DrakeSkullCameo.class));
- cards.add(new SetCardInfo("Dream Thrush", 53, Rarity.COMMON, mage.cards.d.DreamThrush.class));
- cards.add(new SetCardInfo("Dredge", 103, Rarity.UNCOMMON, mage.cards.d.Dredge.class));
- cards.add(new SetCardInfo("Dromar's Attendant", 303, Rarity.UNCOMMON, mage.cards.d.DromarsAttendant.class));
- cards.add(new SetCardInfo("Dromar, the Banisher", 244, Rarity.RARE, mage.cards.d.DromarTheBanisher.class));
- cards.add(new SetCardInfo("Dueling Grounds", 245, Rarity.RARE, mage.cards.d.DuelingGrounds.class));
- cards.add(new SetCardInfo("Duskwalker", 104, Rarity.COMMON, mage.cards.d.Duskwalker.class));
- cards.add(new SetCardInfo("Elfhame Palace", 322, Rarity.UNCOMMON, mage.cards.e.ElfhamePalace.class));
- cards.add(new SetCardInfo("Elfhame Sanctuary", 185, Rarity.UNCOMMON, mage.cards.e.ElfhameSanctuary.class));
- cards.add(new SetCardInfo("Elvish Champion", 186, Rarity.RARE, mage.cards.e.ElvishChampion.class));
- cards.add(new SetCardInfo("Empress Galina", 54, Rarity.RARE, mage.cards.e.EmpressGalina.class));
- cards.add(new SetCardInfo("Exclude", 56, Rarity.COMMON, mage.cards.e.Exclude.class));
- cards.add(new SetCardInfo("Exotic Curse", 105, Rarity.COMMON, mage.cards.e.ExoticCurse.class));
- cards.add(new SetCardInfo("Explosive Growth", 187, Rarity.COMMON, mage.cards.e.ExplosiveGrowth.class));
- cards.add(new SetCardInfo("Fact or Fiction", 57, Rarity.UNCOMMON, mage.cards.f.FactOrFiction.class));
- cards.add(new SetCardInfo("Faerie Squadron", 58, Rarity.COMMON, mage.cards.f.FaerieSquadron.class));
- cards.add(new SetCardInfo("Fertile Ground", 188, Rarity.COMMON, mage.cards.f.FertileGround.class));
- cards.add(new SetCardInfo("Firebrand Ranger", 143, Rarity.UNCOMMON, mage.cards.f.FirebrandRanger.class));
- cards.add(new SetCardInfo("Firescreamer", 106, Rarity.COMMON, mage.cards.f.Firescreamer.class));
- cards.add(new SetCardInfo("Fires of Yavimaya", 246, Rarity.UNCOMMON, mage.cards.f.FiresOfYavimaya.class));
- cards.add(new SetCardInfo("Forest", 347, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Forest", 348, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Forest", 349, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Forest", 350, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Frenzied Tilling", 247, Rarity.COMMON, mage.cards.f.FrenziedTilling.class));
- cards.add(new SetCardInfo("Galina's Knight", 248, Rarity.COMMON, mage.cards.g.GalinasKnight.class));
- cards.add(new SetCardInfo("Geothermal Crevice", 323, Rarity.COMMON, mage.cards.g.GeothermalCrevice.class));
- cards.add(new SetCardInfo("Ghitu Fire", 144, Rarity.RARE, mage.cards.g.GhituFire.class));
- cards.add(new SetCardInfo("Glimmering Angel", 17, Rarity.COMMON, mage.cards.g.GlimmeringAngel.class));
- cards.add(new SetCardInfo("Global Ruin", 18, Rarity.RARE, mage.cards.g.GlobalRuin.class));
- cards.add(new SetCardInfo("Goblin Spy", 145, Rarity.UNCOMMON, mage.cards.g.GoblinSpy.class));
- cards.add(new SetCardInfo("Goham Djinn", 107, Rarity.UNCOMMON, mage.cards.g.GohamDjinn.class));
- cards.add(new SetCardInfo("Halam Djinn", 146, Rarity.UNCOMMON, mage.cards.h.HalamDjinn.class));
- cards.add(new SetCardInfo("Hanna, Ship's Navigator", 249, Rarity.RARE, mage.cards.h.HannaShipsNavigator.class));
- cards.add(new SetCardInfo("Harrow", 189, Rarity.COMMON, mage.cards.h.Harrow.class));
- cards.add(new SetCardInfo("Harsh Judgment", 19, Rarity.RARE, mage.cards.h.HarshJudgment.class));
- cards.add(new SetCardInfo("Hate Weaver", 108, Rarity.UNCOMMON, mage.cards.h.HateWeaver.class));
- cards.add(new SetCardInfo("Heroes' Reunion", 250, Rarity.UNCOMMON, mage.cards.h.HeroesReunion.class));
- cards.add(new SetCardInfo("Holy Day", 20, Rarity.COMMON, mage.cards.h.HolyDay.class));
- cards.add(new SetCardInfo("Hooded Kavu", 147, Rarity.COMMON, mage.cards.h.HoodedKavu.class));
- cards.add(new SetCardInfo("Horned Cheetah", 251, Rarity.UNCOMMON, mage.cards.h.HornedCheetah.class));
- cards.add(new SetCardInfo("Hunting Kavu", 252, Rarity.UNCOMMON, mage.cards.h.HuntingKavu.class));
- cards.add(new SetCardInfo("Hypnotic Cloud", 109, Rarity.COMMON, mage.cards.h.HypnoticCloud.class));
- cards.add(new SetCardInfo("Irrigation Ditch", 324, Rarity.COMMON, mage.cards.i.IrrigationDitch.class));
- cards.add(new SetCardInfo("Island", 335, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Island", 336, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Island", 337, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Island", 338, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Jade Leech", 190, Rarity.RARE, mage.cards.j.JadeLeech.class));
- cards.add(new SetCardInfo("Juntu Stakes", 304, Rarity.RARE, mage.cards.j.JuntuStakes.class));
- cards.add(new SetCardInfo("Kangee, Aerie Keeper", 253, Rarity.RARE, mage.cards.k.KangeeAerieKeeper.class));
- cards.add(new SetCardInfo("Kavu Aggressor", 148, Rarity.COMMON, mage.cards.k.KavuAggressor.class));
- cards.add(new SetCardInfo("Kavu Chameleon", 191, Rarity.UNCOMMON, mage.cards.k.KavuChameleon.class));
- cards.add(new SetCardInfo("Kavu Climber", 192, Rarity.COMMON, mage.cards.k.KavuClimber.class));
- cards.add(new SetCardInfo("Kavu Lair", 193, Rarity.RARE, mage.cards.k.KavuLair.class));
- cards.add(new SetCardInfo("Kavu Monarch", 149, Rarity.RARE, mage.cards.k.KavuMonarch.class));
- cards.add(new SetCardInfo("Kavu Runner", 150, Rarity.UNCOMMON, mage.cards.k.KavuRunner.class));
- cards.add(new SetCardInfo("Kavu Scout", 151, Rarity.COMMON, mage.cards.k.KavuScout.class));
- cards.add(new SetCardInfo("Kavu Titan", 194, Rarity.RARE, mage.cards.k.KavuTitan.class));
- cards.add(new SetCardInfo("Keldon Necropolis", 325, Rarity.RARE, mage.cards.k.KeldonNecropolis.class));
- cards.add(new SetCardInfo("Liberate", 21, Rarity.UNCOMMON, mage.cards.l.Liberate.class));
- cards.add(new SetCardInfo("Lightning Dart", 152, Rarity.UNCOMMON, mage.cards.l.LightningDart.class));
- cards.add(new SetCardInfo("Llanowar Cavalry", 195, Rarity.COMMON, mage.cards.l.LlanowarCavalry.class));
- cards.add(new SetCardInfo("Llanowar Elite", 196, Rarity.COMMON, mage.cards.l.LlanowarElite.class));
- cards.add(new SetCardInfo("Llanowar Knight", 254, Rarity.COMMON, mage.cards.l.LlanowarKnight.class));
- cards.add(new SetCardInfo("Llanowar Vanguard", 197, Rarity.COMMON, mage.cards.l.LlanowarVanguard.class));
- cards.add(new SetCardInfo("Lobotomy", 255, Rarity.UNCOMMON, mage.cards.l.Lobotomy.class));
- cards.add(new SetCardInfo("Lotus Guardian", 305, Rarity.RARE, mage.cards.l.LotusGuardian.class));
- cards.add(new SetCardInfo("Mana Maze", 59, Rarity.RARE, mage.cards.m.ManaMaze.class));
- cards.add(new SetCardInfo("Maniacal Rage", 155, Rarity.COMMON, mage.cards.m.ManiacalRage.class));
- cards.add(new SetCardInfo("Manipulate Fate", 60, Rarity.UNCOMMON, mage.cards.m.ManipulateFate.class));
- cards.add(new SetCardInfo("Marauding Knight", 110, Rarity.RARE, mage.cards.m.MaraudingKnight.class));
- cards.add(new SetCardInfo("Metathran Transport", 62, Rarity.UNCOMMON, mage.cards.m.MetathranTransport.class));
- cards.add(new SetCardInfo("Metathran Zombie", 63, Rarity.COMMON, mage.cards.m.MetathranZombie.class));
- cards.add(new SetCardInfo("Meteor Storm", 256, Rarity.RARE, mage.cards.m.MeteorStorm.class));
- cards.add(new SetCardInfo("Might Weaver", 198, Rarity.UNCOMMON, mage.cards.m.MightWeaver.class));
- cards.add(new SetCardInfo("Molimo, Maro-Sorcerer", 199, Rarity.RARE, mage.cards.m.MolimoMaroSorcerer.class));
- cards.add(new SetCardInfo("Mountain", 343, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Mountain", 344, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Mountain", 345, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Mountain", 346, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Mourning", 111, Rarity.COMMON, mage.cards.m.Mourning.class));
- cards.add(new SetCardInfo("Nightscape Apprentice", 112, Rarity.COMMON, mage.cards.n.NightscapeApprentice.class));
- cards.add(new SetCardInfo("Nightscape Master", 113, Rarity.RARE, mage.cards.n.NightscapeMaster.class));
- cards.add(new SetCardInfo("Noble Panther", 257, Rarity.RARE, mage.cards.n.NoblePanther.class));
- cards.add(new SetCardInfo("Nomadic Elf", 200, Rarity.COMMON, mage.cards.n.NomadicElf.class));
- cards.add(new SetCardInfo("Obliterate", 156, Rarity.RARE, mage.cards.o.Obliterate.class));
- cards.add(new SetCardInfo("Obsidian Acolyte", 22, Rarity.COMMON, mage.cards.o.ObsidianAcolyte.class));
- cards.add(new SetCardInfo("Opt", 64, Rarity.COMMON, mage.cards.o.Opt.class));
- cards.add(new SetCardInfo("Ordered Migration", 258, Rarity.UNCOMMON, mage.cards.o.OrderedMigration.class));
- cards.add(new SetCardInfo("Orim's Touch", 23, Rarity.COMMON, mage.cards.o.OrimsTouch.class));
- cards.add(new SetCardInfo("Overabundance", 259, Rarity.RARE, mage.cards.o.Overabundance.class));
- cards.add(new SetCardInfo("Overload", 157, Rarity.COMMON, mage.cards.o.Overload.class));
- cards.add(new SetCardInfo("Pain // Suffering", 294, Rarity.UNCOMMON, mage.cards.p.PainSuffering.class));
- cards.add(new SetCardInfo("Phantasmal Terrain", 65, Rarity.COMMON, mage.cards.p.PhantasmalTerrain.class));
- cards.add(new SetCardInfo("Phyrexian Altar", 306, Rarity.RARE, mage.cards.p.PhyrexianAltar.class));
- cards.add(new SetCardInfo("Phyrexian Battleflies", 114, Rarity.COMMON, mage.cards.p.PhyrexianBattleflies.class));
- cards.add(new SetCardInfo("Phyrexian Delver", 115, Rarity.RARE, mage.cards.p.PhyrexianDelver.class));
- cards.add(new SetCardInfo("Phyrexian Infiltrator", 116, Rarity.RARE, mage.cards.p.PhyrexianInfiltrator.class));
- cards.add(new SetCardInfo("Phyrexian Lens", 307, Rarity.RARE, mage.cards.p.PhyrexianLens.class));
- cards.add(new SetCardInfo("Phyrexian Reaper", 117, Rarity.COMMON, mage.cards.p.PhyrexianReaper.class));
- cards.add(new SetCardInfo("Phyrexian Slayer", 118, Rarity.COMMON, mage.cards.p.PhyrexianSlayer.class));
- cards.add(new SetCardInfo("Pincer Spider", 201, Rarity.COMMON, mage.cards.p.PincerSpider.class));
- cards.add(new SetCardInfo("Plague Spitter", 119, Rarity.UNCOMMON, mage.cards.p.PlagueSpitter.class));
- cards.add(new SetCardInfo("Plague Spores", 260, Rarity.COMMON, mage.cards.p.PlagueSpores.class));
- cards.add(new SetCardInfo("Plains", 331, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Plains", 332, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Plains", 333, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Plains", 334, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Planar Portal", 308, Rarity.RARE, mage.cards.p.PlanarPortal.class));
- cards.add(new SetCardInfo("Pouncing Kavu", 158, Rarity.COMMON, mage.cards.p.PouncingKavu.class));
- cards.add(new SetCardInfo("Power Armor", 309, Rarity.UNCOMMON, mage.cards.p.PowerArmor.class));
- cards.add(new SetCardInfo("Prison Barricade", 25, Rarity.COMMON, mage.cards.p.PrisonBarricade.class));
- cards.add(new SetCardInfo("Probe", 66, Rarity.COMMON, mage.cards.p.Probe.class));
- cards.add(new SetCardInfo("Prohibit", 67, Rarity.COMMON, mage.cards.p.Prohibit.class));
- cards.add(new SetCardInfo("Pure Reflection", 27, Rarity.RARE, mage.cards.p.PureReflection.class));
- cards.add(new SetCardInfo("Pyre Zombie", 261, Rarity.RARE, mage.cards.p.PyreZombie.class));
- cards.add(new SetCardInfo("Quirion Elves", 203, Rarity.COMMON, mage.cards.q.QuirionElves.class));
- cards.add(new SetCardInfo("Quirion Sentinel", 204, Rarity.COMMON, mage.cards.q.QuirionSentinel.class));
- cards.add(new SetCardInfo("Quirion Trailblazer", 205, Rarity.COMMON, mage.cards.q.QuirionTrailblazer.class));
- cards.add(new SetCardInfo("Rage Weaver", 159, Rarity.UNCOMMON, mage.cards.r.RageWeaver.class));
- cards.add(new SetCardInfo("Raging Kavu", 262, Rarity.RARE, mage.cards.r.RagingKavu.class));
- cards.add(new SetCardInfo("Rainbow Crow", 69, Rarity.UNCOMMON, mage.cards.r.RainbowCrow.class));
- cards.add(new SetCardInfo("Rampant Elephant", 28, Rarity.COMMON, mage.cards.r.RampantElephant.class));
- cards.add(new SetCardInfo("Ravenous Rats", 120, Rarity.COMMON, mage.cards.r.RavenousRats.class));
- cards.add(new SetCardInfo("Razorfoot Griffin", 29, Rarity.COMMON, mage.cards.r.RazorfootGriffin.class));
- cards.add(new SetCardInfo("Reckless Assault", 263, Rarity.RARE, mage.cards.r.RecklessAssault.class));
- cards.add(new SetCardInfo("Reckless Spite", 121, Rarity.UNCOMMON, mage.cards.r.RecklessSpite.class));
- cards.add(new SetCardInfo("Recoil", 264, Rarity.COMMON, mage.cards.r.Recoil.class));
- cards.add(new SetCardInfo("Recover", 122, Rarity.COMMON, mage.cards.r.Recover.class));
- cards.add(new SetCardInfo("Repulse", 70, Rarity.COMMON, mage.cards.r.Repulse.class));
- cards.add(new SetCardInfo("Restock", 206, Rarity.RARE, mage.cards.r.Restock.class));
- cards.add(new SetCardInfo("Restrain", 30, Rarity.COMMON, mage.cards.r.Restrain.class));
- cards.add(new SetCardInfo("Reviving Dose", 31, Rarity.COMMON, mage.cards.r.RevivingDose.class));
- cards.add(new SetCardInfo("Reviving Vapors", 265, Rarity.UNCOMMON, mage.cards.r.RevivingVapors.class));
- cards.add(new SetCardInfo("Rewards of Diversity", 32, Rarity.UNCOMMON, mage.cards.r.RewardsOfDiversity.class));
- cards.add(new SetCardInfo("Reya Dawnbringer", 33, Rarity.RARE, mage.cards.r.ReyaDawnbringer.class));
- cards.add(new SetCardInfo("Riptide Crab", 266, Rarity.UNCOMMON, mage.cards.r.RiptideCrab.class));
- cards.add(new SetCardInfo("Rith's Attendant", 310, Rarity.UNCOMMON, mage.cards.r.RithsAttendant.class));
- cards.add(new SetCardInfo("Rith, the Awakener", 267, Rarity.RARE, mage.cards.r.RithTheAwakener.class));
- cards.add(new SetCardInfo("Rogue Kavu", 160, Rarity.COMMON, mage.cards.r.RogueKavu.class));
- cards.add(new SetCardInfo("Rooting Kavu", 207, Rarity.UNCOMMON, mage.cards.r.RootingKavu.class));
- cards.add(new SetCardInfo("Rout", 34, Rarity.RARE, mage.cards.r.Rout.class));
- cards.add(new SetCardInfo("Ruby Leech", 161, Rarity.RARE, mage.cards.r.RubyLeech.class));
- cards.add(new SetCardInfo("Ruham Djinn", 35, Rarity.UNCOMMON, mage.cards.r.RuhamDjinn.class));
- cards.add(new SetCardInfo("Sabertooth Nishoba", 268, Rarity.RARE, mage.cards.s.SabertoothNishoba.class));
- cards.add(new SetCardInfo("Salt Marsh", 326, Rarity.UNCOMMON, mage.cards.s.SaltMarsh.class));
- cards.add(new SetCardInfo("Samite Archer", 269, Rarity.UNCOMMON, mage.cards.s.SamiteArcher.class));
- cards.add(new SetCardInfo("Sapphire Leech", 71, Rarity.RARE, mage.cards.s.SapphireLeech.class));
- cards.add(new SetCardInfo("Saproling Symbiosis", 209, Rarity.RARE, mage.cards.s.SaprolingSymbiosis.class));
- cards.add(new SetCardInfo("Savage Offensive", 162, Rarity.COMMON, mage.cards.s.SavageOffensive.class));
- cards.add(new SetCardInfo("Scarred Puma", 163, Rarity.COMMON, mage.cards.s.ScarredPuma.class));
- cards.add(new SetCardInfo("Scavenged Weaponry", 123, Rarity.COMMON, mage.cards.s.ScavengedWeaponry.class));
- cards.add(new SetCardInfo("Scorching Lava", 164, Rarity.COMMON, mage.cards.s.ScorchingLava.class));
- cards.add(new SetCardInfo("Scouting Trek", 210, Rarity.UNCOMMON, mage.cards.s.ScoutingTrek.class));
- cards.add(new SetCardInfo("Seashell Cameo", 311, Rarity.UNCOMMON, mage.cards.s.SeashellCameo.class));
- cards.add(new SetCardInfo("Seer's Vision", 270, Rarity.UNCOMMON, mage.cards.s.SeersVision.class));
- cards.add(new SetCardInfo("Serpentine Kavu", 211, Rarity.COMMON, mage.cards.s.SerpentineKavu.class));
- cards.add(new SetCardInfo("Shackles", 37, Rarity.COMMON, mage.cards.s.Shackles.class));
- cards.add(new SetCardInfo("Shimmering Wings", 72, Rarity.COMMON, mage.cards.s.ShimmeringWings.class));
- cards.add(new SetCardInfo("Shivan Emissary", 166, Rarity.UNCOMMON, mage.cards.s.ShivanEmissary.class));
- cards.add(new SetCardInfo("Shivan Harvest", 167, Rarity.UNCOMMON, mage.cards.s.ShivanHarvest.class));
- cards.add(new SetCardInfo("Shivan Oasis", 327, Rarity.UNCOMMON, mage.cards.s.ShivanOasis.class));
- cards.add(new SetCardInfo("Shivan Zombie", 271, Rarity.COMMON, mage.cards.s.ShivanZombie.class));
- cards.add(new SetCardInfo("Shoreline Raider", 73, Rarity.COMMON, mage.cards.s.ShorelineRaider.class));
- cards.add(new SetCardInfo("Simoon", 272, Rarity.UNCOMMON, mage.cards.s.Simoon.class));
- cards.add(new SetCardInfo("Skittish Kavu", 168, Rarity.UNCOMMON, mage.cards.s.SkittishKavu.class));
- cards.add(new SetCardInfo("Skizzik", 169, Rarity.RARE, mage.cards.s.Skizzik.class));
- cards.add(new SetCardInfo("Sky Weaver", 74, Rarity.UNCOMMON, mage.cards.s.SkyWeaver.class));
- cards.add(new SetCardInfo("Sleeper's Robe", 273, Rarity.UNCOMMON, mage.cards.s.SleepersRobe.class));
- cards.add(new SetCardInfo("Slimy Kavu", 170, Rarity.COMMON, mage.cards.s.SlimyKavu.class));
- cards.add(new SetCardInfo("Slinking Serpent", 274, Rarity.UNCOMMON, mage.cards.s.SlinkingSerpent.class));
- cards.add(new SetCardInfo("Smoldering Tar", 275, Rarity.UNCOMMON, mage.cards.s.SmolderingTar.class));
- cards.add(new SetCardInfo("Soul Burn", 124, Rarity.COMMON, mage.cards.s.SoulBurn.class));
- cards.add(new SetCardInfo("Sparring Golem", 312, Rarity.UNCOMMON, mage.cards.s.SparringGolem.class));
- cards.add(new SetCardInfo("Spinal Embrace", 276, Rarity.RARE, mage.cards.s.SpinalEmbrace.class));
- cards.add(new SetCardInfo("Spirit of Resistance", 38, Rarity.RARE, mage.cards.s.SpiritOfResistance.class));
- cards.add(new SetCardInfo("Spirit Weaver", 39, Rarity.UNCOMMON, mage.cards.s.SpiritWeaver.class));
- cards.add(new SetCardInfo("Spite // Malice", 293, Rarity.UNCOMMON, mage.cards.s.SpiteMalice.class));
- cards.add(new SetCardInfo("Spreading Plague", 125, Rarity.RARE, mage.cards.s.SpreadingPlague.class));
- cards.add(new SetCardInfo("Stalking Assassin", 277, Rarity.RARE, mage.cards.s.StalkingAssassin.class));
- cards.add(new SetCardInfo("Stand // Deliver", 292, Rarity.UNCOMMON, mage.cards.s.StandDeliver.class));
- cards.add(new SetCardInfo("Sterling Grove", 278, Rarity.UNCOMMON, mage.cards.s.SterlingGrove.class));
- cards.add(new SetCardInfo("Stormscape Apprentice", 75, Rarity.COMMON, mage.cards.s.StormscapeApprentice.class));
- cards.add(new SetCardInfo("Stormscape Master", 76, Rarity.RARE, mage.cards.s.StormscapeMaster.class));
- cards.add(new SetCardInfo("Strength of Unity", 40, Rarity.COMMON, mage.cards.s.StrengthOfUnity.class));
- cards.add(new SetCardInfo("Stun", 172, Rarity.COMMON, mage.cards.s.Stun.class));
- cards.add(new SetCardInfo("Sulam Djinn", 212, Rarity.UNCOMMON, mage.cards.s.SulamDjinn.class));
- cards.add(new SetCardInfo("Sulfur Vent", 328, Rarity.COMMON, mage.cards.s.SulfurVent.class));
- cards.add(new SetCardInfo("Sunscape Apprentice", 41, Rarity.COMMON, mage.cards.s.SunscapeApprentice.class));
- cards.add(new SetCardInfo("Sunscape Master", 42, Rarity.RARE, mage.cards.s.SunscapeMaster.class));
- cards.add(new SetCardInfo("Swamp", 339, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Swamp", 340, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Swamp", 341, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Swamp", 342, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Sway of Illusion", 77, Rarity.UNCOMMON, mage.cards.s.SwayOfIllusion.class));
- cards.add(new SetCardInfo("Tainted Well", 126, Rarity.COMMON, mage.cards.t.TaintedWell.class));
- cards.add(new SetCardInfo("Tangle", 213, Rarity.UNCOMMON, mage.cards.t.Tangle.class));
- cards.add(new SetCardInfo("Tectonic Instability", 173, Rarity.RARE, mage.cards.t.TectonicInstability.class));
- cards.add(new SetCardInfo("Teferi's Care", 43, Rarity.UNCOMMON, mage.cards.t.TeferisCare.class));
- cards.add(new SetCardInfo("Teferi's Moat", 279, Rarity.RARE, mage.cards.t.TeferisMoat.class));
- cards.add(new SetCardInfo("Teferi's Response", 78, Rarity.RARE, mage.cards.t.TeferisResponse.class));
- cards.add(new SetCardInfo("Tek", 313, Rarity.RARE, mage.cards.t.Tek.class));
- cards.add(new SetCardInfo("Temporal Distortion", 79, Rarity.RARE, mage.cards.t.TemporalDistortion.class));
- cards.add(new SetCardInfo("Thicket Elemental", 214, Rarity.RARE, mage.cards.t.ThicketElemental.class));
- cards.add(new SetCardInfo("Thornscape Apprentice", 215, Rarity.COMMON, mage.cards.t.ThornscapeApprentice.class));
- cards.add(new SetCardInfo("Thornscape Master", 216, Rarity.RARE, mage.cards.t.ThornscapeMaster.class));
- cards.add(new SetCardInfo("Thunderscape Apprentice", 174, Rarity.COMMON, mage.cards.t.ThunderscapeApprentice.class));
- cards.add(new SetCardInfo("Thunderscape Master", 175, Rarity.RARE, mage.cards.t.ThunderscapeMaster.class));
- cards.add(new SetCardInfo("Tidal Visionary", 80, Rarity.COMMON, mage.cards.t.TidalVisionary.class));
- cards.add(new SetCardInfo("Tigereye Cameo", 314, Rarity.UNCOMMON, mage.cards.t.TigereyeCameo.class));
- cards.add(new SetCardInfo("Tinder Farm", 329, Rarity.COMMON, mage.cards.t.TinderFarm.class));
- cards.add(new SetCardInfo("Tolarian Emissary", 81, Rarity.UNCOMMON, mage.cards.t.TolarianEmissary.class));
- cards.add(new SetCardInfo("Tower Drake", 82, Rarity.COMMON, mage.cards.t.TowerDrake.class));
- cards.add(new SetCardInfo("Tranquility", 217, Rarity.COMMON, mage.cards.t.Tranquility.class));
- cards.add(new SetCardInfo("Traveler's Cloak", 83, Rarity.COMMON, mage.cards.t.TravelersCloak.class));
- cards.add(new SetCardInfo("Treefolk Healer", 218, Rarity.UNCOMMON, mage.cards.t.TreefolkHealer.class));
- cards.add(new SetCardInfo("Trench Wurm", 127, Rarity.UNCOMMON, mage.cards.t.TrenchWurm.class));
- cards.add(new SetCardInfo("Treva's Attendant", 315, Rarity.UNCOMMON, mage.cards.t.TrevasAttendant.class));
- cards.add(new SetCardInfo("Treva, the Renewer", 280, Rarity.RARE, mage.cards.t.TrevaTheRenewer.class));
- cards.add(new SetCardInfo("Tribal Flames", 176, Rarity.COMMON, mage.cards.t.TribalFlames.class));
- cards.add(new SetCardInfo("Troll-Horn Cameo", 316, Rarity.UNCOMMON, mage.cards.t.TrollHornCameo.class));
- cards.add(new SetCardInfo("Tsabo's Assassin", 128, Rarity.RARE, mage.cards.t.TsabosAssassin.class));
- cards.add(new SetCardInfo("Tsabo's Decree", 129, Rarity.RARE, mage.cards.t.TsabosDecree.class));
- cards.add(new SetCardInfo("Tsabo's Web", 317, Rarity.RARE, mage.cards.t.TsabosWeb.class));
- cards.add(new SetCardInfo("Tsabo Tavoc", 281, Rarity.RARE, mage.cards.t.TsaboTavoc.class));
- cards.add(new SetCardInfo("Turf Wound", 177, Rarity.COMMON, mage.cards.t.TurfWound.class));
- cards.add(new SetCardInfo("Twilight's Call", 130, Rarity.RARE, mage.cards.t.TwilightsCall.class));
- cards.add(new SetCardInfo("Undermine", 282, Rarity.RARE, mage.cards.u.Undermine.class));
- cards.add(new SetCardInfo("Urborg Drake", 283, Rarity.UNCOMMON, mage.cards.u.UrborgDrake.class));
- cards.add(new SetCardInfo("Urborg Emissary", 131, Rarity.UNCOMMON, mage.cards.u.UrborgEmissary.class));
- cards.add(new SetCardInfo("Urborg Phantom", 132, Rarity.COMMON, mage.cards.u.UrborgPhantom.class));
- cards.add(new SetCardInfo("Urborg Shambler", 133, Rarity.UNCOMMON, mage.cards.u.UrborgShambler.class));
- cards.add(new SetCardInfo("Urborg Skeleton", 134, Rarity.COMMON, mage.cards.u.UrborgSkeleton.class));
- cards.add(new SetCardInfo("Urborg Volcano", 330, Rarity.UNCOMMON, mage.cards.u.UrborgVolcano.class));
- cards.add(new SetCardInfo("Urza's Filter", 318, Rarity.RARE, mage.cards.u.UrzasFilter.class));
- cards.add(new SetCardInfo("Urza's Rage", 178, Rarity.RARE, mage.cards.u.UrzasRage.class));
- cards.add(new SetCardInfo("Utopia Tree", 219, Rarity.RARE, mage.cards.u.UtopiaTree.class));
- cards.add(new SetCardInfo("Verdeloth the Ancient", 220, Rarity.RARE, mage.cards.v.VerdelothTheAncient.class));
- cards.add(new SetCardInfo("Verduran Emissary", 221, Rarity.UNCOMMON, mage.cards.v.VerduranEmissary.class));
- cards.add(new SetCardInfo("Viashino Grappler", 179, Rarity.COMMON, mage.cards.v.ViashinoGrappler.class));
- cards.add(new SetCardInfo("Vicious Kavu", 284, Rarity.UNCOMMON, mage.cards.v.ViciousKavu.class));
- cards.add(new SetCardInfo("Vile Consumption", 285, Rarity.RARE, mage.cards.v.VileConsumption.class));
- cards.add(new SetCardInfo("Vodalian Hypnotist", 84, Rarity.UNCOMMON, mage.cards.v.VodalianHypnotist.class));
- cards.add(new SetCardInfo("Vodalian Merchant", 85, Rarity.COMMON, mage.cards.v.VodalianMerchant.class));
- cards.add(new SetCardInfo("Vodalian Serpent", 86, Rarity.COMMON, mage.cards.v.VodalianSerpent.class));
- cards.add(new SetCardInfo("Vodalian Zombie", 286, Rarity.COMMON, mage.cards.v.VodalianZombie.class));
- cards.add(new SetCardInfo("Void", 287, Rarity.RARE, mage.cards.v.Void.class));
- cards.add(new SetCardInfo("Voracious Cobra", 288, Rarity.UNCOMMON, mage.cards.v.VoraciousCobra.class));
- cards.add(new SetCardInfo("Wallop", 223, Rarity.UNCOMMON, mage.cards.w.Wallop.class));
- cards.add(new SetCardInfo("Wandering Stream", 224, Rarity.COMMON, mage.cards.w.WanderingStream.class));
- cards.add(new SetCardInfo("Wash Out", 87, Rarity.UNCOMMON, mage.cards.w.WashOut.class));
- cards.add(new SetCardInfo("Wax // Wane", 296, Rarity.UNCOMMON, mage.cards.w.WaxWane.class));
- cards.add(new SetCardInfo("Wayfaring Giant", 44, Rarity.UNCOMMON, mage.cards.w.WayfaringGiant.class));
- cards.add(new SetCardInfo("Whip Silk", 225, Rarity.COMMON, mage.cards.w.WhipSilk.class));
- cards.add(new SetCardInfo("Wings of Hope", 289, Rarity.COMMON, mage.cards.w.WingsOfHope.class));
- cards.add(new SetCardInfo("Winnow", 45, Rarity.RARE, mage.cards.w.Winnow.class));
- cards.add(new SetCardInfo("Worldly Counsel", 89, Rarity.COMMON, mage.cards.w.WorldlyCounsel.class));
- cards.add(new SetCardInfo("Yavimaya Barbarian", 290, Rarity.COMMON, mage.cards.y.YavimayaBarbarian.class));
- cards.add(new SetCardInfo("Yavimaya Kavu", 291, Rarity.UNCOMMON, mage.cards.y.YavimayaKavu.class));
- cards.add(new SetCardInfo("Yawgmoth's Agenda", 135, Rarity.RARE, mage.cards.y.YawgmothsAgenda.class));
- cards.add(new SetCardInfo("Zanam Djinn", 90, Rarity.UNCOMMON, mage.cards.z.ZanamDjinn.class));
- cards.add(new SetCardInfo("Zap", 180, Rarity.COMMON, mage.cards.z.Zap.class));
- }
-}
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.sets;
+
+import mage.cards.ExpansionSet;
+import mage.constants.Rarity;
+import mage.constants.SetType;
+
+/**
+ *
+ * @author North
+ */
+public class Invasion extends ExpansionSet {
+
+ private static final Invasion instance = new Invasion();
+
+ public static Invasion getInstance() {
+ return instance;
+ }
+
+ private Invasion() {
+ super("Invasion", "INV", ExpansionSet.buildDate(2000, 9, 2), SetType.EXPANSION);
+ this.blockName = "Invasion";
+ this.hasBoosters = true;
+ this.numBoosterLands = 0;
+ this.numBoosterCommon = 11;
+ this.numBoosterUncommon = 3;
+ this.numBoosterRare = 1;
+ this.ratioBoosterMythic = 0;
+ cards.add(new SetCardInfo("Absorb", 226, Rarity.RARE, mage.cards.a.Absorb.class));
+ cards.add(new SetCardInfo("Addle", 91, Rarity.UNCOMMON, mage.cards.a.Addle.class));
+ cards.add(new SetCardInfo("Aether Rift", 227, Rarity.RARE, mage.cards.a.AetherRift.class));
+ cards.add(new SetCardInfo("Aggressive Urge", 181, Rarity.COMMON, mage.cards.a.AggressiveUrge.class));
+ cards.add(new SetCardInfo("Agonizing Demise", 92, Rarity.COMMON, mage.cards.a.AgonizingDemise.class));
+ cards.add(new SetCardInfo("Alabaster Leech", 1, Rarity.RARE, mage.cards.a.AlabasterLeech.class));
+ cards.add(new SetCardInfo("Alloy Golem", 297, Rarity.UNCOMMON, mage.cards.a.AlloyGolem.class));
+ cards.add(new SetCardInfo("Ancient Kavu", 136, Rarity.COMMON, mage.cards.a.AncientKavu.class));
+ cards.add(new SetCardInfo("Ancient Spring", 319, Rarity.COMMON, mage.cards.a.AncientSpring.class));
+ cards.add(new SetCardInfo("Andradite Leech", 93, Rarity.RARE, mage.cards.a.AndraditeLeech.class));
+ cards.add(new SetCardInfo("Angelic Shield", 228, Rarity.UNCOMMON, mage.cards.a.AngelicShield.class));
+ cards.add(new SetCardInfo("Angel of Mercy", 2, Rarity.UNCOMMON, mage.cards.a.AngelOfMercy.class));
+ cards.add(new SetCardInfo("Annihilate", 94, Rarity.UNCOMMON, mage.cards.a.Annihilate.class));
+ cards.add(new SetCardInfo("Archaeological Dig", 320, Rarity.UNCOMMON, mage.cards.a.ArchaeologicalDig.class));
+ cards.add(new SetCardInfo("Ardent Soldier", 3, Rarity.COMMON, mage.cards.a.ArdentSoldier.class));
+ cards.add(new SetCardInfo("Armadillo Cloak", 229, Rarity.COMMON, mage.cards.a.ArmadilloCloak.class));
+ cards.add(new SetCardInfo("Armored Guardian", 230, Rarity.RARE, mage.cards.a.ArmoredGuardian.class));
+ cards.add(new SetCardInfo("Artifact Mutation", 231, Rarity.RARE, mage.cards.a.ArtifactMutation.class));
+ cards.add(new SetCardInfo("Assault // Battery", 295, Rarity.UNCOMMON, mage.cards.a.AssaultBattery.class));
+ cards.add(new SetCardInfo("Atalya, Samite Master", 4, Rarity.RARE, mage.cards.a.AtalyaSamiteMaster.class));
+ cards.add(new SetCardInfo("Aura Mutation", 232, Rarity.RARE, mage.cards.a.AuraMutation.class));
+ cards.add(new SetCardInfo("Aura Shards", 233, Rarity.UNCOMMON, mage.cards.a.AuraShards.class));
+ cards.add(new SetCardInfo("Backlash", 234, Rarity.UNCOMMON, mage.cards.b.Backlash.class));
+ cards.add(new SetCardInfo("Barrin's Spite", 235, Rarity.RARE, mage.cards.b.BarrinsSpite.class));
+ cards.add(new SetCardInfo("Barrin's Unmaking", 46, Rarity.COMMON, mage.cards.b.BarrinsUnmaking.class));
+ cards.add(new SetCardInfo("Benalish Emissary", 5, Rarity.UNCOMMON, mage.cards.b.BenalishEmissary.class));
+ cards.add(new SetCardInfo("Benalish Heralds", 6, Rarity.UNCOMMON, mage.cards.b.BenalishHeralds.class));
+ cards.add(new SetCardInfo("Benalish Lancer", 7, Rarity.COMMON, mage.cards.b.BenalishLancer.class));
+ cards.add(new SetCardInfo("Benalish Trapper", 8, Rarity.COMMON, mage.cards.b.BenalishTrapper.class));
+ cards.add(new SetCardInfo("Bind", 182, Rarity.RARE, mage.cards.b.Bind.class));
+ cards.add(new SetCardInfo("Blazing Specter", 236, Rarity.RARE, mage.cards.b.BlazingSpecter.class));
+ cards.add(new SetCardInfo("Blinding Light", 9, Rarity.UNCOMMON, mage.cards.b.BlindingLight.class));
+ cards.add(new SetCardInfo("Blind Seer", 47, Rarity.RARE, mage.cards.b.BlindSeer.class));
+ cards.add(new SetCardInfo("Bloodstone Cameo", 298, Rarity.UNCOMMON, mage.cards.b.BloodstoneCameo.class));
+ cards.add(new SetCardInfo("Blurred Mongoose", 183, Rarity.RARE, mage.cards.b.BlurredMongoose.class));
+ cards.add(new SetCardInfo("Bog Initiate", 95, Rarity.COMMON, mage.cards.b.BogInitiate.class));
+ cards.add(new SetCardInfo("Breaking Wave", 48, Rarity.RARE, mage.cards.b.BreakingWave.class));
+ cards.add(new SetCardInfo("Breath of Darigaaz", 138, Rarity.UNCOMMON, mage.cards.b.BreathOfDarigaaz.class));
+ cards.add(new SetCardInfo("Callous Giant", 139, Rarity.RARE, mage.cards.c.CallousGiant.class));
+ cards.add(new SetCardInfo("Canopy Surge", 184, Rarity.UNCOMMON, mage.cards.c.CanopySurge.class));
+ cards.add(new SetCardInfo("Capashen Unicorn", 10, Rarity.COMMON, mage.cards.c.CapashenUnicorn.class));
+ cards.add(new SetCardInfo("Captain Sisay", 237, Rarity.RARE, mage.cards.c.CaptainSisay.class));
+ cards.add(new SetCardInfo("Cauldron Dance", 238, Rarity.UNCOMMON, mage.cards.c.CauldronDance.class));
+ cards.add(new SetCardInfo("Chaotic Strike", 140, Rarity.UNCOMMON, mage.cards.c.ChaoticStrike.class));
+ cards.add(new SetCardInfo("Charging Troll", 239, Rarity.UNCOMMON, mage.cards.c.ChargingTroll.class));
+ cards.add(new SetCardInfo("Chromatic Sphere", 299, Rarity.UNCOMMON, mage.cards.c.ChromaticSphere.class));
+ cards.add(new SetCardInfo("Cinder Shade", 240, Rarity.UNCOMMON, mage.cards.c.CinderShade.class));
+ cards.add(new SetCardInfo("Coalition Victory", 241, Rarity.RARE, mage.cards.c.CoalitionVictory.class));
+ cards.add(new SetCardInfo("Coastal Tower", 321, Rarity.UNCOMMON, mage.cards.c.CoastalTower.class));
+ cards.add(new SetCardInfo("Collapsing Borders", 141, Rarity.RARE, mage.cards.c.CollapsingBorders.class));
+ cards.add(new SetCardInfo("Collective Restraint", 49, Rarity.RARE, mage.cards.c.CollectiveRestraint.class));
+ cards.add(new SetCardInfo("Cremate", 96, Rarity.UNCOMMON, mage.cards.c.Cremate.class));
+ cards.add(new SetCardInfo("Crimson Acolyte", 11, Rarity.COMMON, mage.cards.c.CrimsonAcolyte.class));
+ cards.add(new SetCardInfo("Crosis's Attendant", 300, Rarity.UNCOMMON, mage.cards.c.CrosissAttendant.class));
+ cards.add(new SetCardInfo("Crosis, the Purger", 242, Rarity.RARE, mage.cards.c.CrosisThePurger.class));
+ cards.add(new SetCardInfo("Crown of Flames", 142, Rarity.COMMON, mage.cards.c.CrownOfFlames.class));
+ cards.add(new SetCardInfo("Crusading Knight", 12, Rarity.RARE, mage.cards.c.CrusadingKnight.class));
+ cards.add(new SetCardInfo("Crypt Angel", 97, Rarity.RARE, mage.cards.c.CryptAngel.class));
+ cards.add(new SetCardInfo("Cursed Flesh", 98, Rarity.COMMON, mage.cards.c.CursedFlesh.class));
+ cards.add(new SetCardInfo("Darigaaz's Attendant", 301, Rarity.UNCOMMON, mage.cards.d.DarigaazsAttendant.class));
+ cards.add(new SetCardInfo("Darigaaz, the Igniter", 243, Rarity.RARE, mage.cards.d.DarigaazTheIgniter.class));
+ cards.add(new SetCardInfo("Defiling Tears", 99, Rarity.UNCOMMON, mage.cards.d.DefilingTears.class));
+ cards.add(new SetCardInfo("Devouring Strossus", 101, Rarity.RARE, mage.cards.d.DevouringStrossus.class));
+ cards.add(new SetCardInfo("Dismantling Blow", 14, Rarity.COMMON, mage.cards.d.DismantlingBlow.class));
+ cards.add(new SetCardInfo("Disrupt", 51, Rarity.UNCOMMON, mage.cards.d.Disrupt.class));
+ cards.add(new SetCardInfo("Distorting Wake", 52, Rarity.RARE, mage.cards.d.DistortingWake.class));
+ cards.add(new SetCardInfo("Divine Presence", 15, Rarity.RARE, mage.cards.d.DivinePresence.class));
+ cards.add(new SetCardInfo("Do or Die", 102, Rarity.RARE, mage.cards.d.DoOrDie.class));
+ cards.add(new SetCardInfo("Drake-Skull Cameo", 302, Rarity.UNCOMMON, mage.cards.d.DrakeSkullCameo.class));
+ cards.add(new SetCardInfo("Dream Thrush", 53, Rarity.COMMON, mage.cards.d.DreamThrush.class));
+ cards.add(new SetCardInfo("Dredge", 103, Rarity.UNCOMMON, mage.cards.d.Dredge.class));
+ cards.add(new SetCardInfo("Dromar's Attendant", 303, Rarity.UNCOMMON, mage.cards.d.DromarsAttendant.class));
+ cards.add(new SetCardInfo("Dromar, the Banisher", 244, Rarity.RARE, mage.cards.d.DromarTheBanisher.class));
+ cards.add(new SetCardInfo("Dueling Grounds", 245, Rarity.RARE, mage.cards.d.DuelingGrounds.class));
+ cards.add(new SetCardInfo("Duskwalker", 104, Rarity.COMMON, mage.cards.d.Duskwalker.class));
+ cards.add(new SetCardInfo("Elfhame Palace", 322, Rarity.UNCOMMON, mage.cards.e.ElfhamePalace.class));
+ cards.add(new SetCardInfo("Elfhame Sanctuary", 185, Rarity.UNCOMMON, mage.cards.e.ElfhameSanctuary.class));
+ cards.add(new SetCardInfo("Elvish Champion", 186, Rarity.RARE, mage.cards.e.ElvishChampion.class));
+ cards.add(new SetCardInfo("Empress Galina", 54, Rarity.RARE, mage.cards.e.EmpressGalina.class));
+ cards.add(new SetCardInfo("Exclude", 56, Rarity.COMMON, mage.cards.e.Exclude.class));
+ cards.add(new SetCardInfo("Exotic Curse", 105, Rarity.COMMON, mage.cards.e.ExoticCurse.class));
+ cards.add(new SetCardInfo("Explosive Growth", 187, Rarity.COMMON, mage.cards.e.ExplosiveGrowth.class));
+ cards.add(new SetCardInfo("Fact or Fiction", 57, Rarity.UNCOMMON, mage.cards.f.FactOrFiction.class));
+ cards.add(new SetCardInfo("Faerie Squadron", 58, Rarity.COMMON, mage.cards.f.FaerieSquadron.class));
+ cards.add(new SetCardInfo("Fertile Ground", 188, Rarity.COMMON, mage.cards.f.FertileGround.class));
+ cards.add(new SetCardInfo("Firebrand Ranger", 143, Rarity.UNCOMMON, mage.cards.f.FirebrandRanger.class));
+ cards.add(new SetCardInfo("Firescreamer", 106, Rarity.COMMON, mage.cards.f.Firescreamer.class));
+ cards.add(new SetCardInfo("Fires of Yavimaya", 246, Rarity.UNCOMMON, mage.cards.f.FiresOfYavimaya.class));
+ cards.add(new SetCardInfo("Forest", 347, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Forest", 348, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Forest", 349, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Forest", 350, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Frenzied Tilling", 247, Rarity.COMMON, mage.cards.f.FrenziedTilling.class));
+ cards.add(new SetCardInfo("Galina's Knight", 248, Rarity.COMMON, mage.cards.g.GalinasKnight.class));
+ cards.add(new SetCardInfo("Geothermal Crevice", 323, Rarity.COMMON, mage.cards.g.GeothermalCrevice.class));
+ cards.add(new SetCardInfo("Ghitu Fire", 144, Rarity.RARE, mage.cards.g.GhituFire.class));
+ cards.add(new SetCardInfo("Glimmering Angel", 17, Rarity.COMMON, mage.cards.g.GlimmeringAngel.class));
+ cards.add(new SetCardInfo("Global Ruin", 18, Rarity.RARE, mage.cards.g.GlobalRuin.class));
+ cards.add(new SetCardInfo("Goblin Spy", 145, Rarity.UNCOMMON, mage.cards.g.GoblinSpy.class));
+ cards.add(new SetCardInfo("Goham Djinn", 107, Rarity.UNCOMMON, mage.cards.g.GohamDjinn.class));
+ cards.add(new SetCardInfo("Halam Djinn", 146, Rarity.UNCOMMON, mage.cards.h.HalamDjinn.class));
+ cards.add(new SetCardInfo("Hanna, Ship's Navigator", 249, Rarity.RARE, mage.cards.h.HannaShipsNavigator.class));
+ cards.add(new SetCardInfo("Harrow", 189, Rarity.COMMON, mage.cards.h.Harrow.class));
+ cards.add(new SetCardInfo("Harsh Judgment", 19, Rarity.RARE, mage.cards.h.HarshJudgment.class));
+ cards.add(new SetCardInfo("Hate Weaver", 108, Rarity.UNCOMMON, mage.cards.h.HateWeaver.class));
+ cards.add(new SetCardInfo("Heroes' Reunion", 250, Rarity.UNCOMMON, mage.cards.h.HeroesReunion.class));
+ cards.add(new SetCardInfo("Holy Day", 20, Rarity.COMMON, mage.cards.h.HolyDay.class));
+ cards.add(new SetCardInfo("Hooded Kavu", 147, Rarity.COMMON, mage.cards.h.HoodedKavu.class));
+ cards.add(new SetCardInfo("Horned Cheetah", 251, Rarity.UNCOMMON, mage.cards.h.HornedCheetah.class));
+ cards.add(new SetCardInfo("Hunting Kavu", 252, Rarity.UNCOMMON, mage.cards.h.HuntingKavu.class));
+ cards.add(new SetCardInfo("Hypnotic Cloud", 109, Rarity.COMMON, mage.cards.h.HypnoticCloud.class));
+ cards.add(new SetCardInfo("Irrigation Ditch", 324, Rarity.COMMON, mage.cards.i.IrrigationDitch.class));
+ cards.add(new SetCardInfo("Island", 335, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Island", 336, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Island", 337, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Island", 338, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Jade Leech", 190, Rarity.RARE, mage.cards.j.JadeLeech.class));
+ cards.add(new SetCardInfo("Juntu Stakes", 304, Rarity.RARE, mage.cards.j.JuntuStakes.class));
+ cards.add(new SetCardInfo("Kangee, Aerie Keeper", 253, Rarity.RARE, mage.cards.k.KangeeAerieKeeper.class));
+ cards.add(new SetCardInfo("Kavu Aggressor", 148, Rarity.COMMON, mage.cards.k.KavuAggressor.class));
+ cards.add(new SetCardInfo("Kavu Chameleon", 191, Rarity.UNCOMMON, mage.cards.k.KavuChameleon.class));
+ cards.add(new SetCardInfo("Kavu Climber", 192, Rarity.COMMON, mage.cards.k.KavuClimber.class));
+ cards.add(new SetCardInfo("Kavu Lair", 193, Rarity.RARE, mage.cards.k.KavuLair.class));
+ cards.add(new SetCardInfo("Kavu Monarch", 149, Rarity.RARE, mage.cards.k.KavuMonarch.class));
+ cards.add(new SetCardInfo("Kavu Runner", 150, Rarity.UNCOMMON, mage.cards.k.KavuRunner.class));
+ cards.add(new SetCardInfo("Kavu Scout", 151, Rarity.COMMON, mage.cards.k.KavuScout.class));
+ cards.add(new SetCardInfo("Kavu Titan", 194, Rarity.RARE, mage.cards.k.KavuTitan.class));
+ cards.add(new SetCardInfo("Keldon Necropolis", 325, Rarity.RARE, mage.cards.k.KeldonNecropolis.class));
+ cards.add(new SetCardInfo("Liberate", 21, Rarity.UNCOMMON, mage.cards.l.Liberate.class));
+ cards.add(new SetCardInfo("Lightning Dart", 152, Rarity.UNCOMMON, mage.cards.l.LightningDart.class));
+ cards.add(new SetCardInfo("Llanowar Cavalry", 195, Rarity.COMMON, mage.cards.l.LlanowarCavalry.class));
+ cards.add(new SetCardInfo("Llanowar Elite", 196, Rarity.COMMON, mage.cards.l.LlanowarElite.class));
+ cards.add(new SetCardInfo("Llanowar Knight", 254, Rarity.COMMON, mage.cards.l.LlanowarKnight.class));
+ cards.add(new SetCardInfo("Llanowar Vanguard", 197, Rarity.COMMON, mage.cards.l.LlanowarVanguard.class));
+ cards.add(new SetCardInfo("Lobotomy", 255, Rarity.UNCOMMON, mage.cards.l.Lobotomy.class));
+ cards.add(new SetCardInfo("Lotus Guardian", 305, Rarity.RARE, mage.cards.l.LotusGuardian.class));
+ cards.add(new SetCardInfo("Mana Maze", 59, Rarity.RARE, mage.cards.m.ManaMaze.class));
+ cards.add(new SetCardInfo("Maniacal Rage", 155, Rarity.COMMON, mage.cards.m.ManiacalRage.class));
+ cards.add(new SetCardInfo("Manipulate Fate", 60, Rarity.UNCOMMON, mage.cards.m.ManipulateFate.class));
+ cards.add(new SetCardInfo("Marauding Knight", 110, Rarity.RARE, mage.cards.m.MaraudingKnight.class));
+ cards.add(new SetCardInfo("Metathran Transport", 62, Rarity.UNCOMMON, mage.cards.m.MetathranTransport.class));
+ cards.add(new SetCardInfo("Metathran Zombie", 63, Rarity.COMMON, mage.cards.m.MetathranZombie.class));
+ cards.add(new SetCardInfo("Meteor Storm", 256, Rarity.RARE, mage.cards.m.MeteorStorm.class));
+ cards.add(new SetCardInfo("Might Weaver", 198, Rarity.UNCOMMON, mage.cards.m.MightWeaver.class));
+ cards.add(new SetCardInfo("Molimo, Maro-Sorcerer", 199, Rarity.RARE, mage.cards.m.MolimoMaroSorcerer.class));
+ cards.add(new SetCardInfo("Mountain", 343, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Mountain", 344, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Mountain", 345, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Mountain", 346, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Mourning", 111, Rarity.COMMON, mage.cards.m.Mourning.class));
+ cards.add(new SetCardInfo("Nightscape Apprentice", 112, Rarity.COMMON, mage.cards.n.NightscapeApprentice.class));
+ cards.add(new SetCardInfo("Nightscape Master", 113, Rarity.RARE, mage.cards.n.NightscapeMaster.class));
+ cards.add(new SetCardInfo("Noble Panther", 257, Rarity.RARE, mage.cards.n.NoblePanther.class));
+ cards.add(new SetCardInfo("Nomadic Elf", 200, Rarity.COMMON, mage.cards.n.NomadicElf.class));
+ cards.add(new SetCardInfo("Obliterate", 156, Rarity.RARE, mage.cards.o.Obliterate.class));
+ cards.add(new SetCardInfo("Obsidian Acolyte", 22, Rarity.COMMON, mage.cards.o.ObsidianAcolyte.class));
+ cards.add(new SetCardInfo("Opt", 64, Rarity.COMMON, mage.cards.o.Opt.class));
+ cards.add(new SetCardInfo("Ordered Migration", 258, Rarity.UNCOMMON, mage.cards.o.OrderedMigration.class));
+ cards.add(new SetCardInfo("Orim's Touch", 23, Rarity.COMMON, mage.cards.o.OrimsTouch.class));
+ cards.add(new SetCardInfo("Overabundance", 259, Rarity.RARE, mage.cards.o.Overabundance.class));
+ cards.add(new SetCardInfo("Overload", 157, Rarity.COMMON, mage.cards.o.Overload.class));
+ cards.add(new SetCardInfo("Pain // Suffering", 294, Rarity.UNCOMMON, mage.cards.p.PainSuffering.class));
+ cards.add(new SetCardInfo("Phantasmal Terrain", 65, Rarity.COMMON, mage.cards.p.PhantasmalTerrain.class));
+ cards.add(new SetCardInfo("Phyrexian Altar", 306, Rarity.RARE, mage.cards.p.PhyrexianAltar.class));
+ cards.add(new SetCardInfo("Phyrexian Battleflies", 114, Rarity.COMMON, mage.cards.p.PhyrexianBattleflies.class));
+ cards.add(new SetCardInfo("Phyrexian Delver", 115, Rarity.RARE, mage.cards.p.PhyrexianDelver.class));
+ cards.add(new SetCardInfo("Phyrexian Infiltrator", 116, Rarity.RARE, mage.cards.p.PhyrexianInfiltrator.class));
+ cards.add(new SetCardInfo("Phyrexian Lens", 307, Rarity.RARE, mage.cards.p.PhyrexianLens.class));
+ cards.add(new SetCardInfo("Phyrexian Reaper", 117, Rarity.COMMON, mage.cards.p.PhyrexianReaper.class));
+ cards.add(new SetCardInfo("Phyrexian Slayer", 118, Rarity.COMMON, mage.cards.p.PhyrexianSlayer.class));
+ cards.add(new SetCardInfo("Pincer Spider", 201, Rarity.COMMON, mage.cards.p.PincerSpider.class));
+ cards.add(new SetCardInfo("Plague Spitter", 119, Rarity.UNCOMMON, mage.cards.p.PlagueSpitter.class));
+ cards.add(new SetCardInfo("Plague Spores", 260, Rarity.COMMON, mage.cards.p.PlagueSpores.class));
+ cards.add(new SetCardInfo("Plains", 331, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Plains", 332, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Plains", 333, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Plains", 334, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Planar Portal", 308, Rarity.RARE, mage.cards.p.PlanarPortal.class));
+ cards.add(new SetCardInfo("Pouncing Kavu", 158, Rarity.COMMON, mage.cards.p.PouncingKavu.class));
+ cards.add(new SetCardInfo("Power Armor", 309, Rarity.UNCOMMON, mage.cards.p.PowerArmor.class));
+ cards.add(new SetCardInfo("Prison Barricade", 25, Rarity.COMMON, mage.cards.p.PrisonBarricade.class));
+ cards.add(new SetCardInfo("Probe", 66, Rarity.COMMON, mage.cards.p.Probe.class));
+ cards.add(new SetCardInfo("Prohibit", 67, Rarity.COMMON, mage.cards.p.Prohibit.class));
+ cards.add(new SetCardInfo("Protective Sphere", 26, Rarity.COMMON, mage.cards.p.ProtectiveSphere.class));
+ cards.add(new SetCardInfo("Pure Reflection", 27, Rarity.RARE, mage.cards.p.PureReflection.class));
+ cards.add(new SetCardInfo("Pyre Zombie", 261, Rarity.RARE, mage.cards.p.PyreZombie.class));
+ cards.add(new SetCardInfo("Quirion Elves", 203, Rarity.COMMON, mage.cards.q.QuirionElves.class));
+ cards.add(new SetCardInfo("Quirion Sentinel", 204, Rarity.COMMON, mage.cards.q.QuirionSentinel.class));
+ cards.add(new SetCardInfo("Quirion Trailblazer", 205, Rarity.COMMON, mage.cards.q.QuirionTrailblazer.class));
+ cards.add(new SetCardInfo("Rage Weaver", 159, Rarity.UNCOMMON, mage.cards.r.RageWeaver.class));
+ cards.add(new SetCardInfo("Raging Kavu", 262, Rarity.RARE, mage.cards.r.RagingKavu.class));
+ cards.add(new SetCardInfo("Rainbow Crow", 69, Rarity.UNCOMMON, mage.cards.r.RainbowCrow.class));
+ cards.add(new SetCardInfo("Rampant Elephant", 28, Rarity.COMMON, mage.cards.r.RampantElephant.class));
+ cards.add(new SetCardInfo("Ravenous Rats", 120, Rarity.COMMON, mage.cards.r.RavenousRats.class));
+ cards.add(new SetCardInfo("Razorfoot Griffin", 29, Rarity.COMMON, mage.cards.r.RazorfootGriffin.class));
+ cards.add(new SetCardInfo("Reckless Assault", 263, Rarity.RARE, mage.cards.r.RecklessAssault.class));
+ cards.add(new SetCardInfo("Reckless Spite", 121, Rarity.UNCOMMON, mage.cards.r.RecklessSpite.class));
+ cards.add(new SetCardInfo("Recoil", 264, Rarity.COMMON, mage.cards.r.Recoil.class));
+ cards.add(new SetCardInfo("Recover", 122, Rarity.COMMON, mage.cards.r.Recover.class));
+ cards.add(new SetCardInfo("Repulse", 70, Rarity.COMMON, mage.cards.r.Repulse.class));
+ cards.add(new SetCardInfo("Restock", 206, Rarity.RARE, mage.cards.r.Restock.class));
+ cards.add(new SetCardInfo("Restrain", 30, Rarity.COMMON, mage.cards.r.Restrain.class));
+ cards.add(new SetCardInfo("Reviving Dose", 31, Rarity.COMMON, mage.cards.r.RevivingDose.class));
+ cards.add(new SetCardInfo("Reviving Vapors", 265, Rarity.UNCOMMON, mage.cards.r.RevivingVapors.class));
+ cards.add(new SetCardInfo("Rewards of Diversity", 32, Rarity.UNCOMMON, mage.cards.r.RewardsOfDiversity.class));
+ cards.add(new SetCardInfo("Reya Dawnbringer", 33, Rarity.RARE, mage.cards.r.ReyaDawnbringer.class));
+ cards.add(new SetCardInfo("Riptide Crab", 266, Rarity.UNCOMMON, mage.cards.r.RiptideCrab.class));
+ cards.add(new SetCardInfo("Rith's Attendant", 310, Rarity.UNCOMMON, mage.cards.r.RithsAttendant.class));
+ cards.add(new SetCardInfo("Rith, the Awakener", 267, Rarity.RARE, mage.cards.r.RithTheAwakener.class));
+ cards.add(new SetCardInfo("Rogue Kavu", 160, Rarity.COMMON, mage.cards.r.RogueKavu.class));
+ cards.add(new SetCardInfo("Rooting Kavu", 207, Rarity.UNCOMMON, mage.cards.r.RootingKavu.class));
+ cards.add(new SetCardInfo("Rout", 34, Rarity.RARE, mage.cards.r.Rout.class));
+ cards.add(new SetCardInfo("Ruby Leech", 161, Rarity.RARE, mage.cards.r.RubyLeech.class));
+ cards.add(new SetCardInfo("Ruham Djinn", 35, Rarity.UNCOMMON, mage.cards.r.RuhamDjinn.class));
+ cards.add(new SetCardInfo("Sabertooth Nishoba", 268, Rarity.RARE, mage.cards.s.SabertoothNishoba.class));
+ cards.add(new SetCardInfo("Salt Marsh", 326, Rarity.UNCOMMON, mage.cards.s.SaltMarsh.class));
+ cards.add(new SetCardInfo("Samite Archer", 269, Rarity.UNCOMMON, mage.cards.s.SamiteArcher.class));
+ cards.add(new SetCardInfo("Sapphire Leech", 71, Rarity.RARE, mage.cards.s.SapphireLeech.class));
+ cards.add(new SetCardInfo("Saproling Symbiosis", 209, Rarity.RARE, mage.cards.s.SaprolingSymbiosis.class));
+ cards.add(new SetCardInfo("Savage Offensive", 162, Rarity.COMMON, mage.cards.s.SavageOffensive.class));
+ cards.add(new SetCardInfo("Scarred Puma", 163, Rarity.COMMON, mage.cards.s.ScarredPuma.class));
+ cards.add(new SetCardInfo("Scavenged Weaponry", 123, Rarity.COMMON, mage.cards.s.ScavengedWeaponry.class));
+ cards.add(new SetCardInfo("Scorching Lava", 164, Rarity.COMMON, mage.cards.s.ScorchingLava.class));
+ cards.add(new SetCardInfo("Scouting Trek", 210, Rarity.UNCOMMON, mage.cards.s.ScoutingTrek.class));
+ cards.add(new SetCardInfo("Seashell Cameo", 311, Rarity.UNCOMMON, mage.cards.s.SeashellCameo.class));
+ cards.add(new SetCardInfo("Seer's Vision", 270, Rarity.UNCOMMON, mage.cards.s.SeersVision.class));
+ cards.add(new SetCardInfo("Serpentine Kavu", 211, Rarity.COMMON, mage.cards.s.SerpentineKavu.class));
+ cards.add(new SetCardInfo("Shackles", 37, Rarity.COMMON, mage.cards.s.Shackles.class));
+ cards.add(new SetCardInfo("Shimmering Wings", 72, Rarity.COMMON, mage.cards.s.ShimmeringWings.class));
+ cards.add(new SetCardInfo("Shivan Emissary", 166, Rarity.UNCOMMON, mage.cards.s.ShivanEmissary.class));
+ cards.add(new SetCardInfo("Shivan Harvest", 167, Rarity.UNCOMMON, mage.cards.s.ShivanHarvest.class));
+ cards.add(new SetCardInfo("Shivan Oasis", 327, Rarity.UNCOMMON, mage.cards.s.ShivanOasis.class));
+ cards.add(new SetCardInfo("Shivan Zombie", 271, Rarity.COMMON, mage.cards.s.ShivanZombie.class));
+ cards.add(new SetCardInfo("Shoreline Raider", 73, Rarity.COMMON, mage.cards.s.ShorelineRaider.class));
+ cards.add(new SetCardInfo("Simoon", 272, Rarity.UNCOMMON, mage.cards.s.Simoon.class));
+ cards.add(new SetCardInfo("Skittish Kavu", 168, Rarity.UNCOMMON, mage.cards.s.SkittishKavu.class));
+ cards.add(new SetCardInfo("Skizzik", 169, Rarity.RARE, mage.cards.s.Skizzik.class));
+ cards.add(new SetCardInfo("Sky Weaver", 74, Rarity.UNCOMMON, mage.cards.s.SkyWeaver.class));
+ cards.add(new SetCardInfo("Sleeper's Robe", 273, Rarity.UNCOMMON, mage.cards.s.SleepersRobe.class));
+ cards.add(new SetCardInfo("Slimy Kavu", 170, Rarity.COMMON, mage.cards.s.SlimyKavu.class));
+ cards.add(new SetCardInfo("Slinking Serpent", 274, Rarity.UNCOMMON, mage.cards.s.SlinkingSerpent.class));
+ cards.add(new SetCardInfo("Smoldering Tar", 275, Rarity.UNCOMMON, mage.cards.s.SmolderingTar.class));
+ cards.add(new SetCardInfo("Soul Burn", 124, Rarity.COMMON, mage.cards.s.SoulBurn.class));
+ cards.add(new SetCardInfo("Sparring Golem", 312, Rarity.UNCOMMON, mage.cards.s.SparringGolem.class));
+ cards.add(new SetCardInfo("Spinal Embrace", 276, Rarity.RARE, mage.cards.s.SpinalEmbrace.class));
+ cards.add(new SetCardInfo("Spirit of Resistance", 38, Rarity.RARE, mage.cards.s.SpiritOfResistance.class));
+ cards.add(new SetCardInfo("Spirit Weaver", 39, Rarity.UNCOMMON, mage.cards.s.SpiritWeaver.class));
+ cards.add(new SetCardInfo("Spite // Malice", 293, Rarity.UNCOMMON, mage.cards.s.SpiteMalice.class));
+ cards.add(new SetCardInfo("Spreading Plague", 125, Rarity.RARE, mage.cards.s.SpreadingPlague.class));
+ cards.add(new SetCardInfo("Stalking Assassin", 277, Rarity.RARE, mage.cards.s.StalkingAssassin.class));
+ cards.add(new SetCardInfo("Stand // Deliver", 292, Rarity.UNCOMMON, mage.cards.s.StandDeliver.class));
+ cards.add(new SetCardInfo("Sterling Grove", 278, Rarity.UNCOMMON, mage.cards.s.SterlingGrove.class));
+ cards.add(new SetCardInfo("Stormscape Apprentice", 75, Rarity.COMMON, mage.cards.s.StormscapeApprentice.class));
+ cards.add(new SetCardInfo("Stormscape Master", 76, Rarity.RARE, mage.cards.s.StormscapeMaster.class));
+ cards.add(new SetCardInfo("Strength of Unity", 40, Rarity.COMMON, mage.cards.s.StrengthOfUnity.class));
+ cards.add(new SetCardInfo("Stun", 172, Rarity.COMMON, mage.cards.s.Stun.class));
+ cards.add(new SetCardInfo("Sulam Djinn", 212, Rarity.UNCOMMON, mage.cards.s.SulamDjinn.class));
+ cards.add(new SetCardInfo("Sulfur Vent", 328, Rarity.COMMON, mage.cards.s.SulfurVent.class));
+ cards.add(new SetCardInfo("Sunscape Apprentice", 41, Rarity.COMMON, mage.cards.s.SunscapeApprentice.class));
+ cards.add(new SetCardInfo("Sunscape Master", 42, Rarity.RARE, mage.cards.s.SunscapeMaster.class));
+ cards.add(new SetCardInfo("Swamp", 339, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Swamp", 340, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Swamp", 341, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Swamp", 342, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Sway of Illusion", 77, Rarity.UNCOMMON, mage.cards.s.SwayOfIllusion.class));
+ cards.add(new SetCardInfo("Tainted Well", 126, Rarity.COMMON, mage.cards.t.TaintedWell.class));
+ cards.add(new SetCardInfo("Tangle", 213, Rarity.UNCOMMON, mage.cards.t.Tangle.class));
+ cards.add(new SetCardInfo("Tectonic Instability", 173, Rarity.RARE, mage.cards.t.TectonicInstability.class));
+ cards.add(new SetCardInfo("Teferi's Care", 43, Rarity.UNCOMMON, mage.cards.t.TeferisCare.class));
+ cards.add(new SetCardInfo("Teferi's Moat", 279, Rarity.RARE, mage.cards.t.TeferisMoat.class));
+ cards.add(new SetCardInfo("Teferi's Response", 78, Rarity.RARE, mage.cards.t.TeferisResponse.class));
+ cards.add(new SetCardInfo("Tek", 313, Rarity.RARE, mage.cards.t.Tek.class));
+ cards.add(new SetCardInfo("Temporal Distortion", 79, Rarity.RARE, mage.cards.t.TemporalDistortion.class));
+ cards.add(new SetCardInfo("Thicket Elemental", 214, Rarity.RARE, mage.cards.t.ThicketElemental.class));
+ cards.add(new SetCardInfo("Thornscape Apprentice", 215, Rarity.COMMON, mage.cards.t.ThornscapeApprentice.class));
+ cards.add(new SetCardInfo("Thornscape Master", 216, Rarity.RARE, mage.cards.t.ThornscapeMaster.class));
+ cards.add(new SetCardInfo("Thunderscape Apprentice", 174, Rarity.COMMON, mage.cards.t.ThunderscapeApprentice.class));
+ cards.add(new SetCardInfo("Thunderscape Master", 175, Rarity.RARE, mage.cards.t.ThunderscapeMaster.class));
+ cards.add(new SetCardInfo("Tidal Visionary", 80, Rarity.COMMON, mage.cards.t.TidalVisionary.class));
+ cards.add(new SetCardInfo("Tigereye Cameo", 314, Rarity.UNCOMMON, mage.cards.t.TigereyeCameo.class));
+ cards.add(new SetCardInfo("Tinder Farm", 329, Rarity.COMMON, mage.cards.t.TinderFarm.class));
+ cards.add(new SetCardInfo("Tolarian Emissary", 81, Rarity.UNCOMMON, mage.cards.t.TolarianEmissary.class));
+ cards.add(new SetCardInfo("Tower Drake", 82, Rarity.COMMON, mage.cards.t.TowerDrake.class));
+ cards.add(new SetCardInfo("Tranquility", 217, Rarity.COMMON, mage.cards.t.Tranquility.class));
+ cards.add(new SetCardInfo("Traveler's Cloak", 83, Rarity.COMMON, mage.cards.t.TravelersCloak.class));
+ cards.add(new SetCardInfo("Treefolk Healer", 218, Rarity.UNCOMMON, mage.cards.t.TreefolkHealer.class));
+ cards.add(new SetCardInfo("Trench Wurm", 127, Rarity.UNCOMMON, mage.cards.t.TrenchWurm.class));
+ cards.add(new SetCardInfo("Treva's Attendant", 315, Rarity.UNCOMMON, mage.cards.t.TrevasAttendant.class));
+ cards.add(new SetCardInfo("Treva, the Renewer", 280, Rarity.RARE, mage.cards.t.TrevaTheRenewer.class));
+ cards.add(new SetCardInfo("Tribal Flames", 176, Rarity.COMMON, mage.cards.t.TribalFlames.class));
+ cards.add(new SetCardInfo("Troll-Horn Cameo", 316, Rarity.UNCOMMON, mage.cards.t.TrollHornCameo.class));
+ cards.add(new SetCardInfo("Tsabo's Assassin", 128, Rarity.RARE, mage.cards.t.TsabosAssassin.class));
+ cards.add(new SetCardInfo("Tsabo's Decree", 129, Rarity.RARE, mage.cards.t.TsabosDecree.class));
+ cards.add(new SetCardInfo("Tsabo's Web", 317, Rarity.RARE, mage.cards.t.TsabosWeb.class));
+ cards.add(new SetCardInfo("Tsabo Tavoc", 281, Rarity.RARE, mage.cards.t.TsaboTavoc.class));
+ cards.add(new SetCardInfo("Turf Wound", 177, Rarity.COMMON, mage.cards.t.TurfWound.class));
+ cards.add(new SetCardInfo("Twilight's Call", 130, Rarity.RARE, mage.cards.t.TwilightsCall.class));
+ cards.add(new SetCardInfo("Undermine", 282, Rarity.RARE, mage.cards.u.Undermine.class));
+ cards.add(new SetCardInfo("Urborg Drake", 283, Rarity.UNCOMMON, mage.cards.u.UrborgDrake.class));
+ cards.add(new SetCardInfo("Urborg Emissary", 131, Rarity.UNCOMMON, mage.cards.u.UrborgEmissary.class));
+ cards.add(new SetCardInfo("Urborg Phantom", 132, Rarity.COMMON, mage.cards.u.UrborgPhantom.class));
+ cards.add(new SetCardInfo("Urborg Shambler", 133, Rarity.UNCOMMON, mage.cards.u.UrborgShambler.class));
+ cards.add(new SetCardInfo("Urborg Skeleton", 134, Rarity.COMMON, mage.cards.u.UrborgSkeleton.class));
+ cards.add(new SetCardInfo("Urborg Volcano", 330, Rarity.UNCOMMON, mage.cards.u.UrborgVolcano.class));
+ cards.add(new SetCardInfo("Urza's Filter", 318, Rarity.RARE, mage.cards.u.UrzasFilter.class));
+ cards.add(new SetCardInfo("Urza's Rage", 178, Rarity.RARE, mage.cards.u.UrzasRage.class));
+ cards.add(new SetCardInfo("Utopia Tree", 219, Rarity.RARE, mage.cards.u.UtopiaTree.class));
+ cards.add(new SetCardInfo("Verdeloth the Ancient", 220, Rarity.RARE, mage.cards.v.VerdelothTheAncient.class));
+ cards.add(new SetCardInfo("Verduran Emissary", 221, Rarity.UNCOMMON, mage.cards.v.VerduranEmissary.class));
+ cards.add(new SetCardInfo("Viashino Grappler", 179, Rarity.COMMON, mage.cards.v.ViashinoGrappler.class));
+ cards.add(new SetCardInfo("Vicious Kavu", 284, Rarity.UNCOMMON, mage.cards.v.ViciousKavu.class));
+ cards.add(new SetCardInfo("Vile Consumption", 285, Rarity.RARE, mage.cards.v.VileConsumption.class));
+ cards.add(new SetCardInfo("Vodalian Hypnotist", 84, Rarity.UNCOMMON, mage.cards.v.VodalianHypnotist.class));
+ cards.add(new SetCardInfo("Vodalian Merchant", 85, Rarity.COMMON, mage.cards.v.VodalianMerchant.class));
+ cards.add(new SetCardInfo("Vodalian Serpent", 86, Rarity.COMMON, mage.cards.v.VodalianSerpent.class));
+ cards.add(new SetCardInfo("Vodalian Zombie", 286, Rarity.COMMON, mage.cards.v.VodalianZombie.class));
+ cards.add(new SetCardInfo("Void", 287, Rarity.RARE, mage.cards.v.Void.class));
+ cards.add(new SetCardInfo("Voracious Cobra", 288, Rarity.UNCOMMON, mage.cards.v.VoraciousCobra.class));
+ cards.add(new SetCardInfo("Wallop", 223, Rarity.UNCOMMON, mage.cards.w.Wallop.class));
+ cards.add(new SetCardInfo("Wandering Stream", 224, Rarity.COMMON, mage.cards.w.WanderingStream.class));
+ cards.add(new SetCardInfo("Wash Out", 87, Rarity.UNCOMMON, mage.cards.w.WashOut.class));
+ cards.add(new SetCardInfo("Wax // Wane", 296, Rarity.UNCOMMON, mage.cards.w.WaxWane.class));
+ cards.add(new SetCardInfo("Wayfaring Giant", 44, Rarity.UNCOMMON, mage.cards.w.WayfaringGiant.class));
+ cards.add(new SetCardInfo("Whip Silk", 225, Rarity.COMMON, mage.cards.w.WhipSilk.class));
+ cards.add(new SetCardInfo("Wings of Hope", 289, Rarity.COMMON, mage.cards.w.WingsOfHope.class));
+ cards.add(new SetCardInfo("Winnow", 45, Rarity.RARE, mage.cards.w.Winnow.class));
+ cards.add(new SetCardInfo("Worldly Counsel", 89, Rarity.COMMON, mage.cards.w.WorldlyCounsel.class));
+ cards.add(new SetCardInfo("Yavimaya Barbarian", 290, Rarity.COMMON, mage.cards.y.YavimayaBarbarian.class));
+ cards.add(new SetCardInfo("Yavimaya Kavu", 291, Rarity.UNCOMMON, mage.cards.y.YavimayaKavu.class));
+ cards.add(new SetCardInfo("Yawgmoth's Agenda", 135, Rarity.RARE, mage.cards.y.YawgmothsAgenda.class));
+ cards.add(new SetCardInfo("Zanam Djinn", 90, Rarity.UNCOMMON, mage.cards.z.ZanamDjinn.class));
+ cards.add(new SetCardInfo("Zap", 180, Rarity.COMMON, mage.cards.z.Zap.class));
+ }
+}
diff --git a/Mage.Sets/src/mage/sets/Judgment.java b/Mage.Sets/src/mage/sets/Judgment.java
index 9007e49c9e7..fa99c1a1b31 100644
--- a/Mage.Sets/src/mage/sets/Judgment.java
+++ b/Mage.Sets/src/mage/sets/Judgment.java
@@ -163,6 +163,7 @@ public class Judgment extends ExpansionSet {
cards.add(new SetCardInfo("Swelter", 101, Rarity.UNCOMMON, mage.cards.s.Swelter.class));
cards.add(new SetCardInfo("Swirling Sandstorm", 102, Rarity.COMMON, mage.cards.s.SwirlingSandstorm.class));
cards.add(new SetCardInfo("Sylvan Safekeeper", 133, Rarity.RARE, mage.cards.s.SylvanSafekeeper.class));
+ cards.add(new SetCardInfo("Telekinetic Bonds", 52, Rarity.RARE, mage.cards.t.TelekineticBonds.class));
cards.add(new SetCardInfo("Test of Endurance", 29, Rarity.RARE, mage.cards.t.TestOfEndurance.class));
cards.add(new SetCardInfo("Thriss, Nantuko Primus", 134, Rarity.RARE, mage.cards.t.ThrissNantukoPrimus.class));
cards.add(new SetCardInfo("Toxic Stench", 74, Rarity.COMMON, mage.cards.t.ToxicStench.class));
diff --git a/Mage.Sets/src/mage/sets/Legends.java b/Mage.Sets/src/mage/sets/Legends.java
index ffd05358570..779015f3cdf 100644
--- a/Mage.Sets/src/mage/sets/Legends.java
+++ b/Mage.Sets/src/mage/sets/Legends.java
@@ -133,6 +133,7 @@ public class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Giant Strength", 147, Rarity.COMMON, mage.cards.g.GiantStrength.class));
cards.add(new SetCardInfo("Giant Turtle", 102, Rarity.COMMON, mage.cards.g.GiantTurtle.class));
cards.add(new SetCardInfo("Glyph of Destruction", 148, Rarity.COMMON, mage.cards.g.GlyphOfDestruction.class));
+ cards.add(new SetCardInfo("Glyph of Doom", 14, Rarity.COMMON, mage.cards.g.GlyphOfDoom.class));
cards.add(new SetCardInfo("Glyph of Life", 184, Rarity.COMMON, mage.cards.g.GlyphOfLife.class));
cards.add(new SetCardInfo("Gravity Sphere", 149, Rarity.RARE, mage.cards.g.GravitySphere.class));
cards.add(new SetCardInfo("Great Defender", 185, Rarity.UNCOMMON, mage.cards.g.GreatDefender.class));
@@ -299,6 +300,7 @@ public class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Winds of Change", 169, Rarity.UNCOMMON, mage.cards.w.WindsOfChange.class));
cards.add(new SetCardInfo("Winter Blast", 127, Rarity.RARE, mage.cards.w.WinterBlast.class));
cards.add(new SetCardInfo("Wolverine Pack", 128, Rarity.COMMON, mage.cards.w.WolverinePack.class));
+ cards.add(new SetCardInfo("Wood Elemental", 129, Rarity.RARE, mage.cards.w.WoodElemental.class));
cards.add(new SetCardInfo("Xira Arien", 310, Rarity.RARE, mage.cards.x.XiraArien.class));
cards.add(new SetCardInfo("Zephyr Falcon", 86, Rarity.COMMON, mage.cards.z.ZephyrFalcon.class));
}
diff --git a/Mage.Sets/src/mage/sets/Legions.java b/Mage.Sets/src/mage/sets/Legions.java
index 2622f22cb0a..7dc39c620b7 100644
--- a/Mage.Sets/src/mage/sets/Legions.java
+++ b/Mage.Sets/src/mage/sets/Legions.java
@@ -61,6 +61,7 @@ public class Legions extends ExpansionSet {
cards.add(new SetCardInfo("Aven Redeemer", 3, Rarity.COMMON, mage.cards.a.AvenRedeemer.class));
cards.add(new SetCardInfo("Aven Warhawk", 4, Rarity.UNCOMMON, mage.cards.a.AvenWarhawk.class));
cards.add(new SetCardInfo("Bane of the Living", 60, Rarity.RARE, mage.cards.b.BaneOfTheLiving.class));
+ cards.add(new SetCardInfo("Beacon of Destiny", 5, Rarity.RARE, mage.cards.b.BeaconOfDestiny.class));
cards.add(new SetCardInfo("Berserk Murlodont", 117, Rarity.COMMON, mage.cards.b.BerserkMurlodont.class));
cards.add(new SetCardInfo("Blade Sliver", 88, Rarity.UNCOMMON, mage.cards.b.BladeSliver.class));
cards.add(new SetCardInfo("Blood Celebrant", 61, Rarity.COMMON, mage.cards.b.BloodCelebrant.class));
@@ -141,6 +142,7 @@ public class Legions extends ExpansionSet {
cards.add(new SetCardInfo("Mistform Seaswift", 45, Rarity.COMMON, mage.cards.m.MistformSeaswift.class));
cards.add(new SetCardInfo("Mistform Sliver", 46, Rarity.COMMON, mage.cards.m.MistformSliver.class));
cards.add(new SetCardInfo("Mistform Ultimus", 47, Rarity.RARE, mage.cards.m.MistformUltimus.class));
+ cards.add(new SetCardInfo("Mistform Wakecaster", 48, Rarity.UNCOMMON, mage.cards.m.MistformWakecaster.class));
cards.add(new SetCardInfo("Nantuko Vigilante", 132, Rarity.COMMON, mage.cards.n.NantukoVigilante.class));
cards.add(new SetCardInfo("Needleshot Gourna", 133, Rarity.COMMON, mage.cards.n.NeedleshotGourna.class));
cards.add(new SetCardInfo("Noxious Ghoul", 77, Rarity.UNCOMMON, mage.cards.n.NoxiousGhoul.class));
@@ -188,6 +190,7 @@ public class Legions extends ExpansionSet {
cards.add(new SetCardInfo("Ward Sliver", 25, Rarity.UNCOMMON, mage.cards.w.WardSliver.class));
cards.add(new SetCardInfo("Warped Researcher", 56, Rarity.UNCOMMON, mage.cards.w.WarpedResearcher.class));
cards.add(new SetCardInfo("Weaver of Lies", 57, Rarity.RARE, mage.cards.w.WeaverOfLies.class));
+ cards.add(new SetCardInfo("Whipgrass Entangler", 26, Rarity.COMMON, mage.cards.w.WhipgrassEntangler.class));
cards.add(new SetCardInfo("White Knight", 27, Rarity.UNCOMMON, mage.cards.w.WhiteKnight.class));
cards.add(new SetCardInfo("Willbender", 58, Rarity.UNCOMMON, mage.cards.w.Willbender.class));
cards.add(new SetCardInfo("Windborn Muse", 28, Rarity.RARE, mage.cards.w.WindbornMuse.class));
diff --git a/Mage.Sets/src/mage/sets/LimitedEditionAlpha.java b/Mage.Sets/src/mage/sets/LimitedEditionAlpha.java
index f5c1f066061..8b7de5a757d 100644
--- a/Mage.Sets/src/mage/sets/LimitedEditionAlpha.java
+++ b/Mage.Sets/src/mage/sets/LimitedEditionAlpha.java
@@ -44,6 +44,7 @@ public class LimitedEditionAlpha extends ExpansionSet {
cards.add(new SetCardInfo("Black Lotus", 232, Rarity.RARE, mage.cards.b.BlackLotus.class));
cards.add(new SetCardInfo("Black Vise", 233, Rarity.UNCOMMON, mage.cards.b.BlackVise.class));
cards.add(new SetCardInfo("Black Ward", 189, Rarity.UNCOMMON, mage.cards.b.BlackWard.class));
+ cards.add(new SetCardInfo("Blaze of Glory", 190, Rarity.RARE, mage.cards.b.BlazeOfGlory.class));
cards.add(new SetCardInfo("Blessing", 191, Rarity.RARE, mage.cards.b.Blessing.class));
cards.add(new SetCardInfo("Blue Elemental Blast", 50, Rarity.COMMON, mage.cards.b.BlueElementalBlast.class));
cards.add(new SetCardInfo("Blue Ward", 192, Rarity.UNCOMMON, mage.cards.b.BlueWard.class));
@@ -209,6 +210,7 @@ public class LimitedEditionAlpha extends ExpansionSet {
cards.add(new SetCardInfo("Plains", 285, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plains", 286, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plateau", 287, Rarity.RARE, mage.cards.p.Plateau.class));
+ cards.add(new SetCardInfo("Power Leak", 72, Rarity.COMMON, mage.cards.p.PowerLeak.class));
cards.add(new SetCardInfo("Power Sink", 73, Rarity.COMMON, mage.cards.p.PowerSink.class));
cards.add(new SetCardInfo("Power Surge", 168, Rarity.RARE, mage.cards.p.PowerSurge.class));
cards.add(new SetCardInfo("Prodigal Sorcerer", 74, Rarity.COMMON, mage.cards.p.ProdigalSorcerer.class));
diff --git a/Mage.Sets/src/mage/sets/LimitedEditionBeta.java b/Mage.Sets/src/mage/sets/LimitedEditionBeta.java
index ff30f36357b..9b642609e4c 100644
--- a/Mage.Sets/src/mage/sets/LimitedEditionBeta.java
+++ b/Mage.Sets/src/mage/sets/LimitedEditionBeta.java
@@ -44,6 +44,7 @@ public class LimitedEditionBeta extends ExpansionSet {
cards.add(new SetCardInfo("Black Lotus", 233, Rarity.RARE, mage.cards.b.BlackLotus.class));
cards.add(new SetCardInfo("Black Vise", 234, Rarity.UNCOMMON, mage.cards.b.BlackVise.class));
cards.add(new SetCardInfo("Black Ward", 5, Rarity.UNCOMMON, mage.cards.b.BlackWard.class));
+ cards.add(new SetCardInfo("Blaze of Glory", 6, Rarity.RARE, mage.cards.b.BlazeOfGlory.class));
cards.add(new SetCardInfo("Blessing", 7, Rarity.RARE, mage.cards.b.Blessing.class));
cards.add(new SetCardInfo("Blue Elemental Blast", 50, Rarity.COMMON, mage.cards.b.BlueElementalBlast.class));
cards.add(new SetCardInfo("Blue Ward", 8, Rarity.UNCOMMON, mage.cards.b.BlueWard.class));
@@ -214,6 +215,7 @@ public class LimitedEditionBeta extends ExpansionSet {
cards.add(new SetCardInfo("Plains", 289, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plains", 290, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plateau", 280, Rarity.RARE, mage.cards.p.Plateau.class));
+ cards.add(new SetCardInfo("Power Leak", 72, Rarity.COMMON, mage.cards.p.PowerLeak.class));
cards.add(new SetCardInfo("Power Sink", 73, Rarity.COMMON, mage.cards.p.PowerSink.class));
cards.add(new SetCardInfo("Power Surge", 168, Rarity.RARE, mage.cards.p.PowerSurge.class));
cards.add(new SetCardInfo("Prodigal Sorcerer", 74, Rarity.COMMON, mage.cards.p.ProdigalSorcerer.class));
diff --git a/Mage.Sets/src/mage/sets/MasterpieceSeriesAmonkhet.java b/Mage.Sets/src/mage/sets/MasterpieceSeriesAmonkhet.java
index 291c6782fef..d526453921f 100644
--- a/Mage.Sets/src/mage/sets/MasterpieceSeriesAmonkhet.java
+++ b/Mage.Sets/src/mage/sets/MasterpieceSeriesAmonkhet.java
@@ -27,9 +27,7 @@
*/
package mage.sets;
-import mage.cards.CardGraphicInfo;
import mage.cards.ExpansionSet;
-import mage.cards.FrameStyle;
import mage.constants.Rarity;
import mage.constants.SetType;
@@ -50,7 +48,6 @@ public class MasterpieceSeriesAmonkhet extends ExpansionSet {
this.blockName = "Masterpiece Series";
this.hasBoosters = false;
this.hasBasicLands = false;
- CardGraphicInfo cardGraphicInfo = new CardGraphicInfo(FrameStyle.KLD_INVENTION, false);
cards.add(new SetCardInfo("Aggravated Assault", 25, Rarity.SPECIAL, mage.cards.a.AggravatedAssault.class));
cards.add(new SetCardInfo("Armageddon", 31, Rarity.SPECIAL, mage.cards.a.Armageddon.class));
diff --git a/Mage.Sets/src/mage/sets/Masters25.java b/Mage.Sets/src/mage/sets/Masters25.java
index cb35f2c36ff..83b55f60414 100644
--- a/Mage.Sets/src/mage/sets/Masters25.java
+++ b/Mage.Sets/src/mage/sets/Masters25.java
@@ -29,9 +29,10 @@ package mage.sets;
/**
*
- * @author fireshoes
+ * @author JayDi85
*/
import mage.cards.ExpansionSet;
+import mage.constants.Rarity;
import mage.constants.SetType;
public class Masters25 extends ExpansionSet {
@@ -43,7 +44,7 @@ public class Masters25 extends ExpansionSet {
}
private Masters25() {
- super("Masters 25", "M25", ExpansionSet.buildDate(2018, 3, 16), SetType.SUPPLEMENTAL);
+ super("Masters 25", "A25", ExpansionSet.buildDate(2018, 3, 16), SetType.SUPPLEMENTAL);
this.blockName = "Reprint";
this.hasBasicLands = false;
this.hasBoosters = true;
@@ -52,5 +53,255 @@ public class Masters25 extends ExpansionSet {
this.numBoosterUncommon = 3;
this.numBoosterRare = 1;
this.ratioBoosterMythic = 8;
+
+ cards.add(new SetCardInfo("Act of Heroism", 1, Rarity.COMMON, mage.cards.a.ActOfHeroism.class));
+ cards.add(new SetCardInfo("Akroma, Angel of Wrath", 2, Rarity.MYTHIC, mage.cards.a.AkromaAngelOfWrath.class));
+ cards.add(new SetCardInfo("Akroma's Vengeance", 3, Rarity.RARE, mage.cards.a.AkromasVengeance.class));
+ cards.add(new SetCardInfo("Angelic Page", 4, Rarity.UNCOMMON, mage.cards.a.AngelicPage.class));
+ cards.add(new SetCardInfo("Armageddon", 5, Rarity.MYTHIC, mage.cards.a.Armageddon.class));
+ cards.add(new SetCardInfo("Auramancer", 6, Rarity.COMMON, mage.cards.a.Auramancer.class));
+ cards.add(new SetCardInfo("Cloudshift", 7, Rarity.COMMON, mage.cards.c.Cloudshift.class));
+ cards.add(new SetCardInfo("Congregate", 8, Rarity.UNCOMMON, mage.cards.c.Congregate.class));
+ cards.add(new SetCardInfo("Darien, King of Kjeldor", 9, Rarity.RARE, mage.cards.d.DarienKingOfKjeldor.class));
+ cards.add(new SetCardInfo("Dauntless Cathar", 10, Rarity.COMMON, mage.cards.d.DauntlessCathar.class));
+ cards.add(new SetCardInfo("Decree of Justice", 11, Rarity.RARE, mage.cards.d.DecreeOfJustice.class));
+ cards.add(new SetCardInfo("Disenchant", 12, Rarity.COMMON, mage.cards.d.Disenchant.class));
+ cards.add(new SetCardInfo("Fencing Ace", 13, Rarity.COMMON, mage.cards.f.FencingAce.class));
+ cards.add(new SetCardInfo("Fiend Hunter", 14, Rarity.UNCOMMON, mage.cards.f.FiendHunter.class));
+ cards.add(new SetCardInfo("Geist of the Moors", 15, Rarity.COMMON, mage.cards.g.GeistOfTheMoors.class));
+ cards.add(new SetCardInfo("Gods Willing", 16, Rarity.COMMON, mage.cards.g.GodsWilling.class));
+ cards.add(new SetCardInfo("Griffin Protector", 17, Rarity.COMMON, mage.cards.g.GriffinProtector.class));
+ cards.add(new SetCardInfo("Karona's Zealot", 18, Rarity.UNCOMMON, mage.cards.k.KaronasZealot.class));
+ cards.add(new SetCardInfo("Knight of the Skyward Eye", 19, Rarity.COMMON, mage.cards.k.KnightOfTheSkywardEye.class));
+ cards.add(new SetCardInfo("Kongming, 'Sleeping Dragon'", 20, Rarity.UNCOMMON, mage.cards.k.KongmingSleepingDragon.class));
+ cards.add(new SetCardInfo("Kor Firewalker", 21, Rarity.UNCOMMON, mage.cards.k.KorFirewalker.class));
+ cards.add(new SetCardInfo("Loyal Sentry", 22, Rarity.COMMON, mage.cards.l.LoyalSentry.class));
+ cards.add(new SetCardInfo("Luminarch Ascension", 23, Rarity.RARE, mage.cards.l.LuminarchAscension.class));
+ cards.add(new SetCardInfo("Lunarch Mantle", 24, Rarity.COMMON, mage.cards.l.LunarchMantle.class));
+ cards.add(new SetCardInfo("Noble Templar", 25, Rarity.COMMON, mage.cards.n.NobleTemplar.class));
+ cards.add(new SetCardInfo("Nyx-Fleece Ram", 26, Rarity.UNCOMMON, mage.cards.n.NyxFleeceRam.class));
+ cards.add(new SetCardInfo("Ordeal of Heliod", 27, Rarity.UNCOMMON, mage.cards.o.OrdealOfHeliod.class));
+ cards.add(new SetCardInfo("Pacifism", 28, Rarity.COMMON, mage.cards.p.Pacifism.class));
+ cards.add(new SetCardInfo("Path of Peace", 29, Rarity.COMMON, mage.cards.p.PathOfPeace.class));
+ cards.add(new SetCardInfo("Promise of Bunrei", 30, Rarity.UNCOMMON, mage.cards.p.PromiseOfBunrei.class));
+ cards.add(new SetCardInfo("Renewed Faith", 31, Rarity.COMMON, mage.cards.r.RenewedFaith.class));
+ cards.add(new SetCardInfo("Rest in Peace", 32, Rarity.RARE, mage.cards.r.RestInPeace.class));
+ cards.add(new SetCardInfo("Savannah Lions", 33, Rarity.COMMON, mage.cards.s.SavannahLions.class));
+ cards.add(new SetCardInfo("Squadron Hawk", 34, Rarity.COMMON, mage.cards.s.SquadronHawk.class));
+ cards.add(new SetCardInfo("Swords to Plowshares", 35, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class));
+ cards.add(new SetCardInfo("Thalia, Guardian of Thraben", 36, Rarity.RARE, mage.cards.t.ThaliaGuardianOfThraben.class));
+ cards.add(new SetCardInfo("Urbis Protector", 37, Rarity.UNCOMMON, mage.cards.u.UrbisProtector.class));
+ cards.add(new SetCardInfo("Valor in Akros", 38, Rarity.UNCOMMON, mage.cards.v.ValorInAkros.class));
+ cards.add(new SetCardInfo("Whitemane Lion", 39, Rarity.COMMON, mage.cards.w.WhitemaneLion.class));
+ cards.add(new SetCardInfo("Accumulated Knowledge", 40, Rarity.COMMON, mage.cards.a.AccumulatedKnowledge.class));
+ cards.add(new SetCardInfo("Arcane Denial", 41, Rarity.COMMON, mage.cards.a.ArcaneDenial.class));
+ cards.add(new SetCardInfo("Bident of Thassa", 42, Rarity.RARE, mage.cards.b.BidentOfThassa.class));
+ cards.add(new SetCardInfo("Blue Elemental Blast", 43, Rarity.UNCOMMON, mage.cards.b.BlueElementalBlast.class));
+ cards.add(new SetCardInfo("Blue Sun's Zenith", 44, Rarity.RARE, mage.cards.b.BlueSunsZenith.class));
+ cards.add(new SetCardInfo("Borrowing 100,000 Arrows", 45, Rarity.COMMON, mage.cards.b.Borrowing100000Arrows.class));
+ cards.add(new SetCardInfo("Brainstorm", 46, Rarity.COMMON, mage.cards.b.Brainstorm.class));
+ cards.add(new SetCardInfo("Brine Elemental", 47, Rarity.UNCOMMON, mage.cards.b.BrineElemental.class));
+ cards.add(new SetCardInfo("Choking Tethers", 48, Rarity.COMMON, mage.cards.c.ChokingTethers.class));
+ cards.add(new SetCardInfo("Coralhelm Guide", 49, Rarity.COMMON, mage.cards.c.CoralhelmGuide.class));
+ cards.add(new SetCardInfo("Counterspell", 50, Rarity.COMMON, mage.cards.c.Counterspell.class));
+ cards.add(new SetCardInfo("Court Hussar", 51, Rarity.COMMON, mage.cards.c.CourtHussar.class));
+ cards.add(new SetCardInfo("Curiosity", 52, Rarity.UNCOMMON, mage.cards.c.Curiosity.class));
+ cards.add(new SetCardInfo("Cursecatcher", 53, Rarity.UNCOMMON, mage.cards.c.Cursecatcher.class));
+ cards.add(new SetCardInfo("Dragon's Eye Savants", 54, Rarity.COMMON, mage.cards.d.DragonsEyeSavants.class));
+ cards.add(new SetCardInfo("Exclude", 55, Rarity.UNCOMMON, mage.cards.e.Exclude.class));
+ cards.add(new SetCardInfo("Fathom Seer", 56, Rarity.COMMON, mage.cards.f.FathomSeer.class));
+ cards.add(new SetCardInfo("Flash", 57, Rarity.RARE, mage.cards.f.Flash.class));
+ cards.add(new SetCardInfo("Freed from the Real", 58, Rarity.UNCOMMON, mage.cards.f.FreedFromTheReal.class));
+ cards.add(new SetCardInfo("Genju of the Falls", 59, Rarity.UNCOMMON, mage.cards.g.GenjuOfTheFalls.class));
+ cards.add(new SetCardInfo("Ghost Ship", 60, Rarity.COMMON, mage.cards.g.GhostShip.class));
+ cards.add(new SetCardInfo("Horseshoe Crab", 61, Rarity.COMMON, mage.cards.h.HorseshoeCrab.class));
+ cards.add(new SetCardInfo("Jace, the Mind Sculptor", 62, Rarity.MYTHIC, mage.cards.j.JaceTheMindSculptor.class));
+ cards.add(new SetCardInfo("Jalira, Master Polymorphist", 63, Rarity.UNCOMMON, mage.cards.j.JaliraMasterPolymorphist.class));
+ cards.add(new SetCardInfo("Man-o'-War", 64, Rarity.COMMON, mage.cards.m.ManOWar.class));
+ cards.add(new SetCardInfo("Merfolk Looter", 65, Rarity.UNCOMMON, mage.cards.m.MerfolkLooter.class));
+ cards.add(new SetCardInfo("Murder of Crows", 66, Rarity.UNCOMMON, mage.cards.m.MurderOfCrows.class));
+ cards.add(new SetCardInfo("Mystic of the Hidden Way", 67, Rarity.COMMON, mage.cards.m.MysticOfTheHiddenWay.class));
+ cards.add(new SetCardInfo("Pact of Negation", 68, Rarity.RARE, mage.cards.p.PactOfNegation.class));
+ cards.add(new SetCardInfo("Phantasmal Bear", 69, Rarity.COMMON, mage.cards.p.PhantasmalBear.class));
+ cards.add(new SetCardInfo("Reef Worm", 70, Rarity.RARE, mage.cards.r.ReefWorm.class));
+ cards.add(new SetCardInfo("Retraction Helix", 71, Rarity.COMMON, mage.cards.r.RetractionHelix.class));
+ cards.add(new SetCardInfo("Shoreline Ranger", 72, Rarity.COMMON, mage.cards.s.ShorelineRanger.class));
+ cards.add(new SetCardInfo("Sift", 73, Rarity.COMMON, mage.cards.s.Sift.class));
+ cards.add(new SetCardInfo("Totally Lost", 74, Rarity.COMMON, mage.cards.t.TotallyLost.class));
+ cards.add(new SetCardInfo("Twisted Image", 75, Rarity.UNCOMMON, mage.cards.t.TwistedImage.class));
+ cards.add(new SetCardInfo("Vendilion Clique", 76, Rarity.MYTHIC, mage.cards.v.VendilionClique.class));
+ cards.add(new SetCardInfo("Vesuvan Shapeshifter", 77, Rarity.RARE, mage.cards.v.VesuvanShapeshifter.class));
+ cards.add(new SetCardInfo("Willbender", 78, Rarity.UNCOMMON, mage.cards.w.Willbender.class));
+ cards.add(new SetCardInfo("Ancient Craving", 79, Rarity.UNCOMMON, mage.cards.a.AncientCraving.class));
+ cards.add(new SetCardInfo("Bloodhunter Bat", 80, Rarity.COMMON, mage.cards.b.BloodhunterBat.class));
+ cards.add(new SetCardInfo("Caustic Tar", 81, Rarity.UNCOMMON, mage.cards.c.CausticTar.class));
+ cards.add(new SetCardInfo("Dark Ritual", 82, Rarity.COMMON, mage.cards.d.DarkRitual.class));
+ cards.add(new SetCardInfo("Deadly Designs", 83, Rarity.UNCOMMON, mage.cards.d.DeadlyDesigns.class));
+ cards.add(new SetCardInfo("Death's-Head Buzzard", 84, Rarity.COMMON, mage.cards.d.DeathsHeadBuzzard.class));
+ cards.add(new SetCardInfo("Diabolic Edict", 85, Rarity.COMMON, mage.cards.d.DiabolicEdict.class));
+ cards.add(new SetCardInfo("Dirge of Dread", 86, Rarity.COMMON, mage.cards.d.DirgeOfDread.class));
+ cards.add(new SetCardInfo("Disfigure", 87, Rarity.COMMON, mage.cards.d.Disfigure.class));
+ cards.add(new SetCardInfo("Doomsday", 88, Rarity.MYTHIC, mage.cards.d.Doomsday.class));
+ cards.add(new SetCardInfo("Dusk Legion Zealot", 89, Rarity.COMMON, mage.cards.d.DuskLegionZealot.class));
+ cards.add(new SetCardInfo("Erg Raiders", 90, Rarity.COMMON, mage.cards.e.ErgRaiders.class));
+ cards.add(new SetCardInfo("Fallen Angel", 91, Rarity.UNCOMMON, mage.cards.f.FallenAngel.class));
+ cards.add(new SetCardInfo("Hell's Caretaker", 92, Rarity.RARE, mage.cards.h.HellsCaretaker.class));
+ cards.add(new SetCardInfo("Horror of the Broken Lands", 93, Rarity.COMMON, mage.cards.h.HorrorOfTheBrokenLands.class));
+ cards.add(new SetCardInfo("Ihsan's Shade", 94, Rarity.UNCOMMON, mage.cards.i.IhsansShade.class));
+ cards.add(new SetCardInfo("Laquatus's Champion", 95, Rarity.RARE, mage.cards.l.LaquatussChampion.class));
+ cards.add(new SetCardInfo("Living Death", 96, Rarity.RARE, mage.cards.l.LivingDeath.class));
+ cards.add(new SetCardInfo("Mesmeric Fiend", 97, Rarity.UNCOMMON, mage.cards.m.MesmericFiend.class));
+ cards.add(new SetCardInfo("Murder", 98, Rarity.COMMON, mage.cards.m.Murder.class));
+ cards.add(new SetCardInfo("Nezumi Cutthroat", 99, Rarity.COMMON, mage.cards.n.NezumiCutthroat.class));
+ cards.add(new SetCardInfo("Phyrexian Ghoul", 100, Rarity.COMMON, mage.cards.p.PhyrexianGhoul.class));
+ cards.add(new SetCardInfo("Phyrexian Obliterator", 101, Rarity.MYTHIC, mage.cards.p.PhyrexianObliterator.class));
+ cards.add(new SetCardInfo("Plague Wind", 102, Rarity.RARE, mage.cards.p.PlagueWind.class));
+ cards.add(new SetCardInfo("Ratcatcher", 103, Rarity.RARE, mage.cards.r.Ratcatcher.class));
+ cards.add(new SetCardInfo("Ravenous Chupacabra", 104, Rarity.UNCOMMON, mage.cards.r.RavenousChupacabra.class));
+ cards.add(new SetCardInfo("Relentless Rats", 105, Rarity.COMMON, mage.cards.r.RelentlessRats.class));
+ cards.add(new SetCardInfo("Returned Phalanx", 106, Rarity.COMMON, mage.cards.r.ReturnedPhalanx.class));
+ cards.add(new SetCardInfo("Ruthless Ripper", 107, Rarity.COMMON, mage.cards.r.RuthlessRipper.class));
+ cards.add(new SetCardInfo("Street Wraith", 108, Rarity.UNCOMMON, mage.cards.s.StreetWraith.class));
+ cards.add(new SetCardInfo("Supernatural Stamina", 109, Rarity.COMMON, mage.cards.s.SupernaturalStamina.class));
+ cards.add(new SetCardInfo("Triskaidekaphobia", 110, Rarity.RARE, mage.cards.t.Triskaidekaphobia.class));
+ cards.add(new SetCardInfo("Twisted Abomination", 111, Rarity.COMMON, mage.cards.t.TwistedAbomination.class));
+ cards.add(new SetCardInfo("Undead Gladiator", 112, Rarity.UNCOMMON, mage.cards.u.UndeadGladiator.class));
+ cards.add(new SetCardInfo("Unearth", 113, Rarity.COMMON, mage.cards.u.Unearth.class));
+ cards.add(new SetCardInfo("Vampire Lacerator", 114, Rarity.COMMON, mage.cards.v.VampireLacerator.class));
+ cards.add(new SetCardInfo("Will-o'-the-Wisp", 115, Rarity.UNCOMMON, mage.cards.w.WillOTheWisp.class));
+ cards.add(new SetCardInfo("Zombify", 116, Rarity.UNCOMMON, mage.cards.z.Zombify.class));
+ cards.add(new SetCardInfo("Zulaport Cutthroat", 117, Rarity.UNCOMMON, mage.cards.z.ZulaportCutthroat.class));
+ cards.add(new SetCardInfo("Act of Treason", 118, Rarity.COMMON, mage.cards.a.ActOfTreason.class));
+ cards.add(new SetCardInfo("Akroma, Angel of Fury", 119, Rarity.MYTHIC, mage.cards.a.AkromaAngelOfFury.class));
+ cards.add(new SetCardInfo("Balduvian Horde", 120, Rarity.COMMON, mage.cards.b.BalduvianHorde.class));
+ cards.add(new SetCardInfo("Ball Lightning", 121, Rarity.RARE, mage.cards.b.BallLightning.class));
+ cards.add(new SetCardInfo("Blood Moon", 122, Rarity.RARE, mage.cards.b.BloodMoon.class));
+ cards.add(new SetCardInfo("Browbeat", 123, Rarity.UNCOMMON, mage.cards.b.Browbeat.class));
+ cards.add(new SetCardInfo("Chandra's Outrage", 124, Rarity.COMMON, mage.cards.c.ChandrasOutrage.class));
+ cards.add(new SetCardInfo("Chartooth Cougar", 125, Rarity.COMMON, mage.cards.c.ChartoothCougar.class));
+ cards.add(new SetCardInfo("Cinder Storm", 126, Rarity.COMMON, mage.cards.c.CinderStorm.class));
+ cards.add(new SetCardInfo("Crimson Mage", 127, Rarity.COMMON, mage.cards.c.CrimsonMage.class));
+ cards.add(new SetCardInfo("Eidolon of the Great Revel", 128, Rarity.RARE, mage.cards.e.EidolonOfTheGreatRevel.class));
+ cards.add(new SetCardInfo("Enthralling Victor", 129, Rarity.UNCOMMON, mage.cards.e.EnthrallingVictor.class));
+ cards.add(new SetCardInfo("Fortune Thief", 130, Rarity.RARE, mage.cards.f.FortuneThief.class));
+ cards.add(new SetCardInfo("Frenzied Goblin", 131, Rarity.COMMON, mage.cards.f.FrenziedGoblin.class));
+ cards.add(new SetCardInfo("Genju of the Spires", 132, Rarity.UNCOMMON, mage.cards.g.GenjuOfTheSpires.class));
+ cards.add(new SetCardInfo("Goblin War Drums", 133, Rarity.UNCOMMON, mage.cards.g.GoblinWarDrums.class));
+ cards.add(new SetCardInfo("Hordeling Outburst", 134, Rarity.COMMON, mage.cards.h.HordelingOutburst.class));
+ cards.add(new SetCardInfo("Humble Defector", 135, Rarity.UNCOMMON, mage.cards.h.HumbleDefector.class));
+ cards.add(new SetCardInfo("Imperial Recruiter", 136, Rarity.MYTHIC, mage.cards.i.ImperialRecruiter.class));
+ cards.add(new SetCardInfo("Ire Shaman", 137, Rarity.UNCOMMON, mage.cards.i.IreShaman.class));
+ cards.add(new SetCardInfo("Izzet Chemister", 138, Rarity.RARE, mage.cards.i.IzzetChemister.class));
+ cards.add(new SetCardInfo("Jackal Pup", 139, Rarity.COMMON, mage.cards.j.JackalPup.class));
+ cards.add(new SetCardInfo("Kindle", 140, Rarity.COMMON, mage.cards.k.Kindle.class));
+ cards.add(new SetCardInfo("Lightning Bolt", 141, Rarity.UNCOMMON, mage.cards.l.LightningBolt.class));
+ cards.add(new SetCardInfo("Magus of the Wheel", 142, Rarity.RARE, mage.cards.m.MagusOfTheWheel.class));
+ cards.add(new SetCardInfo("Mogg Flunkies", 143, Rarity.COMMON, mage.cards.m.MoggFlunkies.class));
+ cards.add(new SetCardInfo("Pillage", 144, Rarity.COMMON, mage.cards.p.Pillage.class));
+ cards.add(new SetCardInfo("Pyre Hound", 145, Rarity.COMMON, mage.cards.p.PyreHound.class));
+ cards.add(new SetCardInfo("Pyroclasm", 146, Rarity.UNCOMMON, mage.cards.p.Pyroclasm.class));
+ cards.add(new SetCardInfo("Red Elemental Blast", 147, Rarity.UNCOMMON, mage.cards.r.RedElementalBlast.class));
+ cards.add(new SetCardInfo("Simian Spirit Guide", 148, Rarity.UNCOMMON, mage.cards.s.SimianSpiritGuide.class));
+ cards.add(new SetCardInfo("Skeletonize", 149, Rarity.COMMON, mage.cards.s.Skeletonize.class));
+ cards.add(new SetCardInfo("Skirk Commando", 150, Rarity.COMMON, mage.cards.s.SkirkCommando.class));
+ cards.add(new SetCardInfo("Soulbright Flamekin", 151, Rarity.COMMON, mage.cards.s.SoulbrightFlamekin.class));
+ cards.add(new SetCardInfo("Spikeshot Goblin", 152, Rarity.UNCOMMON, mage.cards.s.SpikeshotGoblin.class));
+ cards.add(new SetCardInfo("Thresher Lizard", 153, Rarity.COMMON, mage.cards.t.ThresherLizard.class));
+ cards.add(new SetCardInfo("Trumpet Blast", 154, Rarity.COMMON, mage.cards.t.TrumpetBlast.class));
+ cards.add(new SetCardInfo("Uncaged Fury", 155, Rarity.COMMON, mage.cards.u.UncagedFury.class));
+ cards.add(new SetCardInfo("Zada, Hedron Grinder", 156, Rarity.UNCOMMON, mage.cards.z.ZadaHedronGrinder.class));
+ cards.add(new SetCardInfo("Ainok Survivalist", 157, Rarity.COMMON, mage.cards.a.AinokSurvivalist.class));
+ cards.add(new SetCardInfo("Ambassador Oak", 158, Rarity.COMMON, mage.cards.a.AmbassadorOak.class));
+ cards.add(new SetCardInfo("Ancient Stirrings", 159, Rarity.UNCOMMON, mage.cards.a.AncientStirrings.class));
+ cards.add(new SetCardInfo("Arbor Elf", 160, Rarity.COMMON, mage.cards.a.ArborElf.class));
+ cards.add(new SetCardInfo("Azusa, Lost but Seeking", 161, Rarity.RARE, mage.cards.a.AzusaLostButSeeking.class));
+ cards.add(new SetCardInfo("Broodhatch Nantuko", 162, Rarity.UNCOMMON, mage.cards.b.BroodhatchNantuko.class));
+ cards.add(new SetCardInfo("Colossal Dreadmaw", 163, Rarity.COMMON, mage.cards.c.ColossalDreadmaw.class));
+ cards.add(new SetCardInfo("Courser of Kruphix", 164, Rarity.RARE, mage.cards.c.CourserOfKruphix.class));
+ cards.add(new SetCardInfo("Cultivate", 165, Rarity.COMMON, mage.cards.c.Cultivate.class));
+ cards.add(new SetCardInfo("Echoing Courage", 166, Rarity.COMMON, mage.cards.e.EchoingCourage.class));
+ cards.add(new SetCardInfo("Elvish Aberration", 167, Rarity.COMMON, mage.cards.e.ElvishAberration.class));
+ cards.add(new SetCardInfo("Elvish Piper", 168, Rarity.RARE, mage.cards.e.ElvishPiper.class));
+ cards.add(new SetCardInfo("Ember Weaver", 169, Rarity.COMMON, mage.cards.e.EmberWeaver.class));
+ cards.add(new SetCardInfo("Epic Confrontation", 170, Rarity.COMMON, mage.cards.e.EpicConfrontation.class));
+ cards.add(new SetCardInfo("Fierce Empath", 171, Rarity.UNCOMMON, mage.cards.f.FierceEmpath.class));
+ cards.add(new SetCardInfo("Giant Growth", 172, Rarity.COMMON, mage.cards.g.GiantGrowth.class));
+ cards.add(new SetCardInfo("Invigorate", 173, Rarity.UNCOMMON, mage.cards.i.Invigorate.class));
+ cards.add(new SetCardInfo("Iwamori of the Open Fist", 174, Rarity.UNCOMMON, mage.cards.i.IwamoriOfTheOpenFist.class));
+ cards.add(new SetCardInfo("Kavu Climber", 175, Rarity.COMMON, mage.cards.k.KavuClimber.class));
+ cards.add(new SetCardInfo("Kavu Predator", 176, Rarity.UNCOMMON, mage.cards.k.KavuPredator.class));
+ cards.add(new SetCardInfo("Krosan Colossus", 177, Rarity.UNCOMMON, mage.cards.k.KrosanColossus.class));
+ cards.add(new SetCardInfo("Krosan Tusker", 178, Rarity.UNCOMMON, mage.cards.k.KrosanTusker.class));
+ cards.add(new SetCardInfo("Living Wish", 179, Rarity.RARE, mage.cards.l.LivingWish.class));
+ cards.add(new SetCardInfo("Lull", 180, Rarity.COMMON, mage.cards.l.Lull.class));
+ cards.add(new SetCardInfo("Master of the Wild Hunt", 181, Rarity.MYTHIC, mage.cards.m.MasterOfTheWildHunt.class));
+ cards.add(new SetCardInfo("Nettle Sentinel", 182, Rarity.COMMON, mage.cards.n.NettleSentinel.class));
+ cards.add(new SetCardInfo("Plummet", 183, Rarity.COMMON, mage.cards.p.Plummet.class));
+ cards.add(new SetCardInfo("Presence of Gond", 184, Rarity.COMMON, mage.cards.p.PresenceOfGond.class));
+ cards.add(new SetCardInfo("Protean Hulk", 185, Rarity.RARE, mage.cards.p.ProteanHulk.class));
+ cards.add(new SetCardInfo("Rancor", 186, Rarity.UNCOMMON, mage.cards.r.Rancor.class));
+ cards.add(new SetCardInfo("Regrowth", 187, Rarity.UNCOMMON, mage.cards.r.Regrowth.class));
+ cards.add(new SetCardInfo("Stampede Driver", 188, Rarity.UNCOMMON, mage.cards.s.StampedeDriver.class));
+ cards.add(new SetCardInfo("Summoner's Pact", 189, Rarity.RARE, mage.cards.s.SummonersPact.class));
+ cards.add(new SetCardInfo("Timberpack Wolf", 190, Rarity.COMMON, mage.cards.t.TimberpackWolf.class));
+ cards.add(new SetCardInfo("Tree of Redemption", 191, Rarity.MYTHIC, mage.cards.t.TreeOfRedemption.class));
+ cards.add(new SetCardInfo("Utopia Sprawl", 192, Rarity.UNCOMMON, mage.cards.u.UtopiaSprawl.class));
+ cards.add(new SetCardInfo("Vessel of Nascency", 193, Rarity.COMMON, mage.cards.v.VesselOfNascency.class));
+ cards.add(new SetCardInfo("Wildheart Invoker", 194, Rarity.COMMON, mage.cards.w.WildheartInvoker.class));
+ cards.add(new SetCardInfo("Woolly Loxodon", 195, Rarity.COMMON, mage.cards.w.WoollyLoxodon.class));
+ cards.add(new SetCardInfo("Animar, Soul of Elements", 196, Rarity.MYTHIC, mage.cards.a.AnimarSoulOfElements.class));
+ cards.add(new SetCardInfo("Baloth Null", 197, Rarity.UNCOMMON, mage.cards.b.BalothNull.class));
+ cards.add(new SetCardInfo("Blightning", 198, Rarity.UNCOMMON, mage.cards.b.Blightning.class));
+ cards.add(new SetCardInfo("Boros Charm", 199, Rarity.UNCOMMON, mage.cards.b.BorosCharm.class));
+ cards.add(new SetCardInfo("Brion Stoutarm", 200, Rarity.RARE, mage.cards.b.BrionStoutarm.class));
+ cards.add(new SetCardInfo("Cloudblazer", 201, Rarity.UNCOMMON, mage.cards.c.Cloudblazer.class));
+ cards.add(new SetCardInfo("Conflux", 202, Rarity.RARE, mage.cards.c.Conflux.class));
+ cards.add(new SetCardInfo("Eladamri's Call", 203, Rarity.RARE, mage.cards.e.EladamrisCall.class));
+ cards.add(new SetCardInfo("Gisela, Blade of Goldnight", 204, Rarity.MYTHIC, mage.cards.g.GiselaBladeOfGoldnight.class));
+ cards.add(new SetCardInfo("Grenzo, Dungeon Warden", 205, Rarity.RARE, mage.cards.g.GrenzoDungeonWarden.class));
+ cards.add(new SetCardInfo("Hanna, Ship's Navigator", 206, Rarity.RARE, mage.cards.h.HannaShipsNavigator.class));
+ cards.add(new SetCardInfo("Lorescale Coatl", 207, Rarity.UNCOMMON, mage.cards.l.LorescaleCoatl.class));
+ cards.add(new SetCardInfo("Mystic Snake", 208, Rarity.RARE, mage.cards.m.MysticSnake.class));
+ cards.add(new SetCardInfo("Nicol Bolas", 209, Rarity.RARE, mage.cards.n.NicolBolas.class));
+ cards.add(new SetCardInfo("Niv-Mizzet, the Firemind", 210, Rarity.RARE, mage.cards.n.NivMizzetTheFiremind.class));
+ cards.add(new SetCardInfo("Notion Thief", 211, Rarity.RARE, mage.cards.n.NotionThief.class));
+ cards.add(new SetCardInfo("Pernicious Deed", 212, Rarity.RARE, mage.cards.p.PerniciousDeed.class));
+ cards.add(new SetCardInfo("Pillory of the Sleepless", 213, Rarity.UNCOMMON, mage.cards.p.PilloryOfTheSleepless.class));
+ cards.add(new SetCardInfo("Prossh, Skyraider of Kher", 214, Rarity.MYTHIC, mage.cards.p.ProsshSkyraiderOfKher.class));
+ cards.add(new SetCardInfo("Quicksilver Dagger", 215, Rarity.UNCOMMON, mage.cards.q.QuicksilverDagger.class));
+ cards.add(new SetCardInfo("Ruric Thar, the Unbowed", 216, Rarity.RARE, mage.cards.r.RuricTharTheUnbowed.class));
+ cards.add(new SetCardInfo("Shadowmage Infiltrator", 217, Rarity.UNCOMMON, mage.cards.s.ShadowmageInfiltrator.class));
+ cards.add(new SetCardInfo("Stangg", 218, Rarity.UNCOMMON, mage.cards.s.Stangg.class));
+ cards.add(new SetCardInfo("Vindicate", 219, Rarity.RARE, mage.cards.v.Vindicate.class));
+ cards.add(new SetCardInfo("Watchwolf", 220, Rarity.UNCOMMON, mage.cards.w.Watchwolf.class));
+ cards.add(new SetCardInfo("Assembly-Worker", 221, Rarity.COMMON, mage.cards.a.AssemblyWorker.class));
+ cards.add(new SetCardInfo("Chalice of the Void", 222, Rarity.MYTHIC, mage.cards.c.ChaliceOfTheVoid.class));
+ cards.add(new SetCardInfo("Coalition Relic", 223, Rarity.RARE, mage.cards.c.CoalitionRelic.class));
+ cards.add(new SetCardInfo("Ensnaring Bridge", 224, Rarity.MYTHIC, mage.cards.e.EnsnaringBridge.class));
+ cards.add(new SetCardInfo("Heavy Arbalest", 225, Rarity.UNCOMMON, mage.cards.h.HeavyArbalest.class));
+ cards.add(new SetCardInfo("Nihil Spellbomb", 226, Rarity.COMMON, mage.cards.n.NihilSpellbomb.class));
+ cards.add(new SetCardInfo("Perilous Myr", 227, Rarity.UNCOMMON, mage.cards.p.PerilousMyr.class));
+ cards.add(new SetCardInfo("Primal Clay", 228, Rarity.COMMON, mage.cards.p.PrimalClay.class));
+ cards.add(new SetCardInfo("Prophetic Prism", 229, Rarity.COMMON, mage.cards.p.PropheticPrism.class));
+ cards.add(new SetCardInfo("Sai of the Shinobi", 230, Rarity.UNCOMMON, mage.cards.s.SaiOfTheShinobi.class));
+ cards.add(new SetCardInfo("Self-Assembler", 231, Rarity.COMMON, mage.cards.s.SelfAssembler.class));
+ cards.add(new SetCardInfo("Strionic Resonator", 232, Rarity.RARE, mage.cards.s.StrionicResonator.class));
+ cards.add(new SetCardInfo("Sundering Titan", 233, Rarity.RARE, mage.cards.s.SunderingTitan.class));
+ cards.add(new SetCardInfo("Swiftfoot Boots", 234, Rarity.UNCOMMON, mage.cards.s.SwiftfootBoots.class));
+ cards.add(new SetCardInfo("Treasure Keeper", 235, Rarity.UNCOMMON, mage.cards.t.TreasureKeeper.class));
+ cards.add(new SetCardInfo("Ash Barrens", 236, Rarity.UNCOMMON, mage.cards.a.AshBarrens.class));
+ cards.add(new SetCardInfo("Cascade Bluffs", 237, Rarity.RARE, mage.cards.c.CascadeBluffs.class));
+ cards.add(new SetCardInfo("Fetid Heath", 238, Rarity.RARE, mage.cards.f.FetidHeath.class));
+ cards.add(new SetCardInfo("Flooded Grove", 239, Rarity.RARE, mage.cards.f.FloodedGrove.class));
+ cards.add(new SetCardInfo("Haunted Fengraf", 240, Rarity.COMMON, mage.cards.h.HauntedFengraf.class));
+ cards.add(new SetCardInfo("Mikokoro, Center of the Sea", 241, Rarity.RARE, mage.cards.m.MikokoroCenterOfTheSea.class));
+ cards.add(new SetCardInfo("Mishra's Factory", 242, Rarity.UNCOMMON, mage.cards.m.MishrasFactory.class));
+ cards.add(new SetCardInfo("Myriad Landscape", 243, Rarity.UNCOMMON, mage.cards.m.MyriadLandscape.class));
+ cards.add(new SetCardInfo("Pendelhaven", 244, Rarity.RARE, mage.cards.p.Pendelhaven.class));
+ cards.add(new SetCardInfo("Quicksand", 245, Rarity.UNCOMMON, mage.cards.q.Quicksand.class));
+ cards.add(new SetCardInfo("Rishadan Port", 246, Rarity.RARE, mage.cards.r.RishadanPort.class));
+ cards.add(new SetCardInfo("Rugged Prairie", 247, Rarity.RARE, mage.cards.r.RuggedPrairie.class));
+ cards.add(new SetCardInfo("Twilight Mire", 248, Rarity.RARE, mage.cards.t.TwilightMire.class));
+ cards.add(new SetCardInfo("Zoetic Cavern", 249, Rarity.UNCOMMON, mage.cards.z.ZoeticCavern.class));
}
}
diff --git a/Mage.Sets/src/mage/sets/MastersEdition.java b/Mage.Sets/src/mage/sets/MastersEdition.java
index d38ce5df2e2..cdf94aba0e5 100644
--- a/Mage.Sets/src/mage/sets/MastersEdition.java
+++ b/Mage.Sets/src/mage/sets/MastersEdition.java
@@ -114,6 +114,7 @@ public class MastersEdition extends ExpansionSet {
cards.add(new SetCardInfo("Erg Raiders", 68, Rarity.COMMON, mage.cards.e.ErgRaiders.class));
cards.add(new SetCardInfo("Eureka", 117, Rarity.RARE, mage.cards.e.Eureka.class));
cards.add(new SetCardInfo("Exile", 12, Rarity.COMMON, mage.cards.e.Exile.class));
+ cards.add(new SetCardInfo("The Fallen", 69, Rarity.UNCOMMON, mage.cards.t.TheFallen.class));
cards.add(new SetCardInfo("Feast or Famine", 70, Rarity.COMMON, mage.cards.f.FeastOrFamine.class));
cards.add(new SetCardInfo("Fire Covenant", 145, Rarity.UNCOMMON, mage.cards.f.FireCovenant.class));
cards.add(new SetCardInfo("Fissure", 93, Rarity.COMMON, mage.cards.f.Fissure.class));
diff --git a/Mage.Sets/src/mage/sets/MastersEditionIII.java b/Mage.Sets/src/mage/sets/MastersEditionIII.java
index 6ba61343461..dfc7254072c 100644
--- a/Mage.Sets/src/mage/sets/MastersEditionIII.java
+++ b/Mage.Sets/src/mage/sets/MastersEditionIII.java
@@ -137,6 +137,7 @@ public class MastersEditionIII extends ExpansionSet {
cards.add(new SetCardInfo("Hammerheim", 207, Rarity.UNCOMMON, mage.cards.h.Hammerheim.class));
cards.add(new SetCardInfo("Hazezon Tamar", 151, Rarity.RARE, mage.cards.h.HazezonTamar.class));
cards.add(new SetCardInfo("Heal", 14, Rarity.COMMON, mage.cards.h.Heal.class));
+ cards.add(new SetCardInfo("Heavy Fog", 122, Rarity.COMMON, mage.cards.h.HeavyFog.class));
cards.add(new SetCardInfo("Hellfire", 70, Rarity.RARE, mage.cards.h.Hellfire.class));
cards.add(new SetCardInfo("Hua Tuo, Honored Physician", 123, Rarity.RARE, mage.cards.h.HuaTuoHonoredPhysician.class));
cards.add(new SetCardInfo("Hunding Gjornersen", 152, Rarity.UNCOMMON, mage.cards.h.HundingGjornersen.class));
diff --git a/Mage.Sets/src/mage/sets/MastersEditionIV.java b/Mage.Sets/src/mage/sets/MastersEditionIV.java
index 03ff7d240ac..e06cd8e06cd 100644
--- a/Mage.Sets/src/mage/sets/MastersEditionIV.java
+++ b/Mage.Sets/src/mage/sets/MastersEditionIV.java
@@ -91,6 +91,7 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Bee Sting", 144, Rarity.UNCOMMON, mage.cards.b.BeeSting.class));
cards.add(new SetCardInfo("Bird Maiden", 110, Rarity.COMMON, mage.cards.b.BirdMaiden.class));
cards.add(new SetCardInfo("Black Knight", 71, Rarity.UNCOMMON, mage.cards.b.BlackKnight.class));
+ cards.add(new SetCardInfo("Blaze of Glory", 7, Rarity.UNCOMMON, mage.cards.b.BlazeOfGlory.class));
cards.add(new SetCardInfo("Blue Elemental Blast", 39, Rarity.UNCOMMON, mage.cards.b.BlueElementalBlast.class));
cards.add(new SetCardInfo("Book of Rass", 183, Rarity.UNCOMMON, mage.cards.b.BookOfRass.class));
cards.add(new SetCardInfo("Bottle of Suleiman", 184, Rarity.RARE, mage.cards.b.BottleOfSuleiman.class));
@@ -169,6 +170,7 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Grapeshot Catapult", 204, Rarity.UNCOMMON, mage.cards.g.GrapeshotCatapult.class));
cards.add(new SetCardInfo("Gravebind", 84, Rarity.COMMON, mage.cards.g.Gravebind.class));
cards.add(new SetCardInfo("Guardian Beast", 85, Rarity.RARE, mage.cards.g.GuardianBeast.class));
+ cards.add(new SetCardInfo("Harsh Justice", 13, Rarity.RARE, mage.cards.h.HarshJustice.class));
cards.add(new SetCardInfo("Hasran Ogress", 86, Rarity.COMMON, mage.cards.h.HasranOgress.class));
cards.add(new SetCardInfo("Healing Salve", 14, Rarity.COMMON, mage.cards.h.HealingSalve.class));
cards.add(new SetCardInfo("Horn of Deafening", 205, Rarity.UNCOMMON, mage.cards.h.HornOfDeafening.class));
@@ -181,6 +183,7 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Jade Monolith", 208, Rarity.RARE, mage.cards.j.JadeMonolith.class));
cards.add(new SetCardInfo("Juggernaut", 209, Rarity.UNCOMMON, mage.cards.j.Juggernaut.class));
cards.add(new SetCardInfo("Junún Efreet", 88, Rarity.UNCOMMON, mage.cards.j.JununEfreet.class));
+ cards.add(new SetCardInfo("Just Fate", 16, Rarity.COMMON, mage.cards.j.JustFate.class));
cards.add(new SetCardInfo("Kismet", 17, Rarity.RARE, mage.cards.k.Kismet.class));
cards.add(new SetCardInfo("Kormus Bell", 210, Rarity.RARE, mage.cards.k.KormusBell.class));
cards.add(new SetCardInfo("Kudzu", 159, Rarity.UNCOMMON, mage.cards.k.Kudzu.class));
@@ -238,6 +241,7 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Sandstorm", 164, Rarity.COMMON, mage.cards.s.Sandstorm.class));
cards.add(new SetCardInfo("Savannah Lions", 24, Rarity.UNCOMMON, mage.cards.s.SavannahLions.class));
cards.add(new SetCardInfo("Savannah", 250, Rarity.RARE, mage.cards.s.Savannah.class));
+ cards.add(new SetCardInfo("Scarecrow", 225, Rarity.UNCOMMON, mage.cards.s.Scarecrow.class));
cards.add(new SetCardInfo("Scarwood Bandits", 165, Rarity.RARE, mage.cards.s.ScarwoodBandits.class));
cards.add(new SetCardInfo("Scavenger Folk", 166, Rarity.COMMON, mage.cards.s.ScavengerFolk.class));
cards.add(new SetCardInfo("Scavenging Ghoul", 95, Rarity.UNCOMMON, mage.cards.s.ScavengingGhoul.class));
@@ -316,6 +320,7 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Wild Aesthir", 34, Rarity.COMMON, mage.cards.w.WildAesthir.class));
cards.add(new SetCardInfo("Wild Griffin", 35, Rarity.COMMON, mage.cards.w.WildGriffin.class));
cards.add(new SetCardInfo("Wild Ox", 174, Rarity.UNCOMMON, mage.cards.w.WildOx.class));
+ cards.add(new SetCardInfo("Wood Elemental", 175, Rarity.RARE, mage.cards.w.WoodElemental.class));
cards.add(new SetCardInfo("Xenic Poltergeist", 104, Rarity.UNCOMMON, mage.cards.x.XenicPoltergeist.class));
cards.add(new SetCardInfo("Yotian Soldier", 240, Rarity.COMMON, mage.cards.y.YotianSoldier.class));
cards.add(new SetCardInfo("Zombie Master", 105, Rarity.UNCOMMON, mage.cards.z.ZombieMaster.class));
diff --git a/Mage.Sets/src/mage/sets/MercadianMasques.java b/Mage.Sets/src/mage/sets/MercadianMasques.java
index 233c8fc0ecf..0b52b888585 100644
--- a/Mage.Sets/src/mage/sets/MercadianMasques.java
+++ b/Mage.Sets/src/mage/sets/MercadianMasques.java
@@ -219,6 +219,7 @@ public class MercadianMasques extends ExpansionSet {
cards.add(new SetCardInfo("Maggot Therapy", 145, Rarity.COMMON, mage.cards.m.MaggotTherapy.class));
cards.add(new SetCardInfo("Magistrate's Scepter", 304, Rarity.RARE, mage.cards.m.MagistratesScepter.class));
cards.add(new SetCardInfo("Magistrate's Veto", 204, Rarity.UNCOMMON, mage.cards.m.MagistratesVeto.class));
+ cards.add(new SetCardInfo("Mercadia's Downfall", 205, Rarity.UNCOMMON, mage.cards.m.MercadiasDownfall.class));
cards.add(new SetCardInfo("Mercadian Bazaar", 321, Rarity.UNCOMMON, mage.cards.m.MercadianBazaar.class));
cards.add(new SetCardInfo("Midnight Ritual", 146, Rarity.RARE, mage.cards.m.MidnightRitual.class));
cards.add(new SetCardInfo("Misdirection", 87, Rarity.RARE, mage.cards.m.Misdirection.class));
diff --git a/Mage.Sets/src/mage/sets/Portal.java b/Mage.Sets/src/mage/sets/Portal.java
index 8c15c619ed3..36adbfaa9b7 100644
--- a/Mage.Sets/src/mage/sets/Portal.java
+++ b/Mage.Sets/src/mage/sets/Portal.java
@@ -71,7 +71,7 @@ public class Portal extends ExpansionSet {
cards.add(new SetCardInfo("Armageddon", 167, Rarity.RARE, mage.cards.a.Armageddon.class));
cards.add(new SetCardInfo("Armored Pegasus", 168, Rarity.COMMON, mage.cards.a.ArmoredPegasus.class));
cards.add(new SetCardInfo("Arrogant Vampire", 1, Rarity.UNCOMMON, mage.cards.a.ArrogantVampire.class));
- cards.add(new SetCardInfo("Assassin's Blade", 2, Rarity.UNCOMMON, mage.cards.a.AssassinsBlade.class));
+ cards.add(new SetCardInfo("Assassin's Blade", 2, Rarity.UNCOMMON, mage.cards.a.AssassinsBlade.class));
cards.add(new SetCardInfo("Balance of Power", 42, Rarity.RARE, mage.cards.b.BalanceOfPower.class));
cards.add(new SetCardInfo("Baleful Stare", 43, Rarity.UNCOMMON, mage.cards.b.BalefulStare.class));
cards.add(new SetCardInfo("Bee Sting", 83, Rarity.UNCOMMON, mage.cards.b.BeeSting.class));
@@ -95,19 +95,22 @@ public class Portal extends ExpansionSet {
cards.add(new SetCardInfo("Cloud Dragon", 46, Rarity.RARE, mage.cards.c.CloudDragon.class));
cards.add(new SetCardInfo("Cloud Pirates", 47, Rarity.COMMON, mage.cards.c.CloudPirates.class));
cards.add(new SetCardInfo("Cloud Spirit", 48, Rarity.UNCOMMON, mage.cards.c.CloudSpirit.class));
- cards.add(new SetCardInfo("Command of Unsummoning", 49, Rarity.UNCOMMON, mage.cards.c.CommandOfUnsummoning.class));
+ cards.add(new SetCardInfo("Command of Unsummoning", 49, Rarity.UNCOMMON, mage.cards.c.CommandOfUnsummoning.class));
cards.add(new SetCardInfo("Coral Eel", 50, Rarity.COMMON, mage.cards.c.CoralEel.class));
cards.add(new SetCardInfo("Craven Giant", 126, Rarity.COMMON, mage.cards.c.CravenGiant.class));
cards.add(new SetCardInfo("Craven Knight", 7, Rarity.COMMON, mage.cards.c.CravenKnight.class));
cards.add(new SetCardInfo("Cruel Bargain", 8, Rarity.RARE, mage.cards.c.CruelBargain.class));
+ cards.add(new SetCardInfo("Cruel Fate", 51, Rarity.RARE, mage.cards.c.CruelFate.class));
cards.add(new SetCardInfo("Cruel Tutor", 9, Rarity.RARE, mage.cards.c.CruelTutor.class));
cards.add(new SetCardInfo("Deep-Sea Serpent", 52, Rarity.UNCOMMON, mage.cards.d.DeepSeaSerpent.class));
- cards.add(new SetCardInfo("Defiant Stand", 174, Rarity.UNCOMMON, mage.cards.d.DefiantStand.class));
+ cards.add(new SetCardInfo("Deep Wood", 86, Rarity.UNCOMMON, mage.cards.d.DeepWood.class));
+ cards.add(new SetCardInfo("Defiant Stand", 174, Rarity.UNCOMMON, mage.cards.d.DefiantStand.class));
cards.add(new SetCardInfo("Deja Vu", 53, Rarity.COMMON, mage.cards.d.DejaVu.class));
cards.add(new SetCardInfo("Desert Drake", 127, Rarity.UNCOMMON, mage.cards.d.DesertDrake.class));
cards.add(new SetCardInfo("Devastation", 128, Rarity.RARE, mage.cards.d.Devastation.class));
cards.add(new SetCardInfo("Devoted Hero", 175, Rarity.COMMON, mage.cards.d.DevotedHero.class));
cards.add(new SetCardInfo("Djinn of the Lamp", 54, Rarity.RARE, mage.cards.d.DjinnOfTheLamp.class));
+ cards.add(new SetCardInfo("Dread Charge", 10, Rarity.RARE, mage.cards.d.DreadCharge.class));
cards.add(new SetCardInfo("Dread Reaper", 11, Rarity.RARE, mage.cards.d.DreadReaper.class));
cards.add(new SetCardInfo("Dry Spell", 12, Rarity.UNCOMMON, DrySpell.class));
cards.add(new SetCardInfo("Earthquake", 129, Rarity.RARE, mage.cards.e.Earthquake.class));
@@ -143,6 +146,7 @@ public class Portal extends ExpansionSet {
cards.add(new SetCardInfo("Grizzly Bears", 94, Rarity.COMMON, mage.cards.g.GrizzlyBears.class));
cards.add(new SetCardInfo("Hand of Death", 18, Rarity.COMMON, mage.cards.h.HandOfDeath.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Hand of Death", 19, Rarity.COMMON, mage.cards.h.HandOfDeath.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Harsh Justice", 180, Rarity.RARE, mage.cards.h.HarshJustice.class));
cards.add(new SetCardInfo("Highland Giant", 137, Rarity.COMMON, mage.cards.h.HighlandGiant.class));
cards.add(new SetCardInfo("Hill Giant", 138, Rarity.COMMON, mage.cards.h.HillGiant.class));
cards.add(new SetCardInfo("Horned Turtle", 58, Rarity.COMMON, mage.cards.h.HornedTurtle.class));
@@ -217,7 +221,7 @@ public class Portal extends ExpansionSet {
cards.add(new SetCardInfo("Sacred Knight", 186, Rarity.COMMON, mage.cards.s.SacredKnight.class));
cards.add(new SetCardInfo("Sacred Nectar", 187, Rarity.COMMON, mage.cards.s.SacredNectar.class));
cards.add(new SetCardInfo("Scorching Spear", 154, Rarity.COMMON, mage.cards.s.ScorchingSpear.class));
- cards.add(new SetCardInfo("Scorching Winds", 155, Rarity.UNCOMMON, mage.cards.s.ScorchingWinds.class));
+ cards.add(new SetCardInfo("Scorching Winds", 155, Rarity.UNCOMMON, mage.cards.s.ScorchingWinds.class));
cards.add(new SetCardInfo("Seasoned Marshal", 188, Rarity.UNCOMMON, mage.cards.s.SeasonedMarshal.class));
cards.add(new SetCardInfo("Serpent Assassin", 31, Rarity.RARE, mage.cards.s.SerpentAssassin.class));
cards.add(new SetCardInfo("Serpent Warrior", 32, Rarity.COMMON, mage.cards.s.SerpentWarrior.class));
@@ -245,6 +249,7 @@ public class Portal extends ExpansionSet {
cards.add(new SetCardInfo("Sylvan Tutor", 114, Rarity.RARE, mage.cards.s.SylvanTutor.class));
cards.add(new SetCardInfo("Symbol of Unsummoning", 71, Rarity.COMMON, mage.cards.s.SymbolOfUnsummoning.class));
cards.add(new SetCardInfo("Taunt", 72, Rarity.RARE, mage.cards.t.Taunt.class));
+ cards.add(new SetCardInfo("Temporary Truce", 195, Rarity.RARE, mage.cards.t.TemporaryTruce.class));
cards.add(new SetCardInfo("Theft of Dreams", 73, Rarity.UNCOMMON, mage.cards.t.TheftOfDreams.class));
cards.add(new SetCardInfo("Thing from the Deep", 74, Rarity.RARE, mage.cards.t.ThingFromTheDeep.class));
cards.add(new SetCardInfo("Thundering Wurm", 115, Rarity.RARE, mage.cards.t.ThunderingWurm.class));
@@ -252,7 +257,7 @@ public class Portal extends ExpansionSet {
cards.add(new SetCardInfo("Tidal Surge", 75, Rarity.COMMON, mage.cards.t.TidalSurge.class));
cards.add(new SetCardInfo("Time Ebb", 76, Rarity.COMMON, mage.cards.t.TimeEbb.class));
cards.add(new SetCardInfo("Touch of Brilliance", 77, Rarity.COMMON, mage.cards.t.TouchOfBrilliance.class));
- cards.add(new SetCardInfo("Treetop Defense", 116, Rarity.RARE, mage.cards.t.TreetopDefense.class));
+ cards.add(new SetCardInfo("Treetop Defense", 116, Rarity.RARE, mage.cards.t.TreetopDefense.class));
cards.add(new SetCardInfo("Undying Beast", 36, Rarity.COMMON, mage.cards.u.UndyingBeast.class));
cards.add(new SetCardInfo("Untamed Wilds", 117, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class));
cards.add(new SetCardInfo("Valorous Charge", 196, Rarity.UNCOMMON, mage.cards.v.ValorousCharge.class));
diff --git a/Mage.Sets/src/mage/sets/PortalSecondAge.java b/Mage.Sets/src/mage/sets/PortalSecondAge.java
index f014ac1968b..827a31692cd 100644
--- a/Mage.Sets/src/mage/sets/PortalSecondAge.java
+++ b/Mage.Sets/src/mage/sets/PortalSecondAge.java
@@ -95,6 +95,7 @@ public class PortalSecondAge extends ExpansionSet {
cards.add(new SetCardInfo("Dakmor Sorceress", 11, Rarity.RARE, mage.cards.d.DakmorSorceress.class));
cards.add(new SetCardInfo("Dark Offering", 12, Rarity.UNCOMMON, mage.cards.d.DarkOffering.class));
cards.add(new SetCardInfo("Deathcoil Wurm", 65, Rarity.RARE, mage.cards.d.DeathcoilWurm.class));
+ cards.add(new SetCardInfo("Deep Wood", 66, Rarity.UNCOMMON, mage.cards.d.DeepWood.class));
cards.add(new SetCardInfo("Deja Vu", 35, Rarity.COMMON, mage.cards.d.DejaVu.class));
cards.add(new SetCardInfo("Denizen of the Deep", 36, Rarity.RARE, mage.cards.d.DenizenOfTheDeep.class));
cards.add(new SetCardInfo("Earthquake", 94, Rarity.RARE, mage.cards.e.Earthquake.class));
@@ -116,6 +117,7 @@ public class PortalSecondAge extends ExpansionSet {
cards.add(new SetCardInfo("Goblin Mountaineer", 101, Rarity.COMMON, mage.cards.g.GoblinMountaineer.class));
cards.add(new SetCardInfo("Goblin Piker", 102, Rarity.COMMON, mage.cards.g.GoblinPiker.class));
cards.add(new SetCardInfo("Goblin Raider", 103, Rarity.COMMON, mage.cards.g.GoblinRaider.class));
+ cards.add(new SetCardInfo("Goblin War Cry", 104, Rarity.UNCOMMON, mage.cards.g.GoblinWarCry.class));
cards.add(new SetCardInfo("Goblin War Strike", 105, Rarity.COMMON, mage.cards.g.GoblinWarStrike.class));
cards.add(new SetCardInfo("Golden Bear", 67, Rarity.COMMON, mage.cards.g.GoldenBear.class));
cards.add(new SetCardInfo("Hand of Death", 14, Rarity.COMMON, mage.cards.h.HandOfDeath.class));
@@ -127,6 +129,7 @@ public class PortalSecondAge extends ExpansionSet {
cards.add(new SetCardInfo("Island", 155, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Island", 156, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Jagged Lightning", 106, Rarity.UNCOMMON, mage.cards.j.JaggedLightning.class));
+ cards.add(new SetCardInfo("Just Fate", 137, Rarity.RARE, mage.cards.j.JustFate.class));
cards.add(new SetCardInfo("Kiss of Death", 16, Rarity.UNCOMMON, mage.cards.k.KissOfDeath.class));
cards.add(new SetCardInfo("Lava Axe", 107, Rarity.COMMON, mage.cards.l.LavaAxe.class));
cards.add(new SetCardInfo("Lone Wolf", 71, Rarity.UNCOMMON, mage.cards.l.LoneWolf.class));
@@ -212,6 +215,7 @@ public class PortalSecondAge extends ExpansionSet {
cards.add(new SetCardInfo("Vengeance", 147, Rarity.UNCOMMON, mage.cards.v.Vengeance.class));
cards.add(new SetCardInfo("Volcanic Hammer", 119, Rarity.COMMON, mage.cards.v.VolcanicHammer.class));
cards.add(new SetCardInfo("Volunteer Militia", 148, Rarity.COMMON, mage.cards.v.VolunteerMilitia.class));
+ cards.add(new SetCardInfo("Warrior's Stand", 149, Rarity.UNCOMMON, mage.cards.w.WarriorsStand.class));
cards.add(new SetCardInfo("Wildfire", 120, Rarity.RARE, mage.cards.w.Wildfire.class));
cards.add(new SetCardInfo("Wild Griffin", 150, Rarity.COMMON, mage.cards.w.WildGriffin.class));
cards.add(new SetCardInfo("Wild Ox", 90, Rarity.UNCOMMON, mage.cards.w.WildOx.class));
diff --git a/Mage.Sets/src/mage/sets/PortalThreeKingdoms.java b/Mage.Sets/src/mage/sets/PortalThreeKingdoms.java
index bc64a4afe95..611ca804708 100644
--- a/Mage.Sets/src/mage/sets/PortalThreeKingdoms.java
+++ b/Mage.Sets/src/mage/sets/PortalThreeKingdoms.java
@@ -83,6 +83,7 @@ public class PortalThreeKingdoms extends ExpansionSet {
cards.add(new SetCardInfo("Dong Zhou, the Tyrant", 109, Rarity.RARE, mage.cards.d.DongZhouTheTyrant.class));
cards.add(new SetCardInfo("Eightfold Maze", 2, Rarity.RARE, mage.cards.e.EightfoldMaze.class));
cards.add(new SetCardInfo("Empty City Ruse", 3, Rarity.UNCOMMON, mage.cards.e.EmptyCityRuse.class));
+ cards.add(new SetCardInfo("Eunuchs' Intrigues", 110, Rarity.UNCOMMON, mage.cards.e.EunuchsIntrigues.class));
cards.add(new SetCardInfo("Exhaustion", 42, Rarity.RARE, mage.cards.e.Exhaustion.class));
cards.add(new SetCardInfo("Extinguish", 43, Rarity.COMMON, mage.cards.e.Extinguish.class));
cards.add(new SetCardInfo("False Defeat", 4, Rarity.COMMON, mage.cards.f.FalseDefeat.class));
@@ -99,6 +100,7 @@ public class PortalThreeKingdoms extends ExpansionSet {
cards.add(new SetCardInfo("Ghostly Visit", 76, Rarity.COMMON, mage.cards.g.GhostlyVisit.class));
cards.add(new SetCardInfo("Guan Yu's 1,000-Li March", 7, Rarity.RARE, mage.cards.g.GuanYus1000LiMarch.class));
cards.add(new SetCardInfo("Guan Yu, Sainted Warrior", 6, Rarity.RARE, mage.cards.g.GuanYuSaintedWarrior.class));
+ cards.add(new SetCardInfo("Heavy Fog", 136, Rarity.UNCOMMON, mage.cards.h.HeavyFog.class));
cards.add(new SetCardInfo("Huang Zhong, Shu General", 8, Rarity.RARE, mage.cards.h.HuangZhongShuGeneral.class));
cards.add(new SetCardInfo("Hua Tuo, Honored Physician", 137, Rarity.RARE, mage.cards.h.HuaTuoHonoredPhysician.class));
cards.add(new SetCardInfo("Hunting Cheetah", 138, Rarity.UNCOMMON, mage.cards.h.HuntingCheetah.class));
@@ -110,6 +112,7 @@ public class PortalThreeKingdoms extends ExpansionSet {
cards.add(new SetCardInfo("Island", 170, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Island", 171, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Kongming, \"Sleeping Dragon\"", 9, Rarity.RARE, mage.cards.k.KongmingSleepingDragon.class));
+ cards.add(new SetCardInfo("Kongming's Contraptions", 10, Rarity.RARE, mage.cards.k.KongmingsContraptions.class));
cards.add(new SetCardInfo("Lady Sun", 45, Rarity.RARE, mage.cards.l.LadySun.class));
cards.add(new SetCardInfo("Lady Zhurong, Warrior Queen", 139, Rarity.RARE, mage.cards.l.LadyZhurongWarriorQueen.class));
cards.add(new SetCardInfo("Liu Bei, Lord of Shu", 11, Rarity.RARE, mage.cards.l.LiuBeiLordOfShu.class));
@@ -185,6 +188,7 @@ public class PortalThreeKingdoms extends ExpansionSet {
cards.add(new SetCardInfo("Virtuous Charge", 29, Rarity.COMMON, mage.cards.v.VirtuousCharge.class));
cards.add(new SetCardInfo("Volunteer Militia", 30, Rarity.COMMON, mage.cards.v.VolunteerMilitia.class));
cards.add(new SetCardInfo("Warrior's Oath", 124, Rarity.RARE, mage.cards.w.WarriorsOath.class));
+ cards.add(new SetCardInfo("Warrior's Stand", 31, Rarity.UNCOMMON, mage.cards.w.WarriorsStand.class));
cards.add(new SetCardInfo("Wei Ambush Force", 85, Rarity.COMMON, mage.cards.w.WeiAmbushForce.class));
cards.add(new SetCardInfo("Wei Assassins", 86, Rarity.UNCOMMON, mage.cards.w.WeiAssassins.class));
cards.add(new SetCardInfo("Wei Elite Companions", 87, Rarity.UNCOMMON, mage.cards.w.WeiEliteCompanions.class));
diff --git a/Mage.Sets/src/mage/sets/RevisedEdition.java b/Mage.Sets/src/mage/sets/RevisedEdition.java
index a798e9d1fcd..74924028acb 100644
--- a/Mage.Sets/src/mage/sets/RevisedEdition.java
+++ b/Mage.Sets/src/mage/sets/RevisedEdition.java
@@ -220,6 +220,7 @@ public class RevisedEdition extends ExpansionSet {
cards.add(new SetCardInfo("Plains", 294, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plains", 295, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plateau", 296, Rarity.RARE, mage.cards.p.Plateau.class));
+ cards.add(new SetCardInfo("Power Leak", 73, Rarity.COMMON, mage.cards.p.PowerLeak.class));
cards.add(new SetCardInfo("Power Sink", 74, Rarity.COMMON, mage.cards.p.PowerSink.class));
cards.add(new SetCardInfo("Power Surge", 169, Rarity.RARE, mage.cards.p.PowerSurge.class));
cards.add(new SetCardInfo("Primal Clay", 271, Rarity.RARE, mage.cards.p.PrimalClay.class));
@@ -234,6 +235,7 @@ public class RevisedEdition extends ExpansionSet {
cards.add(new SetCardInfo("Regrowth", 121, Rarity.UNCOMMON, mage.cards.r.Regrowth.class));
cards.add(new SetCardInfo("Resurrection", 218, Rarity.UNCOMMON, mage.cards.r.Resurrection.class));
cards.add(new SetCardInfo("Reverse Damage", 219, Rarity.RARE, mage.cards.r.ReverseDamage.class));
+ cards.add(new SetCardInfo("Reverse Polarity", 220, Rarity.UNCOMMON, mage.cards.r.ReversePolarity.class));
cards.add(new SetCardInfo("Righteousness", 221, Rarity.RARE, mage.cards.r.Righteousness.class));
cards.add(new SetCardInfo("Roc of Kher Ridges", 171, Rarity.RARE, mage.cards.r.RocOfKherRidges.class));
cards.add(new SetCardInfo("Rock Hydra", 172, Rarity.RARE, mage.cards.r.RockHydra.class));
diff --git a/Mage.Sets/src/mage/sets/Scourge.java b/Mage.Sets/src/mage/sets/Scourge.java
index ad8585d5827..3c5bf9920f1 100644
--- a/Mage.Sets/src/mage/sets/Scourge.java
+++ b/Mage.Sets/src/mage/sets/Scourge.java
@@ -126,6 +126,7 @@ public class Scourge extends ExpansionSet {
cards.add(new SetCardInfo("Guilty Conscience", 17, Rarity.COMMON, mage.cards.g.GuiltyConscience.class));
cards.add(new SetCardInfo("Hindering Touch", 37, Rarity.COMMON, mage.cards.h.HinderingTouch.class));
cards.add(new SetCardInfo("Hunting Pack", 121, Rarity.UNCOMMON, mage.cards.h.HuntingPack.class));
+ cards.add(new SetCardInfo("Karona's Zealot", 18, Rarity.UNCOMMON, mage.cards.k.KaronasZealot.class));
cards.add(new SetCardInfo("Karona, False God", 138, Rarity.RARE, mage.cards.k.KaronaFalseGod.class));
cards.add(new SetCardInfo("Krosan Drover", 122, Rarity.COMMON, mage.cards.k.KrosanDrover.class));
cards.add(new SetCardInfo("Krosan Warchief", 123, Rarity.UNCOMMON, mage.cards.k.KrosanWarchief.class));
@@ -142,8 +143,10 @@ public class Scourge extends ExpansionSet {
cards.add(new SetCardInfo("Nefashu", 70, Rarity.RARE, mage.cards.n.Nefashu.class));
cards.add(new SetCardInfo("Noble Templar", 19, Rarity.COMMON, mage.cards.n.NobleTemplar.class));
cards.add(new SetCardInfo("One with Nature", 125, Rarity.UNCOMMON, mage.cards.o.OneWithNature.class));
+ cards.add(new SetCardInfo("Parallel Thoughts", 44, Rarity.RARE, mage.cards.p.ParallelThoughts.class));
cards.add(new SetCardInfo("Pemmin's Aura", 45, Rarity.UNCOMMON, mage.cards.p.PemminsAura.class));
cards.add(new SetCardInfo("Primitive Etchings", 126, Rarity.RARE, mage.cards.p.PrimitiveEtchings.class));
+ cards.add(new SetCardInfo("Proteus Machine", 141, Rarity.UNCOMMON, mage.cards.p.ProteusMachine.class));
cards.add(new SetCardInfo("Putrid Raptor", 71, Rarity.UNCOMMON, mage.cards.p.PutridRaptor.class));
cards.add(new SetCardInfo("Pyrostatic Pillar", 100, Rarity.UNCOMMON, mage.cards.p.PyrostaticPillar.class));
cards.add(new SetCardInfo("Rain of Blades", 20, Rarity.UNCOMMON, mage.cards.r.RainOfBlades.class));
diff --git a/Mage.Sets/src/mage/sets/Tempest.java b/Mage.Sets/src/mage/sets/Tempest.java
index 4766f25acd5..26a956063fb 100644
--- a/Mage.Sets/src/mage/sets/Tempest.java
+++ b/Mage.Sets/src/mage/sets/Tempest.java
@@ -196,6 +196,7 @@ public class Tempest extends ExpansionSet {
cards.add(new SetCardInfo("Meditate", 76, Rarity.RARE, mage.cards.m.Meditate.class));
cards.add(new SetCardInfo("Metallic Sliver", 287, Rarity.COMMON, mage.cards.m.MetallicSliver.class));
cards.add(new SetCardInfo("Mindwhip Sliver", 39, Rarity.UNCOMMON, mage.cards.m.MindwhipSliver.class));
+ cards.add(new SetCardInfo("Minion of the Wastes", 40, Rarity.RARE, mage.cards.m.MinionOfTheWastes.class));
cards.add(new SetCardInfo("Mirri's Guile", 130, Rarity.RARE, mage.cards.m.MirrisGuile.class));
cards.add(new SetCardInfo("Mnemonic Sliver", 77, Rarity.UNCOMMON, mage.cards.m.MnemonicSliver.class));
cards.add(new SetCardInfo("Mogg Cannon", 288, Rarity.UNCOMMON, mage.cards.m.MoggCannon.class));
@@ -218,6 +219,7 @@ public class Tempest extends ExpansionSet {
cards.add(new SetCardInfo("Opportunist", 194, Rarity.UNCOMMON, mage.cards.o.Opportunist.class));
cards.add(new SetCardInfo("Oracle en-Vec", 243, Rarity.RARE, mage.cards.o.OracleEnVec.class));
cards.add(new SetCardInfo("Orim, Samite Healer", 244, Rarity.RARE, mage.cards.o.OrimSamiteHealer.class));
+ cards.add(new SetCardInfo("Orim's Prayer", 245, Rarity.UNCOMMON, mage.cards.o.OrimsPrayer.class));
cards.add(new SetCardInfo("Overrun", 137, Rarity.UNCOMMON, mage.cards.o.Overrun.class));
cards.add(new SetCardInfo("Pacifism", 246, Rarity.COMMON, mage.cards.p.Pacifism.class));
cards.add(new SetCardInfo("Pallimud", 195, Rarity.RARE, mage.cards.p.Pallimud.class));
diff --git a/Mage.Sets/src/mage/sets/TheDark.java b/Mage.Sets/src/mage/sets/TheDark.java
index 4fe90148e64..f67cff2be9c 100644
--- a/Mage.Sets/src/mage/sets/TheDark.java
+++ b/Mage.Sets/src/mage/sets/TheDark.java
@@ -126,6 +126,7 @@ public class TheDark extends ExpansionSet {
cards.add(new SetCardInfo("Miracle Worker", 86, Rarity.COMMON, mage.cards.m.MiracleWorker.class));
cards.add(new SetCardInfo("Morale", 87, Rarity.COMMON, mage.cards.m.Morale.class));
cards.add(new SetCardInfo("Murk Dwellers", 11, Rarity.COMMON, mage.cards.m.MurkDwellers.class));
+ cards.add(new SetCardInfo("Nameless Race", 12, Rarity.RARE, mage.cards.n.NamelessRace.class));
cards.add(new SetCardInfo("Necropolis", 102, Rarity.RARE, mage.cards.n.Necropolis.class));
cards.add(new SetCardInfo("Niall Silvain", 45, Rarity.RARE, mage.cards.n.NiallSilvain.class));
cards.add(new SetCardInfo("Orc General", 72, Rarity.UNCOMMON, mage.cards.o.OrcGeneral.class));
@@ -135,6 +136,7 @@ public class TheDark extends ExpansionSet {
cards.add(new SetCardInfo("Psychic Allergy", 33, Rarity.RARE, mage.cards.p.PsychicAllergy.class));
cards.add(new SetCardInfo("Rag Man", 13, Rarity.RARE, mage.cards.r.RagMan.class));
cards.add(new SetCardInfo("Riptide", 34, Rarity.COMMON, mage.cards.r.Riptide.class));
+ cards.add(new SetCardInfo("Runesword", 104, Rarity.RARE, mage.cards.r.Runesword.class));
cards.add(new SetCardInfo("Safe Haven", 115, Rarity.RARE, mage.cards.s.SafeHaven.class));
cards.add(new SetCardInfo("Savaen Elves", 47, Rarity.COMMON, mage.cards.s.SavaenElves.class));
cards.add(new SetCardInfo("Scarecrow", 105, Rarity.RARE, mage.cards.s.Scarecrow.class));
@@ -152,6 +154,7 @@ public class TheDark extends ExpansionSet {
cards.add(new SetCardInfo("Stone Calendar", 108, Rarity.RARE, mage.cards.s.StoneCalendar.class));
cards.add(new SetCardInfo("Sunken City", 35, Rarity.COMMON, mage.cards.s.SunkenCity.class));
cards.add(new SetCardInfo("Tangle Kelp", 36, Rarity.RARE, mage.cards.t.TangleKelp.class));
+ cards.add(new SetCardInfo("The Fallen", 15, Rarity.RARE, mage.cards.t.TheFallen.class));
cards.add(new SetCardInfo("Tivadar's Crusade", 91, Rarity.UNCOMMON, mage.cards.t.TivadarsCrusade.class));
cards.add(new SetCardInfo("Tormod's Crypt", 109, Rarity.UNCOMMON, mage.cards.t.TormodsCrypt.class));
cards.add(new SetCardInfo("Tower of Coireall", 110, Rarity.RARE, mage.cards.t.TowerOfCoireall.class));
diff --git a/Mage.Sets/src/mage/sets/TimeSpiralTimeshifted.java b/Mage.Sets/src/mage/sets/TimeSpiralTimeshifted.java
index 119cb767c9c..d124325bccc 100644
--- a/Mage.Sets/src/mage/sets/TimeSpiralTimeshifted.java
+++ b/Mage.Sets/src/mage/sets/TimeSpiralTimeshifted.java
@@ -96,6 +96,7 @@ public class TimeSpiralTimeshifted extends ExpansionSet {
cards.add(new SetCardInfo("Goblin Snowman", 64, Rarity.UNCOMMON, mage.cards.g.GoblinSnowman.class));
cards.add(new SetCardInfo("Grinning Totem", 110, Rarity.SPECIAL, mage.cards.g.GrinningTotem.class));
cards.add(new SetCardInfo("Hail Storm", 79, Rarity.SPECIAL, mage.cards.h.HailStorm.class));
+ cards.add(new SetCardInfo("Honorable Passage", 9, Rarity.SPECIAL, mage.cards.h.HonorablePassage.class));
cards.add(new SetCardInfo("Hunting Moa", 80, Rarity.COMMON, mage.cards.h.HuntingMoa.class));
cards.add(new SetCardInfo("Icatian Javelineers", 10, Rarity.SPECIAL, IcatianJavelineers.class));
cards.add(new SetCardInfo("Jasmine Boreal", 93, Rarity.COMMON, mage.cards.j.JasmineBoreal.class));
diff --git a/Mage.Sets/src/mage/sets/UnlimitedEdition.java b/Mage.Sets/src/mage/sets/UnlimitedEdition.java
index e12d2c0d435..a27c910c64f 100644
--- a/Mage.Sets/src/mage/sets/UnlimitedEdition.java
+++ b/Mage.Sets/src/mage/sets/UnlimitedEdition.java
@@ -44,6 +44,7 @@ public class UnlimitedEdition extends ExpansionSet {
cards.add(new SetCardInfo("Black Lotus", 233, Rarity.RARE, mage.cards.b.BlackLotus.class));
cards.add(new SetCardInfo("Black Vise", 234, Rarity.UNCOMMON, mage.cards.b.BlackVise.class));
cards.add(new SetCardInfo("Black Ward", 189, Rarity.UNCOMMON, mage.cards.b.BlackWard.class));
+ cards.add(new SetCardInfo("Blaze of Glory", 190, Rarity.RARE, mage.cards.b.BlazeOfGlory.class));
cards.add(new SetCardInfo("Blessing", 191, Rarity.RARE, mage.cards.b.Blessing.class));
cards.add(new SetCardInfo("Blue Elemental Blast", 50, Rarity.COMMON, mage.cards.b.BlueElementalBlast.class));
cards.add(new SetCardInfo("Blue Ward", 192, Rarity.UNCOMMON, mage.cards.b.BlueWard.class));
@@ -214,6 +215,7 @@ public class UnlimitedEdition extends ExpansionSet {
cards.add(new SetCardInfo("Plains", 290, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plains", 291, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plateau", 292, Rarity.RARE, mage.cards.p.Plateau.class));
+ cards.add(new SetCardInfo("Power Leak", 72, Rarity.COMMON, mage.cards.p.PowerLeak.class));
cards.add(new SetCardInfo("Power Sink", 73, Rarity.COMMON, mage.cards.p.PowerSink.class));
cards.add(new SetCardInfo("Power Surge", 168, Rarity.RARE, mage.cards.p.PowerSurge.class));
cards.add(new SetCardInfo("Prodigal Sorcerer", 74, Rarity.COMMON, mage.cards.p.ProdigalSorcerer.class));
diff --git a/Mage.Sets/src/mage/sets/Unstable.java b/Mage.Sets/src/mage/sets/Unstable.java
index f675d4cbebb..7f1e655814f 100644
--- a/Mage.Sets/src/mage/sets/Unstable.java
+++ b/Mage.Sets/src/mage/sets/Unstable.java
@@ -75,6 +75,7 @@ public class Unstable extends ExpansionSet {
cards.add(new SetCardInfo("Plains", 212, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
cards.add(new SetCardInfo("Snickering Squirrel", 68, Rarity.COMMON, mage.cards.s.SnickeringSquirrel.class));
cards.add(new SetCardInfo("Squirrel-Powered Scheme", 70, Rarity.UNCOMMON, mage.cards.s.SquirrelPoweredScheme.class));
+ cards.add(new SetCardInfo("Steamflogger Boss", 93, Rarity.RARE, mage.cards.s.SteamfloggerBoss.class));
cards.add(new SetCardInfo("Steel Squirrel", 162, Rarity.UNCOMMON, mage.cards.s.SteelSquirrel.class));
cards.add(new SetCardInfo("Summon the Pack", 74, Rarity.MYTHIC, mage.cards.s.SummonThePack.class));
cards.add(new SetCardInfo("Swamp", 214, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false)));
diff --git a/Mage.Sets/src/mage/sets/Visions.java b/Mage.Sets/src/mage/sets/Visions.java
index b537d3b33dd..e1458607a94 100644
--- a/Mage.Sets/src/mage/sets/Visions.java
+++ b/Mage.Sets/src/mage/sets/Visions.java
@@ -63,7 +63,7 @@ public class Visions extends ExpansionSet {
cards.add(new SetCardInfo("Brass-Talon Chimera", 142, Rarity.UNCOMMON, mage.cards.b.BrassTalonChimera.class));
cards.add(new SetCardInfo("Breathstealer's Crypt", 127, Rarity.RARE, mage.cards.b.BreathstealersCrypt.class));
cards.add(new SetCardInfo("Breezekeeper", 27, Rarity.COMMON, mage.cards.b.Breezekeeper.class));
- cards.add(new SetCardInfo("Brood of Cockroaches", 3, Rarity.UNCOMMON, mage.cards.b.BroodOfCockroaches.class));
+ cards.add(new SetCardInfo("Brood of Cockroaches", 3, Rarity.UNCOMMON, mage.cards.b.BroodOfCockroaches.class));
cards.add(new SetCardInfo("Bull Elephant", 51, Rarity.COMMON, mage.cards.b.BullElephant.class));
cards.add(new SetCardInfo("Chronatog", 28, Rarity.RARE, mage.cards.c.Chronatog.class));
cards.add(new SetCardInfo("City of Solitude", 52, Rarity.RARE, mage.cards.c.CityOfSolitude.class));
@@ -96,6 +96,7 @@ public class Visions extends ExpansionSet {
cards.add(new SetCardInfo("Fireblast", 79, Rarity.COMMON, mage.cards.f.Fireblast.class));
cards.add(new SetCardInfo("Firestorm Hellkite", 130, Rarity.RARE, mage.cards.f.FirestormHellkite.class));
cards.add(new SetCardInfo("Flooded Shoreline", 32, Rarity.RARE, mage.cards.f.FloodedShoreline.class));
+ cards.add(new SetCardInfo("Foreshadow", 33, Rarity.UNCOMMON, mage.cards.f.Foreshadow.class));
cards.add(new SetCardInfo("Freewind Falcon", 105, Rarity.COMMON, mage.cards.f.FreewindFalcon.class));
cards.add(new SetCardInfo("Funeral Charm", 11, Rarity.COMMON, mage.cards.f.FuneralCharm.class));
cards.add(new SetCardInfo("Giant Caterpillar", 58, Rarity.COMMON, mage.cards.g.GiantCaterpillar.class));
@@ -105,6 +106,7 @@ public class Visions extends ExpansionSet {
cards.add(new SetCardInfo("Griffin Canyon", 163, Rarity.RARE, mage.cards.g.GriffinCanyon.class));
cards.add(new SetCardInfo("Hearth Charm", 82, Rarity.COMMON, mage.cards.h.HearthCharm.class));
cards.add(new SetCardInfo("Helm of Awakening", 145, Rarity.UNCOMMON, mage.cards.h.HelmOfAwakening.class));
+ cards.add(new SetCardInfo("Honorable Passage", 107, Rarity.UNCOMMON, mage.cards.h.HonorablePassage.class));
cards.add(new SetCardInfo("Hope Charm", 108, Rarity.COMMON, mage.cards.h.HopeCharm.class));
cards.add(new SetCardInfo("Hulking Cyclops", 84, Rarity.UNCOMMON, mage.cards.h.HulkingCyclops.class));
cards.add(new SetCardInfo("Impulse", 34, Rarity.COMMON, mage.cards.i.Impulse.class));
@@ -199,6 +201,7 @@ public class Visions extends ExpansionSet {
cards.add(new SetCardInfo("Warthog", 74, Rarity.COMMON, mage.cards.w.Warthog.class));
cards.add(new SetCardInfo("Waterspout Djinn", 50, Rarity.UNCOMMON, mage.cards.w.WaterspoutDjinn.class));
cards.add(new SetCardInfo("Wicked Reward", 25, Rarity.COMMON, mage.cards.w.WickedReward.class));
+ cards.add(new SetCardInfo("Wind Shear", 75, Rarity.UNCOMMON, mage.cards.w.WindShear.class));
cards.add(new SetCardInfo("Zhalfirin Crusader", 125, Rarity.RARE, mage.cards.z.ZhalfirinCrusader.class));
}
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/BloodMoonTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/BloodMoonTest.java
index 52b8740aac1..d2844086f62 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/BloodMoonTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/BloodMoonTest.java
@@ -5,10 +5,13 @@
*/
package org.mage.test.cards.abilities.enters;
+import mage.constants.CardType;
import mage.constants.PhaseStep;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.permanent.Permanent;
import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@@ -90,7 +93,7 @@ public class BloodMoonTest extends CardTestPlayerBase {
* Spreading Seas was played turn 3 in a Steam Vents, Blood Moon turn 7 or
* something
*
- * The enchanted Steam Vents was producing only U when ir should produce
+ * The enchanted Steam Vents was producing only U when it should produce
* only R because of blood moon's time stamp.
*
* http://blogs.magicjudges.org/articles/2013/06/18/blood-moon-in-a-modern-environment/
@@ -238,4 +241,167 @@ public class BloodMoonTest extends CardTestPlayerBase {
Assert.assertTrue("The mana the land can produce should be [{R}] but it's " + playerA.getManaAvailable(currentGame).toString(), playerA.getManaAvailable(currentGame).toString().equals("[{R}]"));
}
+
+ /**
+ * If Blood Moon enters the battlefield with an animated Mutavault in play,
+ * the Mutavault stays a 2/2 creature with all creature types and “gains”
+ * the land type mountain (it can also tap for R). However, once the turn
+ * ends, the Mutavault will loses both of its abilities and become a non
+ * basic mountain named Mutavault.
+ */
+ @Test
+ public void testBloodMoonMutavault() {
+
+ addCard(Zone.BATTLEFIELD, playerA, "Swamp");
+
+ // {T}: Add {C} to your mana pool.
+ // {1}: Mutavault becomes a 2/2 creature with all creature types until end of turn. It's still a land.
+ addCard(Zone.BATTLEFIELD, playerA, "Mutavault", 1);
+
+ // Blood Moon 2R
+ // Enchantment
+ // Nonbasic lands are Mountains
+ addCard(Zone.HAND, playerB, "Blood Moon", 1);
+ addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3);
+
+ activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}: ");
+
+ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Blood Moon");
+
+ setStopAt(2, PhaseStep.END_TURN);
+
+ execute();
+
+ assertPermanentCount(playerB, "Blood Moon", 1);
+ assertPowerToughness(playerA, "Mutavault", 2, 2);
+ assertType("Mutavault", CardType.LAND, SubType.MOUNTAIN);
+ assertType("Swamp", CardType.LAND, SubType.SWAMP);
+
+ Assert.assertTrue("The mana the land can produce should be [{R}] but it's " + playerA.getManaAvailable(currentGame).toString(), playerA.getManaAvailable(currentGame).toString().equals("[{R}]"));
+ }
+
+ @Test
+ public void testBloodMoonMutavaultEnd() {
+
+ addCard(Zone.BATTLEFIELD, playerA, "Swamp");
+
+ // {T}: Add {C} to your mana pool.
+ // {1}: Mutavault becomes a 2/2 creature with all creature types until end of turn. It's still a land.
+ addCard(Zone.BATTLEFIELD, playerA, "Mutavault", 1);
+
+ // Blood Moon 2R
+ // Enchantment
+ // Nonbasic lands are Mountains
+ addCard(Zone.HAND, playerB, "Blood Moon", 1);
+ addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3);
+
+ activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}: ");
+
+ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Blood Moon");
+
+ setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
+
+ execute();
+
+ assertPermanentCount(playerB, "Blood Moon", 1);
+ assertPowerToughness(playerA, "Mutavault", 0, 0);
+ assertType("Mutavault", CardType.LAND, SubType.MOUNTAIN);
+ assertType("Swamp", CardType.LAND, SubType.SWAMP);
+
+ Assert.assertTrue("The mana the lands can produce should be [{B}{R}] but it's " + playerA.getManaAvailable(currentGame).toString(), playerA.getManaAvailable(currentGame).toString().equals("[{B}{R}]"));
+ }
+
+ /**
+ * If Blood Moon is on the battlefield, Flagstones of Trokair will enter the
+ * battlefield as a legendary non-basic Mountain. If Flagstones of Trokair
+ * is put into the graveyard due to “Legends rule” or because it was
+ * destroyed, its ability doesn’t trigger, because it doesn’t exist: it
+ * won’t fetch you a Plains.
+ */
+ @Test
+ public void testBloodMoonFlagstonesOfTrokair() {
+ // {T}: Add {W} to your mana pool.
+ // When Flagstones of Trokair is put into a graveyard from the battlefield, you may search
+ // your library for a Plains card and put it onto the battlefield tapped. If you do, shuffle your library.
+ addCard(Zone.HAND, playerA, "Flagstones of Trokair", 1);
+ addCard(Zone.LIBRARY, playerA, "Plains");
+
+ // Blood Moon 2R
+ // Enchantment
+ // Nonbasic lands are Mountains
+ addCard(Zone.BATTLEFIELD, playerB, "Blood Moon");
+ addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3);
+ addCard(Zone.HAND, playerB, "Stone Rain");
+
+ playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flagstones of Trokair");
+ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Stone Rain", "Flagstones of Trokair");
+
+ setStopAt(2, PhaseStep.BEGIN_COMBAT);
+
+ execute();
+
+ assertPermanentCount(playerB, "Blood Moon", 1);
+ assertGraveyardCount(playerB, "Stone Rain", 1);
+
+ assertPermanentCount(playerA, "Flagstones of Trokair", 0);
+ assertGraveyardCount(playerA, "Flagstones of Trokair", 1);
+
+ assertPermanentCount(playerA, 0);
+ }
+
+ /**
+ * Because Blood Moon’s static ability operates only when it’s on the
+ * battlefield and begins affecting any nonbasic lands immediately. In fact,
+ * Blood Moon’s effect is so quick that once a non-basic land hits the
+ * battlefield it’s going to be affected. Therefore:
+ *
+ * If a nonbasic land’s has EtB triggered abilities, these will not trigger
+ * because the ability isn’t there (it’s gone). Effects that modify the way
+ * the land enters the battlefield are replacement effects. They are applied
+ * before the permanent enters the battlefield and taking into account
+ * continuous effects that already exist and would apply to the permanent.
+ * (see CR 614.12).
+ *
+ * 614.12 Some replacement effects modify how a permanent enters the
+ * battlefield. (See rules 614.1c-d.) Such effects may come from the
+ * permanent itself if they affect only that permanent (as opposed to a
+ * general subset of permanents that includes it). They may also come from
+ * other sources. To determine which replacement effects apply and how they
+ * apply, check the characteristics of the permanent as it would exist on
+ * the battlefield, taking into account replacement effects that have
+ * already modified how it enters the battlefield (see rule 616.1),
+ * continuous effects from the permanent's own static abilities that would
+ * apply to it once it's on the battlefield, and continuous effects that
+ * ..........................................===========================
+ * already exist and would apply to the permanent.
+ * ================================================
+ *
+ * Madblind Mountain enters the battlefield untapped, as a nonbasic Mountain
+ * with single mana ability and no other.
+ */
+ @Test
+ @Ignore
+ public void testBloodMoonMadblindMountain() {
+ // {T}: Add {R} to your mana pool.
+ // Madblind Mountain enters the battlefield tapped.
+ // {R}, {tap}: Shuffle your library. Activate this ability only if you control two or more red permanents.
+ addCard(Zone.HAND, playerA, "Madblind Mountain", 1);
+
+ // Blood Moon 2R
+ // Enchantment
+ // Nonbasic lands are Mountains
+ addCard(Zone.BATTLEFIELD, playerB, "Blood Moon");
+
+ playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Madblind Mountain");
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+
+ execute();
+
+ assertPermanentCount(playerB, "Blood Moon", 1);
+ assertPermanentCount(playerA, "Madblind Mountain", 1);
+
+ assertTapped("Madblind Mountain", false); // it may not be tapped because the etB effect was removed by Blood Moon
+
+ }
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FlashbackTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FlashbackTest.java
index 30f0d24fb93..02bf64326b3 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FlashbackTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/FlashbackTest.java
@@ -27,9 +27,9 @@
*/
package org.mage.test.cards.abilities.keywords;
+import mage.abilities.keyword.TrampleAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
-import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@@ -39,6 +39,27 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*/
public class FlashbackTest extends CardTestPlayerBase {
+ @Test
+ public void testNormalWildHunger() {
+
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
+
+ // Target creature gets +3/+1 and gains trample until end of turn.
+ // Flashback {3}{R}
+ addCard(Zone.GRAVEYARD, playerA, "Wild Hunger");
+
+ addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flashback", "Silvercoat Lion");
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertPowerToughness(playerA, "Silvercoat Lion", 5, 3);
+ assertAbility(playerA, "Silvercoat Lion", TrampleAbility.getInstance(), true);
+ assertExileCount("Wild Hunger", 1);
+ }
+
/**
* Fracturing Gust is bugged. In a match against Affinity, it worked
* properly when cast from hand. When I cast it from graveyard c/o
@@ -219,7 +240,7 @@ public class FlashbackTest extends CardTestPlayerBase {
// Conflagrate deals X damage divided as you choose among any number of target creatures and/or players.
// Flashback-{R}{R}, Discard X cards.
- addCard(Zone.HAND, playerA, "Conflagrate", 1);
+ addCard(Zone.HAND, playerA, "Conflagrate", 1); // Sorcery {X}{X}{R}
addCard(Zone.HAND, playerA, "Forest", 4);
@@ -307,20 +328,26 @@ public class FlashbackTest extends CardTestPlayerBase {
public void testAltarsReap() {
addCard(Zone.LIBRARY, playerA, "Island", 2);
- addCard(Zone.GRAVEYARD, playerA, "Altar's Reap", 1);
+ // As an additional cost to cast Altar's Reap, sacrifice a creature.
+ // Draw two cards.
+ addCard(Zone.GRAVEYARD, playerA, "Altar's Reap", 1); // Instant {1}{B}
addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 4);
addCard(Zone.HAND, playerA, "Snapcaster Mage", 1);
+ // Flash
+ // When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn.
+ // The flashback cost is equal to its mana cost.
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Altar's Reap");
- activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback {1}{B}");
+ activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback");
setChoice(playerA, "Snapcaster Mage");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, "Snapcaster Mage", 1);
+ assertExileCount(playerA, "Altar's Reap", 1);
}
/**
@@ -520,7 +547,6 @@ public class FlashbackTest extends CardTestPlayerBase {
* to a spell, and the flashback cost is already an alternative cost.
*/
@Test
- @Ignore
public void testSnapcasterMageSpellWithAlternateCost() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/SpendOtherManaTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/SpendOtherManaTest.java
index a71cef7116f..76d22a2f123 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/SpendOtherManaTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/SpendOtherManaTest.java
@@ -134,4 +134,34 @@ public class SpendOtherManaTest extends CardTestPlayerBase {
assertHandCount(playerA, "Nissa, Voice of Zendikar", 0);
assertPermanentCount(playerA, "Nissa, Voice of Zendikar", 1);
}
+
+ @Test
+ public void testUseSpendManaAsThoughWithManaFromPool() {
+ addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
+
+ addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // Creature {1}{W}
+
+ // When Hostage Taker enters the battlefield, exile another target artifact or creature until Hostage Taker leaves the battlefield.
+ // You may cast that card as long as it remains exiled, and you may spend mana as though it were mana of any type to cast that spell.
+ addCard(Zone.HAND, playerA, "Hostage Taker"); // {2}{U}{B}
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hostage Taker");
+ setChoice(playerA, "Silvercoat Lion");
+
+ activateManaAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: Add {R} to your mana pool."); // red mana to pool
+ activateManaAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}: Add {R} to your mana pool."); // red mana to pool
+ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Silvercoat Lion"); // cast it from exile with red mana from pool
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+
+ assertPermanentCount(playerA, "Hostage Taker", 1);
+ assertTappedCount("Mountain", true, 4);
+
+ assertPermanentCount(playerA, "Silvercoat Lion", 1);
+
+ }
+
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java
index 83697190404..b695a681ac4 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java
@@ -118,11 +118,11 @@ public class IsochronScepterTest extends CardTestPlayerBase {
public void testAngelsGrace() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.HAND, playerA, "Isochron Scepter");
+
// Split second (As long as this spell is on the stack, players can't cast spells or activate abilities that aren't mana abilities.)
// You can't lose the game this turn and your opponents can't win the game this turn.
// Until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead.
-
- addCard(Zone.HAND, playerA, "Angel's Grace");
+ addCard(Zone.HAND, playerA, "Angel's Grace"); // Instant {W}
addCard(Zone.BATTLEFIELD, playerB, "Dross Crocodile", 4);// 5/1
addCard(Zone.HAND, playerB, "Lightning Bolt", 2);
@@ -149,9 +149,6 @@ public class IsochronScepterTest extends CardTestPlayerBase {
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
- assertExileCount("Angel's Grace", 1);
- assertGraveyardCount(playerA, "Angel's Grace", 0);
-
assertLife(playerA, 1);
assertLife(playerB, 20);
@@ -160,6 +157,9 @@ public class IsochronScepterTest extends CardTestPlayerBase {
assertPermanentCount(playerB, "Dross Crocodile", 3);
assertPermanentCount(playerA, "Isochron Scepter", 1);
+ assertExileCount("Angel's Grace", 1);
+ assertGraveyardCount(playerA, "Angel's Grace", 0);
+
}
/**
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java
index b708a3d6c9a..73f7b9eacb9 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java
@@ -111,4 +111,47 @@ public class MimicVatTest extends CardTestPlayerBase {
}
+ /**
+ * Player A has Mimic Vat and plays Sidisi, Undead Vizier and exploits.
+ * Player N responds to Mimic Vat Trigger with Shred Memory, exiling Sidisi.
+ * Sidisi gets exiled but then xmage allows player A to imprint the
+ * creature, which shouldn't be possible.
+ */
+ @Test
+ public void TestExileFails() {
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
+ // Imprint - Whenever a nontoken creature dies, you may exile that card. If you do, return each other card exiled with Mimic Vat to its owner's graveyard.
+ // {3}, {T}: Create a token that's a copy of a card exiled with Mimic Vat. It gains haste. Exile it at the beginning of the next end step.
+ addCard(Zone.BATTLEFIELD, playerA, "Mimic Vat", 1); // Artifact {3}
+
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
+
+ addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
+ // Exile up to four target cards from a single graveyard.
+ // Transmute {1}{B}{B}
+ addCard(Zone.HAND, playerB, "Shred Memory", 1); // Instant {1}{B}
+
+ addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion");
+ setChoice(playerA, "Yes");
+ setChoice(playerA, "Silvercoat Lion");
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Shred Memory", "Silvercoat Lion", "Whenever a nontoken creature dies");
+ setChoice(playerA, "Yes");
+
+ activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}, {T}: Create a token that's a copy of a card exiled with ");
+ setChoice(playerA, "Yes");
+ setChoice(playerA, "Silvercoat Lion");
+
+ setStopAt(3, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertGraveyardCount(playerA, "Lightning Bolt", 1);
+ assertGraveyardCount(playerB, "Shred Memory", 1);
+
+ assertExileCount(playerB, "Silvercoat Lion", 1);
+ assertPermanentCount(playerA, "Silvercoat Lion", 0);
+
+ }
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/SpreadingSeasTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/SpreadingSeasTest.java
index c44ce2e37d3..f5528bbe33e 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/SpreadingSeasTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/SpreadingSeasTest.java
@@ -86,12 +86,12 @@ public class SpreadingSeasTest extends CardTestPlayerBase {
}
@Test
- public void testUtopiaSprawlWithSpreadingSeas(){
+ public void testUtopiaSprawlWithSpreadingSeas() {
addCard(Zone.HAND, playerA, "Spreading Seas", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 10);
addCard(Zone.HAND, playerA, "Utopia Sprawl");
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Utopia Sprawl","Forest");
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Utopia Sprawl", "Forest");
setChoice(playerA, "Green");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spreading Seas", "Forest");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
@@ -99,9 +99,8 @@ public class SpreadingSeasTest extends CardTestPlayerBase {
assertNotSubtype("Forest", SubType.FOREST);
}
-
@Test
- public void testSpreadingSeasWithUrzaLand(){
+ public void testSpreadingSeasWithUrzaLand() {
addCard(Zone.HAND, playerA, "Spreading Seas", 1);
addCard(Zone.BATTLEFIELD, playerA, "Urza's Tower", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 10);
@@ -111,4 +110,40 @@ public class SpreadingSeasTest extends CardTestPlayerBase {
assertNotSubtype("Urza's Tower", SubType.URZAS);
assertNotSubtype("Urza's Tower", SubType.TOWER);
}
+
+ /**
+ * https://github.com/magefree/mage/issues/4529 Some spell effects that
+ * effect the use of mana abilities on lands are inoperative. Example
+ * Spreading Seas transforms enchanted land into an island and it loses all
+ * other abilities. The AI does not recognize this and is able to use all
+ * abilities of the enchanted land including all previous mana abilities and
+ * activated abilities, in addition to now also being an island due to
+ * Spreading Sea's effect.
+ */
+ @Test
+ public void testSpreadingRemovesOtherAbilities() {
+
+ // Enchant land
+ // When Spreading Seas enters the battlefield, draw a card.
+ // Enchanted land is an Island.
+ addCard(Zone.HAND, playerA, "Spreading Seas", 1); // ENCHANTMENT {1}{U}
+ addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
+
+ // {T}: Add {C} to your mana pool.
+ // {1}{R}, {T}: Create a 0/1 red Kobold creature token named Kobolds of Kher Keep.
+ addCard(Zone.BATTLEFIELD, playerB, "Kher Keep", 1);
+ addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spreading Seas", "Kher Keep");
+ activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{1}{R}"); // Ability should not be available
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+
+ assertPermanentCount(playerA, "Spreading Seas", 1);
+
+ assertPermanentCount(playerB, "Kobolds of Kher Keep", 0);
+ assertTapped("Kher Keep", false);
+ }
+
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/TorporOrbTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/TorporOrbTest.java
index c8694f3540b..36b5edb5309 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/TorporOrbTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/TorporOrbTest.java
@@ -41,7 +41,8 @@ public class TorporOrbTest extends CardTestPlayerBase {
*/
@Test
public void testPitTweller() {
- addCard(Zone.BATTLEFIELD, playerB, "Torpor Orb");
+ // Creatures entering the battlefield don't cause abilities to trigger.
+ addCard(Zone.BATTLEFIELD, playerB, "Hushwing Gryff");
addCard(Zone.BATTLEFIELD, playerB, "Treacherous Pit-Dweller"); // 4/3
addCard(Zone.HAND, playerA, "Lightning Bolt");
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lrw/CairnWandererTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lrw/CairnWandererTest.java
index 2f3e6851fe3..6f96643b134 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/single/lrw/CairnWandererTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lrw/CairnWandererTest.java
@@ -80,28 +80,28 @@ public class CairnWandererTest extends CardTestPlayerBase {
addCard(Zone.GRAVEYARD, playerA, "Typhoid Rats");
// Testing HasteAbility.
- addCard(Zone.GRAVEYARD, playerA, "Raging Goblin");
+ addCard(Zone.GRAVEYARD, playerB, "Raging Goblin");
// Testing LandwalkAbility.
- addCard(Zone.GRAVEYARD, playerA, "Zodiac Rooster");
+ addCard(Zone.GRAVEYARD, playerB, "Zodiac Rooster");
// Testing LifelinkAbility.
- addCard(Zone.GRAVEYARD, playerA, "Trained Caracal");
+ addCard(Zone.GRAVEYARD, playerB, "Trained Caracal");
// Testing ProtectionAbility.
- addCard(Zone.GRAVEYARD, playerA, "Progenitus");
+ addCard(Zone.GRAVEYARD, playerB, "Progenitus");
// Testing ReachAbility.
- addCard(Zone.GRAVEYARD, playerA, "Tree Monkey");
+ addCard(Zone.GRAVEYARD, playerB, "Tree Monkey");
// Testing TrampleAbility.
- addCard(Zone.GRAVEYARD, playerA, "Defiant Elf");
+ addCard(Zone.GRAVEYARD, playerB, "Defiant Elf");
// Testing ShroudAbility.
- addCard(Zone.GRAVEYARD, playerA, "Elvish Lookout");
+ addCard(Zone.GRAVEYARD, playerB, "Elvish Lookout");
// Testing VigilanceAbility.
- addCard(Zone.GRAVEYARD, playerA, "Veteran Cavalier");
+ addCard(Zone.GRAVEYARD, playerB, "Veteran Cavalier");
execute();
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/DefiantVanguardTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/DefiantVanguardTest.java
new file mode 100644
index 00000000000..dc4b99e66fc
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/DefiantVanguardTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package org.mage.test.cards.triggers;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class DefiantVanguardTest extends CardTestPlayerBase {
+
+ @Test
+ public void testAllDestroyed() {
+ // When Defiant Vanguard blocks, at end of combat, destroy it and all creatures it blocked this turn.
+ // {5}, {tap}: Search your library for a Rebel permanent card with converted mana cost 4 or less and put it onto the battlefield. Then shuffle your library.
+ addCard(Zone.BATTLEFIELD, playerA, "Defiant Vanguard", 1); // Creature {2}{W} 2/2
+
+ addCard(Zone.BATTLEFIELD, playerB, "Bane Alley Blackguard", 1); // Creature {1}{B} 1/3
+
+ attack(2, playerB, "Bane Alley Blackguard");
+ block(2, playerA, "Defiant Vanguard", "Bane Alley Blackguard");
+
+ setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertGraveyardCount(playerA, "Defiant Vanguard", 1);
+ assertGraveyardCount(playerB, "Bane Alley Blackguard", 1);
+ }
+
+ @Test
+ public void testSaveCreatureWithCloudshift() {
+ // When Defiant Vanguard blocks, at end of combat, destroy it and all creatures it blocked this turn.
+ // {5}, {tap}: Search your library for a Rebel permanent card with converted mana cost 4 or less and put it onto the battlefield. Then shuffle your library.
+ addCard(Zone.BATTLEFIELD, playerA, "Defiant Vanguard", 1); // Creature {2}{W} 2/2
+
+ addCard(Zone.BATTLEFIELD, playerB, "Bane Alley Blackguard", 1); // Creature {1}{B} 1/3
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 1);
+ // Exile target creature you control, then return that card to the battlefield under your control.
+ addCard(Zone.HAND, playerB, "Cloudshift", 1); // Instant {W}
+
+ attack(2, playerB, "Bane Alley Blackguard");
+ block(2, playerA, "Defiant Vanguard", "Bane Alley Blackguard");
+
+ castSpell(2, PhaseStep.END_COMBAT, playerB, "Cloudshift", "Bane Alley Blackguard", "At end of combat, destroy it and all creatures it blocked this turn.");
+
+ setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertGraveyardCount(playerA, "Defiant Vanguard", 1);
+ assertGraveyardCount(playerB, "Cloudshift", 1);
+ assertPermanentCount(playerB, "Bane Alley Blackguard", 1);
+
+ }
+
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
index 417fc5a46d3..41d0c95c6de 100644
--- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
+++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
@@ -740,7 +740,7 @@ public class TestPlayer implements Player {
@Override
public boolean choose(Outcome outcome, Choice choice, Game game) {
if (!choices.isEmpty()) {
- if(choice.setChoiceByAnswers(choices, true)){
+ if (choice.setChoiceByAnswers(choices, true)) {
return true;
}
}
@@ -2167,6 +2167,24 @@ public class TestPlayer implements Player {
@Override
public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
+ switch (ability.getSpellAbilityType()) {
+ case SPLIT:
+ case SPLIT_FUSED:
+ case SPLIT_AFTERMATH:
+ if (!choices.isEmpty()) {
+ MageObject object = game.getObject(ability.getSourceId());
+ if (object != null) {
+ LinkedHashMap useableAbilities = computerPlayer.getSpellAbilities(object, game.getState().getZone(object.getId()), game);
+ for (String choose : choices) {
+ for (ActivatedAbility actiavtedAbility : useableAbilities.values()) {
+ if (actiavtedAbility.getRule().startsWith(choose)) {
+ return (SpellAbility) actiavtedAbility;
+ }
+ }
+ }
+ }
+ }
+ }
return computerPlayer.chooseSpellAbilityForCast(ability, game, noMana);
}
@@ -2176,13 +2194,17 @@ public class TestPlayer implements Player {
}
@Override
- public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
+ public boolean choose(Outcome outcome, Target target,
+ UUID sourceId, Game game
+ ) {
// needed to call here the TestPlayer because it's overwitten
return choose(outcome, target, sourceId, game, null);
}
@Override
- public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) {
+ public boolean choose(Outcome outcome, Cards cards,
+ TargetCard target, Game game
+ ) {
if (!choices.isEmpty()) {
for (String choose2 : choices) {
// TODO: More targetting to fix
@@ -2212,58 +2234,78 @@ public class TestPlayer implements Player {
}
@Override
- public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
+ public boolean chooseTargetAmount(Outcome outcome, TargetAmount target,
+ Ability source, Game game
+ ) {
return computerPlayer.chooseTargetAmount(outcome, target, source, game);
}
@Override
- public boolean chooseMulligan(Game game) {
+ public boolean chooseMulligan(Game game
+ ) {
return computerPlayer.chooseMulligan(game);
}
@Override
- public boolean choosePile(Outcome outcome, String message, List extends Card> pile1, List extends Card> pile2, Game game) {
+ public boolean choosePile(Outcome outcome, String message,
+ List extends Card> pile1, List extends Card> pile2,
+ Game game
+ ) {
return computerPlayer.choosePile(outcome, message, pile1, pile2, game);
}
@Override
- public boolean playMana(Ability ability, ManaCost unpaid, String promptText, Game game) {
+ public boolean playMana(Ability ability, ManaCost unpaid,
+ String promptText, Game game
+ ) {
groupsForTargetHandling = null;
return computerPlayer.playMana(ability, unpaid, promptText, game);
}
@Override
- public UUID chooseAttackerOrder(List attacker, Game game) {
+ public UUID chooseAttackerOrder(List attacker, Game game
+ ) {
return computerPlayer.chooseAttackerOrder(attacker, game);
}
@Override
- public UUID chooseBlockerOrder(List blockers, CombatGroup combatGroup, List blockerOrder, Game game) {
+ public UUID chooseBlockerOrder(List blockers, CombatGroup combatGroup,
+ List blockerOrder, Game game
+ ) {
return computerPlayer.chooseBlockerOrder(blockers, combatGroup, blockerOrder, game);
}
@Override
- public void assignDamage(int damage, List targets, String singleTargetName, UUID sourceId, Game game) {
+ public void assignDamage(int damage, List targets,
+ String singleTargetName, UUID sourceId,
+ Game game
+ ) {
computerPlayer.assignDamage(damage, targets, singleTargetName, sourceId, game);
}
@Override
- public void sideboard(Match match, Deck deck) {
+ public void sideboard(Match match, Deck deck
+ ) {
computerPlayer.sideboard(match, deck);
}
@Override
- public void construct(Tournament tournament, Deck deck) {
+ public void construct(Tournament tournament, Deck deck
+ ) {
computerPlayer.construct(tournament, deck);
}
@Override
- public void pickCard(List cards, Deck deck, Draft draft) {
+ public void pickCard(List cards, Deck deck,
+ Draft draft
+ ) {
computerPlayer.pickCard(cards, deck, draft);
}
@Override
- public boolean scry(int value, Ability source, Game game) {
+ public boolean scry(int value, Ability source,
+ Game game
+ ) {
// Don't scry at the start of the game.
if (game.getTurnNum() == 1 && game.getStep() == null) {
return false;
@@ -2272,37 +2314,51 @@ public class TestPlayer implements Player {
}
@Override
- public boolean moveCards(Card card, Zone toZone, Ability source, Game game) {
+ public boolean moveCards(Card card, Zone toZone,
+ Ability source, Game game
+ ) {
return computerPlayer.moveCards(card, toZone, source, game);
}
@Override
- public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects) {
+ public boolean moveCards(Card card, Zone toZone,
+ Ability source, Game game,
+ boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects
+ ) {
return computerPlayer.moveCards(card, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
}
@Override
- public boolean moveCards(Cards cards, Zone toZone, Ability source, Game game) {
+ public boolean moveCards(Cards cards, Zone toZone,
+ Ability source, Game game
+ ) {
return computerPlayer.moveCards(cards, toZone, source, game);
}
@Override
- public boolean moveCards(Set cards, Zone toZone, Ability source, Game game) {
+ public boolean moveCards(Set cards, Zone toZone,
+ Ability source, Game game
+ ) {
return computerPlayer.moveCards(cards, toZone, source, game);
}
@Override
- public boolean moveCards(Set cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects) {
+ public boolean moveCards(Set cards, Zone toZone,
+ Ability source, Game game,
+ boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects
+ ) {
return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
}
@Override
- public boolean hasDesignation(DesignationType designationName) {
+ public boolean hasDesignation(DesignationType designationName
+ ) {
return computerPlayer.hasDesignation(designationName);
}
@Override
- public void addDesignation(Designation designation) {
+ public void addDesignation(Designation designation
+ ) {
computerPlayer.addDesignation(designation);
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/deck/DeckValidatorTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/deck/DeckValidatorTest.java
index f7bf2fe462e..38d002d5240 100644
--- a/Mage.Tests/src/test/java/org/mage/test/serverside/deck/DeckValidatorTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/deck/DeckValidatorTest.java
@@ -27,24 +27,24 @@
*/
package org.mage.test.serverside.deck;
+import java.util.ArrayList;
+import java.util.List;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckValidator;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.deck.Limited;
import mage.deck.Modern;
+import mage.deck.Standard;
import org.junit.Assert;
import org.junit.Test;
-import org.mage.test.serverside.base.CardTestPlayerBase;
-
-import java.util.ArrayList;
-import java.util.List;
+import org.mage.test.serverside.base.MageTestBase;
/**
*
* @author LevelX2
*/
-public class DeckValidatorTest extends CardTestPlayerBase {
+public class DeckValidatorTest extends MageTestBase {
static class CardNameAmount {
@@ -84,6 +84,38 @@ public class DeckValidatorTest extends CardTestPlayerBase {
}
+ @Test
+ public void testStandardValid() {
+ ArrayList deck = new ArrayList<>();
+
+ deck.add(new CardNameAmount("MPS-AKH", 28, 4)); // Rhonas the Indomitable
+ deck.add(new CardNameAmount("Built to Smash", 4));
+ deck.add(new CardNameAmount("Heroic Intervention", 4));
+ deck.add(new CardNameAmount("Mountain", 48));
+
+ DeckValidator validator = new Standard();
+ boolean validationSuccessful = testDeckValid(validator, deck);
+ Assert.assertTrue(validator.getInvalid().toString(), validationSuccessful);
+ }
+
+ @Test
+ public void testStandardNotValid() {
+ ArrayList deck = new ArrayList<>();
+
+ deck.add(new CardNameAmount("MPS-AKH", 28, 4)); // Rhonas the Indomitable
+ deck.add(new CardNameAmount("Built to Smash", 4));
+ deck.add(new CardNameAmount("Heroic Intervention", 4));
+ deck.add(new CardNameAmount("Mountain", 47));
+
+ ArrayList sideboard = new ArrayList<>();
+ sideboard.add(new CardNameAmount("Mountain", 16));
+
+ DeckValidator validator = new Standard();
+ testDeckValid(validator, deck, sideboard);
+ Assert.assertEquals("invalid message not correct",
+ "{Sideboard=Must contain no more than 15 cards : has 16 cards, Deck=Must contain at least 60 cards: has only 59 cards}", validator.getInvalid().toString());
+ }
+
@Test
public void testLimitedValid() {
ArrayList deck = new ArrayList<>();
@@ -226,37 +258,156 @@ public class DeckValidatorTest extends CardTestPlayerBase {
@Test
public void testModernBanned() {
ArrayList deckList = new ArrayList<>();
+ DeckValidator validator = new Modern();
+
deckList.add(new CardNameAmount("Ancestral Vision", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ boolean validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertTrue(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Ancient Den", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
deckList.add(new CardNameAmount("Birthing Pod", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Blazing Shoal", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Bloodbraid Elf", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertTrue(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Chrome Mox", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Cloudpost", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Dark Depths", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Deathrite Shaman", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Dig Through Time", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Dread Return", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Glimpse of Nature", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Great Furnace", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Green Sun's Zenith", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Hypergenesis", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Jace, the Mind Sculptor", 4));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertTrue(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
+
+ deckList.clear();
deckList.add(new CardNameAmount("Mental Misstep", 4));
- Assert.assertFalse("banned cards are not allowed", testDeckValid(new Modern(), deckList));
+ deckList.add(new CardNameAmount("Mountain", 56));
+ validationSuccessful = testDeckValid(validator, deckList);
+ Assert.assertFalse(validator.getInvalid().toString(), validationSuccessful);
+ validator.getInvalid().clear();
}
private boolean testDeckValid(DeckValidator validator, List cards) {
+ return testDeckValid(validator, cards, null);
+ }
+
+ private boolean testDeckValid(DeckValidator validator, List cards, List cardsSideboard) {
Deck deckToTest = new Deck();
- for (CardNameAmount cardNameAmount : cards) {
- CardInfo cardinfo;
- if (cardNameAmount.getName().isEmpty()) {
- cardinfo = CardRepository.instance.findCard(cardNameAmount.getSetCode(), cardNameAmount.getCardNumber());
- } else {
- cardinfo = CardRepository.instance.findCard(cardNameAmount.getName());
+ if (cards != null) {
+ for (CardNameAmount cardNameAmount : cards) {
+ CardInfo cardinfo;
+ if (cardNameAmount.getName().isEmpty()) {
+ cardinfo = CardRepository.instance.findCard(cardNameAmount.getSetCode(), cardNameAmount.getCardNumber());
+ } else {
+ cardinfo = CardRepository.instance.findCard(cardNameAmount.getName());
+ }
+ for (int i = 0; i < cardNameAmount.getNumber(); i++) {
+ deckToTest.getCards().add(cardinfo.getCard());
+ }
}
- for (int i = 0; i < cardNameAmount.getNumber(); i++) {
- deckToTest.getCards().add(cardinfo.getCard());
+ }
+ if (cardsSideboard != null) {
+ for (CardNameAmount cardNameAmount : cardsSideboard) {
+ CardInfo cardinfo;
+ if (cardNameAmount.getName().isEmpty()) {
+ cardinfo = CardRepository.instance.findCard(cardNameAmount.getSetCode(), cardNameAmount.getCardNumber());
+ } else {
+ cardinfo = CardRepository.instance.findCard(cardNameAmount.getName());
+ }
+ for (int i = 0; i < cardNameAmount.getNumber(); i++) {
+ deckToTest.getSideboard().add(cardinfo.getCard());
+ }
}
}
return validator.validate(deckToTest);
diff --git a/Mage/src/main/java/mage/MageObjectReference.java b/Mage/src/main/java/mage/MageObjectReference.java
index 0c4cde8808f..9fd237f7c87 100644
--- a/Mage/src/main/java/mage/MageObjectReference.java
+++ b/Mage/src/main/java/mage/MageObjectReference.java
@@ -47,7 +47,7 @@ public class MageObjectReference implements Comparable, Ser
private static final Logger logger = Logger.getLogger(MageObjectReference.class);
private final UUID sourceId;
- private int zoneChangeCounter;
+ private final int zoneChangeCounter;
public MageObjectReference(MageObject mageObject, Game game) {
this.sourceId = mageObject.getId();
@@ -167,8 +167,4 @@ public class MageObjectReference implements Comparable, Ser
}
return null;
}
-
- public void setZoneChangeCounter(int zoneChangeCounter) {
- this.zoneChangeCounter = zoneChangeCounter;
- }
}
diff --git a/Mage/src/main/java/mage/Mana.java b/Mage/src/main/java/mage/Mana.java
index b2461d2b367..0e9aaf28253 100644
--- a/Mage/src/main/java/mage/Mana.java
+++ b/Mage/src/main/java/mage/Mana.java
@@ -131,6 +131,35 @@ public class Mana implements Comparable, Serializable, Copyable {
}
}
+ public Mana(final ManaType manaType) {
+ Objects.requireNonNull(manaType, "The passed in ManaType can not be null");
+ switch (manaType) {
+ case GREEN:
+ green = 1;
+ break;
+ case RED:
+ red = 1;
+ break;
+ case BLACK:
+ black = 1;
+ break;
+ case BLUE:
+ blue = 1;
+ break;
+ case WHITE:
+ white = 1;
+ break;
+ case COLORLESS:
+ colorless = 1;
+ break;
+ case GENERIC:
+ generic = 1;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown manaType: " + manaType);
+ }
+ }
+
/**
* Creates a {@link Mana} object with the passed in {@code num} of Red mana.
* {@code num} can not be a negative value. Negative values will be logged
@@ -222,13 +251,12 @@ public class Mana implements Comparable, Serializable, Copyable {
}
/**
- * Creates a {@link Mana} object with the passed in {@code num} of Any
- * mana. {@code num} can not be a negative value. Negative values will be
- * logged and set to 0.
+ * Creates a {@link Mana} object with the passed in {@code num} of Any mana.
+ * {@code num} can not be a negative value. Negative values will be logged
+ * and set to 0.
*
* @param num value of Any mana to create.
- * @return a {@link Mana} object with the passed in {@code num} of Any
- * mana.
+ * @return a {@link Mana} object with the passed in {@code num} of Any mana.
*/
public static Mana AnyMana(int num) {
return new Mana(0, 0, 0, 0, 0, 0, notNegative(num, "Any"), 0);
diff --git a/Mage/src/main/java/mage/abilities/Ability.java b/Mage/src/main/java/mage/abilities/Ability.java
index d6baff95d43..d0a8f783aa9 100644
--- a/Mage/src/main/java/mage/abilities/Ability.java
+++ b/Mage/src/main/java/mage/abilities/Ability.java
@@ -45,6 +45,7 @@ import mage.constants.Zone;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.Targets;
@@ -535,6 +536,17 @@ public interface Ability extends Controllable, Serializable {
*/
MageObject getSourceObjectIfItStillExists(Game game);
+ /**
+ * Returns the permanent that actually existed while the ability triggerd or
+ * an ability was activated only if it has not changed zone meanwhile. If
+ * not set yet, the current permanent if one exists will be retrieved from
+ * the game and returned.
+ *
+ * @param game
+ * @return
+ */
+ Permanent getSourcePermanentIfItStillExists(Game game);
+
String getTargetDescription(Targets targets, Game game);
void setCanFizzle(boolean canFizzle);
diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java
index 8caf2db48c3..25528d242b6 100644
--- a/Mage/src/main/java/mage/abilities/AbilityImpl.java
+++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java
@@ -44,7 +44,6 @@ import mage.abilities.effects.Effects;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DynamicManaEffect;
import mage.abilities.effects.common.ManaEffect;
-import mage.abilities.keyword.FlashbackAbility;
import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.Card;
import mage.cards.SplitCard;
@@ -337,9 +336,7 @@ public abstract class AbilityImpl implements Ability {
if (sourceObject != null && this.getAbilityType() != AbilityType.TRIGGERED) { // triggered abilities check this already in playerImpl.triggerAbility
sourceObject.adjustTargets(this, game);
}
- // Flashback abilities haven't made the choices the underlying spell might need for targeting.
- if (!(this instanceof FlashbackAbility)
- && !getTargets().isEmpty()) {
+ if (!getTargets().isEmpty()) {
Outcome outcome = getEffects().isEmpty() ? Outcome.Detriment : getEffects().get(0).getOutcome();
if (getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game) == false) {
if ((variableManaCost != null || announceString != null)) {
@@ -445,8 +442,15 @@ public abstract class AbilityImpl implements Ability {
@Override
public boolean activateAlternateOrAdditionalCosts(MageObject sourceObject, boolean noMana, Player controller, Game game) {
+ if (this instanceof SpellAbility) {
+ if (((SpellAbility) this).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
+ // A player can't apply two alternative methods of casting or two alternative costs to a single spell.
+ // So can only use alternate costs if the spell is cast in normal mode
+ return false;
+ }
+ }
boolean alternativeCostisUsed = false;
- if (sourceObject != null && !(sourceObject instanceof Permanent) && !(this instanceof FlashbackAbility)) {
+ if (sourceObject != null && !(sourceObject instanceof Permanent)) {
Abilities abilities = null;
if (sourceObject instanceof Card) {
abilities = ((Card) sourceObject).getAbilities(game);
@@ -1207,6 +1211,19 @@ public abstract class AbilityImpl implements Ability {
return null;
}
+ @Override
+ public Permanent getSourcePermanentIfItStillExists(Game game) {
+ if (sourceObject == null) {
+ setSourceObject(game.getObject(getSourceId()), game);
+ }
+ if (sourceObject instanceof Permanent) {
+ if (game.getState().getZoneChangeCounter(getSourceId()) == getSourceObjectZoneChangeCounter()) {
+ return (Permanent) sourceObject;
+ }
+ }
+ return null;
+ }
+
@Override
public int getSourceObjectZoneChangeCounter() {
return sourceObjectZoneChangeCounter;
diff --git a/Mage/src/main/java/mage/abilities/SpellAbility.java b/Mage/src/main/java/mage/abilities/SpellAbility.java
index 2cd291a957a..289fa05592e 100644
--- a/Mage/src/main/java/mage/abilities/SpellAbility.java
+++ b/Mage/src/main/java/mage/abilities/SpellAbility.java
@@ -217,7 +217,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
this.name = "Cast fused " + cardName;
break;
default:
- this.name = "Cast " + cardName + (this.spellAbilityCastMode != SpellAbilityCastMode.NORMAL ? " by " + spellAbilityCastMode.toString() : "");
+ this.name = "Cast " + cardName + (this.spellAbilityCastMode != SpellAbilityCastMode.NORMAL ? " using " + spellAbilityCastMode.toString() : "");
}
}
@@ -230,4 +230,11 @@ public class SpellAbility extends ActivatedAbilityImpl {
setSpellName();
}
+ public SpellAbility getSpellAbilityToResolve(Game game) {
+ return this;
+ }
+
+ public void setId(UUID idToUse) {
+ this.id = idToUse;
+ }
}
diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbility.java b/Mage/src/main/java/mage/abilities/TriggeredAbility.java
index 638079c1e35..93ca77a32c5 100644
--- a/Mage/src/main/java/mage/abilities/TriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/TriggeredAbility.java
@@ -50,6 +50,17 @@ public interface TriggeredAbility extends Ability {
*/
boolean checkEventType(GameEvent event, Game game);
+ /**
+ * This method checks if the event has to trigger the ability. It's
+ * important to do nothing unique within this method, that can't be done
+ * multiple times. Because some abilities call this to check if an ability
+ * is relevant (e.g. Torpor Orb), so the method is calle dmultiple times for
+ * the same event.
+ *
+ * @param event
+ * @param game
+ * @return
+ */
boolean checkTrigger(GameEvent event, Game game);
boolean checkInterveningIfClause(Game game);
diff --git a/Mage/src/main/java/mage/abilities/costs/VariableCostImpl.java b/Mage/src/main/java/mage/abilities/costs/VariableCostImpl.java
index aefaf6f5269..6b96444bd20 100644
--- a/Mage/src/main/java/mage/abilities/costs/VariableCostImpl.java
+++ b/Mage/src/main/java/mage/abilities/costs/VariableCostImpl.java
@@ -29,7 +29,6 @@ package mage.abilities.costs;
import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.keyword.FlashbackAbility;
import mage.abilities.mana.ManaAbility;
import mage.game.Game;
import mage.game.stack.StackObject;
@@ -173,7 +172,6 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
StackObject stackObject = game.getStack().getStackObject(source.getId());
if (controller != null
&& (source instanceof ManaAbility
- || source instanceof FlashbackAbility
|| stackObject != null)) {
xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game),
"Announce the number of " + actionText, game, source, this);
diff --git a/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java b/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java
new file mode 100644
index 00000000000..44fa2a8a5e9
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/costs/common/PutCardFromHandOnTopOfLibraryCost.java
@@ -0,0 +1,60 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package mage.abilities.costs.common;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.costs.Cost;
+import mage.abilities.costs.CostImpl;
+import mage.cards.Card;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetCardInHand;
+
+/**
+ *
+ * @author jeffwadsworth
+ */
+
+public class PutCardFromHandOnTopOfLibraryCost extends CostImpl {
+
+ public PutCardFromHandOnTopOfLibraryCost() {
+ this.text = "Put a card from your hand on top of your library";
+ }
+
+ public PutCardFromHandOnTopOfLibraryCost(PutCardFromHandOnTopOfLibraryCost cost) {
+ super(cost);
+ }
+
+ @Override
+ public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
+ Player controller = game.getPlayer(controllerId);
+ TargetCardInHand targetCardInHand = new TargetCardInHand();
+ targetCardInHand.setRequired(false);
+ Card card;
+ if (targetCardInHand.canChoose(controllerId, game)
+ && controller.choose(Outcome.PreventDamage, targetCardInHand, sourceId, game)) {
+ card = game.getCard(targetCardInHand.getFirstTarget());
+ paid = controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.HAND, true, true);
+ }
+ return paid;
+ }
+
+ @Override
+ public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
+ Player controller = game.getPlayer(controllerId);
+ return (controller != null
+ && !controller.getHand().isEmpty());
+ }
+
+ @Override
+ public PutCardFromHandOnTopOfLibraryCost copy() {
+ return new PutCardFromHandOnTopOfLibraryCost(this);
+ }
+}
+
diff --git a/Mage/src/main/java/mage/abilities/costs/common/SacrificeAllCost.java b/Mage/src/main/java/mage/abilities/costs/common/SacrificeAllCost.java
index 88f5d8af975..a784838b8c9 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/SacrificeAllCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/SacrificeAllCost.java
@@ -55,19 +55,19 @@ public class SacrificeAllCost extends CostImpl {
public SacrificeAllCost(final SacrificeAllCost cost) {
super(cost);
- for (Permanent permanent: cost.permanents) {
- this.permanents.add(permanent.copy());
- }
+ this.permanents.addAll(cost.permanents); // because this are already copied permanents, they can't change, so no copy again is needed
this.filter = cost.filter.copy();
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) {
- permanents.add(permanent.copy());
- permanent.sacrifice(sourceId, game);
+ if (permanent.sacrifice(sourceId, game)) {
+ permanents.add(permanent.copy());
+ }
}
- return true;
+ paid = true;
+ return paid;
}
@Override
@@ -81,13 +81,13 @@ public class SacrificeAllCost extends CostImpl {
activator = controllerId;
}
}
-
- for (Permanent permanent :game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) {
- if(!game.getPlayer(activator).canPaySacrificeCost(permanent, sourceId, controllerId, game)) {
- return false;
- }
+
+ for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) {
+ if (!game.getPlayer(activator).canPaySacrificeCost(permanent, sourceId, controllerId, game)) {
+ return false;
+ }
}
-
+
return true;
}
diff --git a/Mage/src/main/java/mage/abilities/costs/common/TapTargetCost.java b/Mage/src/main/java/mage/abilities/costs/common/TapTargetCost.java
index ef095d353cc..82ed1c371fa 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/TapTargetCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/TapTargetCost.java
@@ -78,6 +78,10 @@ public class TapTargetCost extends CostImpl {
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
return target.canChoose(sourceId, controllerId, game);
}
+
+ public TargetControlledPermanent getTarget() {
+ return target;
+ }
@Override
public TapTargetCost copy() {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/CantBeRegeneratedTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CantBeRegeneratedTargetEffect.java
index a0219501fb8..d844803f730 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/CantBeRegeneratedTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/CantBeRegeneratedTargetEffect.java
@@ -81,7 +81,6 @@ public class CantBeRegeneratedTargetEffect extends ContinuousRuleModifyingEffect
}
sb.append(" can't be regenerated");
if (!duration.toString().isEmpty()) {
- sb.append(' ');
if (duration == Duration.EndOfTurn) {
sb.append(" this turn");
} else {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java
index 993422a0d4b..6bb2ce18c58 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenCopyTargetEffect.java
@@ -286,7 +286,7 @@ public class CreateTokenCopyTargetEffect extends OneShotEffect {
sb.append("tokens that are copies of target ");
}
if (!mode.getTargets().isEmpty()) {
- sb.append(mode.getTargets().get(0).getMessage());
+ sb.append(mode.getTargets().get(0).getTargetName());
} else {
throw new UnsupportedOperationException("Using default rule generation of target effect without having a target object");
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DetainAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DetainAllEffect.java
index 56005a87753..774304b6ea6 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/DetainAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/DetainAllEffect.java
@@ -24,19 +24,17 @@
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
-*/
-
+ */
package mage.abilities.effects.common;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-
-import mage.constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect;
import mage.constants.Duration;
+import mage.constants.Outcome;
import mage.constants.PhaseStep;
import mage.filter.FilterPermanent;
import mage.game.Game;
@@ -48,7 +46,6 @@ import mage.target.targetpointer.FixedTarget;
*
* @author LevelX2
*/
-
public class DetainAllEffect extends OneShotEffect {
private FilterPermanent filter = new FilterPermanent();
@@ -56,7 +53,7 @@ public class DetainAllEffect extends OneShotEffect {
public DetainAllEffect(FilterPermanent filter) {
super(Outcome.Benefit);
this.filter = filter;
- this.staticText = new StringBuilder("detain ").append(filter.getMessage()).toString();
+ this.staticText = "detain " + filter.getMessage();
}
public DetainAllEffect(final DetainAllEffect effect) {
@@ -73,10 +70,10 @@ public class DetainAllEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
List detainedObjects = new ArrayList<>();
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
- if (!game.isSimulation())
+ if (!game.isSimulation()) {
game.informPlayers("Detained permanent: " + permanent.getName());
- FixedTarget fixedTarget = new FixedTarget(permanent.getId());
- fixedTarget.init(game, source);
+ }
+ FixedTarget fixedTarget = new FixedTarget(permanent, game);
detainedObjects.add(fixedTarget);
}
@@ -103,23 +100,22 @@ class DetainAllRestrictionEffect extends RestrictionEffect {
@Override
public void init(Ability source, Game game) {
super.init(source, game);
- for(FixedTarget fixedTarget :this.detainedObjects) {
+ for (FixedTarget fixedTarget : this.detainedObjects) {
Permanent permanent = game.getPermanent(fixedTarget.getFirst(game, source));
if (permanent != null) {
- permanent.addInfo(new StringBuilder("detain").append(getId()).toString(),"[Detained]", game);
+ permanent.addInfo(new StringBuilder("detain").append(getId()).toString(), "[Detained]", game);
}
}
}
@Override
public boolean isInactive(Ability source, Game game) {
- if (game.getPhase().getStep().getType() == PhaseStep.UNTAP && game.getStep().getStepPart() == Step.StepPart.PRE)
- {
+ if (game.getPhase().getStep().getType() == PhaseStep.UNTAP && game.getStep().getStepPart() == Step.StepPart.PRE) {
if (game.getActivePlayerId().equals(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) {
- for(FixedTarget fixedTarget :this.detainedObjects) {
+ for (FixedTarget fixedTarget : this.detainedObjects) {
Permanent permanent = game.getPermanent(fixedTarget.getFirst(game, source));
if (permanent != null) {
- permanent.addInfo(new StringBuilder("detain").append(getId()).toString(),"", game);
+ permanent.addInfo(new StringBuilder("detain").append(getId()).toString(), "", game);
}
}
return true;
@@ -130,7 +126,7 @@ class DetainAllRestrictionEffect extends RestrictionEffect {
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
- for(FixedTarget fixedTarget :this.detainedObjects) {
+ for (FixedTarget fixedTarget : this.detainedObjects) {
UUID targetId = fixedTarget.getFirst(game, source);
if (targetId != null && targetId.equals(permanent.getId())) {
return true;
@@ -148,7 +144,7 @@ class DetainAllRestrictionEffect extends RestrictionEffect {
public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) {
return false;
}
-
+
@Override
public boolean canUseActivatedAbilities(Permanent permanent, Ability source, Game game) {
return false;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/DiscardsACardPlayerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/effects/common/DiscardsACardPlayerTriggeredAbility.java
new file mode 100644
index 00000000000..5c4ac7641cd
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/effects/common/DiscardsACardPlayerTriggeredAbility.java
@@ -0,0 +1,57 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package mage.abilities.effects.common;
+
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.effects.Effect;
+import mage.constants.SetTargetPointer;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+
+/**
+ *
+ * @author jeffwadsworth
+ */
+
+ public class DiscardsACardPlayerTriggeredAbility extends TriggeredAbilityImpl {
+
+ private SetTargetPointer setTargetPointer;
+
+ public DiscardsACardPlayerTriggeredAbility(Effect effect, boolean isOptional) {
+ this(effect, isOptional, SetTargetPointer.NONE);
+ }
+
+ public DiscardsACardPlayerTriggeredAbility(Effect effect, boolean isOptional, SetTargetPointer setTargetPointer) {
+ super(Zone.BATTLEFIELD, effect, isOptional);
+ this.setTargetPointer = setTargetPointer;
+ }
+
+ public DiscardsACardPlayerTriggeredAbility(final DiscardsACardPlayerTriggeredAbility ability) {
+ super(ability);
+ this.setTargetPointer = ability.setTargetPointer;
+ }
+
+ @Override
+ public DiscardsACardPlayerTriggeredAbility copy() {
+ return new DiscardsACardPlayerTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.DISCARDED_CARD;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ return true;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever player discards a card, " + super.getRule();
+ }
+}
\ No newline at end of file
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java
index e26affa441f..081cd81b8c8 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java
@@ -96,7 +96,7 @@ public class PreventDamageByTargetEffect extends PreventionEffectImpl {
StringBuilder sb = new StringBuilder();
sb.append("Prevent all");
if (onlyCombat) {
- sb.append(" combat ");
+ sb.append(" combat");
}
sb.append(" damage target ");
sb.append(mode.getTargets().get(0).getTargetName()).append(" would deal ").append(duration.toString());
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventNextDamageFromChosenSourceToYouEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventNextDamageFromChosenSourceToYouEffect.java
index 6164d9c2de3..86f10acf760 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PreventNextDamageFromChosenSourceToYouEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PreventNextDamageFromChosenSourceToYouEffect.java
@@ -71,7 +71,7 @@ public class PreventNextDamageFromChosenSourceToYouEffect extends PreventionEffe
StringBuilder sb = new StringBuilder("The next time a ").append(targetSource.getFilter().getMessage());
sb.append(" of your choice would deal damage to you");
if (duration == Duration.EndOfTurn) {
- sb.append(" this turn");
+ sb.append(" this turn");
}
sb.append(", prevent that damage");
return sb.toString();
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java
index 77ebb1377df..0a378703ab4 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PutTopCardOfLibraryIntoGraveEachPlayerEffect.java
@@ -123,9 +123,12 @@ public class PutTopCardOfLibraryIntoGraveEachPlayerEffect extends OneShotEffect
throw new UnsupportedOperationException("TargetController type not supported.");
}
sb.append("puts the top ");
- sb.append(CardUtil.numberToText(numberCards.toString(), "a"));
- sb.append(" card");
- sb.append(numberCards.toString().equals("1") ? "" : "s");
+ if(numberCards.toString().equals("1")) {
+ sb.append("card");
+ } else {
+ sb.append(CardUtil.numberToText(numberCards.toString()));
+ sb.append(" cards");
+ }
sb.append(" of his or her library into his or her graveyard");
return sb.toString();
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/RegenerateAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RegenerateAllEffect.java
index f224789f661..2482ff947f2 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/RegenerateAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/RegenerateAllEffect.java
@@ -63,7 +63,7 @@ public class RegenerateAllEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
RegenerateTargetEffect regenEffect = new RegenerateTargetEffect();
- regenEffect.setTargetPointer(new FixedTarget(permanent.getId()));
+ regenEffect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(regenEffect, source);
}
return true;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java
index 08ca0c506f2..ac2bee4e1da 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/TapAllTargetPlayerControlsEffect.java
@@ -80,6 +80,6 @@ public class TapAllTargetPlayerControlsEffect extends OneShotEffect {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
- return "tap all " + filter.toString() + " target " + mode.getTargets().get(0).getMessage() + " controls";
+ return "tap all " + filter.toString() + " target " + mode.getTargets().get(0).getTargetName() + " controls";
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByCreaturesAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByCreaturesAllEffect.java
index fa528cfcdf2..11dfb626a5e 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByCreaturesAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantBeBlockedByCreaturesAllEffect.java
@@ -45,7 +45,7 @@ public class CantBeBlockedByCreaturesAllEffect extends RestrictionEffect {
private final FilterCreaturePermanent filterCreatures;
public CantBeBlockedByCreaturesAllEffect(FilterCreaturePermanent filterCreatures, FilterCreaturePermanent filterBlockedBy, Duration duration) {
- super(Duration.WhileOnBattlefield);
+ super(duration);
this.filterCreatures = filterCreatures;
this.filterBlockedBy = filterBlockedBy;
staticText = new StringBuilder(filterCreatures.getMessage()).append(" can't be blocked ")
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesChosenCreatureTypeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesChosenCreatureTypeSourceEffect.java
index 56d90e8f218..4ee8f6462e4 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesChosenCreatureTypeSourceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesChosenCreatureTypeSourceEffect.java
@@ -3,6 +3,7 @@ package mage.abilities.effects.common.continuous;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
+import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
@@ -10,17 +11,28 @@ import mage.target.targetpointer.FixedTarget;
public class BecomesChosenCreatureTypeSourceEffect extends OneShotEffect {
+ private final boolean nonWall;
+ private final Duration duration;
+
public BecomesChosenCreatureTypeSourceEffect() {
- this(false);
+ this(false, Duration.EndOfTurn);
}
public BecomesChosenCreatureTypeSourceEffect(boolean nonWall) {
+ this(nonWall, Duration.EndOfTurn);
+ }
+
+ public BecomesChosenCreatureTypeSourceEffect(boolean nonWall, Duration duration) {
super(Outcome.BoostCreature);
- staticText = "{this} becomes the creature type of your choice until end of turn.";
+ this.nonWall = nonWall;
+ this.duration = duration;
+ staticText = "{this} becomes the creature type of your choice" + (duration == Duration.EndOfTurn ? " until end of turn." : "");
}
public BecomesChosenCreatureTypeSourceEffect(final BecomesChosenCreatureTypeSourceEffect effect) {
super(effect);
+ this.nonWall = effect.nonWall;
+ this.duration = effect.duration;
}
@Override
@@ -29,7 +41,7 @@ public class BecomesChosenCreatureTypeSourceEffect extends OneShotEffect {
if (sourcePerm == null) {
return false;
}
- Effect effect = new BecomesChosenCreatureTypeTargetEffect();
+ Effect effect = new BecomesChosenCreatureTypeTargetEffect(nonWall, duration);
effect.setTargetPointer(new FixedTarget(sourcePerm, game));
return effect.apply(game, source);
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesChosenCreatureTypeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesChosenCreatureTypeTargetEffect.java
index 982f160fb66..ef3759eaa90 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesChosenCreatureTypeTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesChosenCreatureTypeTargetEffect.java
@@ -17,17 +17,24 @@ import mage.target.targetpointer.FixedTarget;
public class BecomesChosenCreatureTypeTargetEffect extends OneShotEffect {
private final boolean nonWall;
+ private final Duration duration;
public BecomesChosenCreatureTypeTargetEffect() {
- this(false);
+ this(false, Duration.EndOfTurn);
}
public BecomesChosenCreatureTypeTargetEffect(boolean nonWall) {
+ this(nonWall, Duration.EndOfTurn);
+ }
+
+ public BecomesChosenCreatureTypeTargetEffect(boolean nonWall, Duration duration) {
super(Outcome.BoostCreature);
this.nonWall = nonWall;
- if (nonWall) {
+ this.duration = duration;
+ if(nonWall) {
staticText = "choose a creature type other than Wall. Target creature becomes that type until end of turn";
- } else {
+ }
+ else {
staticText = "target creature becomes the creature type of your choice until end of turn";
}
@@ -36,6 +43,7 @@ public class BecomesChosenCreatureTypeTargetEffect extends OneShotEffect {
public BecomesChosenCreatureTypeTargetEffect(final BecomesChosenCreatureTypeTargetEffect effect) {
super(effect);
this.nonWall = effect.nonWall;
+ this.duration = effect.duration;
}
@Override
@@ -46,21 +54,23 @@ public class BecomesChosenCreatureTypeTargetEffect extends OneShotEffect {
if (player != null && card != null) {
Choice typeChoice = new ChoiceCreatureType();
String msg = "Choose a creature type";
- if (nonWall) {
+ if(nonWall) {
msg += " other than Wall";
}
typeChoice.setMessage(msg);
- if (nonWall) {
+ if(nonWall) {
typeChoice.getChoices().remove(SubType.WALL.getDescription());
}
- if (!player.choose(Outcome.BoostCreature, typeChoice, game)) {
- return false;
+ while (!player.choose(Outcome.BoostCreature, typeChoice, game)) {
+ if (!player.canRespond()) {
+ return false;
+ }
}
game.informPlayers(card.getName() + ": " + player.getLogName() + " has chosen " + typeChoice.getChoice());
chosenType = typeChoice.getChoice();
if (chosenType != null && !chosenType.isEmpty()) {
// ADD TYPE TO TARGET
- ContinuousEffect effect = new BecomesCreatureTypeTargetEffect(Duration.EndOfTurn, SubType.byDescription(chosenType));
+ ContinuousEffect effect = new BecomesCreatureTypeTargetEffect(duration, SubType.byDescription(chosenType));
effect.setTargetPointer(new FixedTarget(getTargetPointer().getFirst(game, source)));
game.addEffect(effect, source);
return true;
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/MaximumHandSizeControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/MaximumHandSizeControllerEffect.java
index b3193d96699..cedfb9fcec1 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/MaximumHandSizeControllerEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/MaximumHandSizeControllerEffect.java
@@ -142,42 +142,50 @@ public class MaximumHandSizeControllerEffect extends ContinuousEffectImpl {
private void setText() {
StringBuilder sb = new StringBuilder();
- switch (targetController) {
- case ANY:
- if (handSize instanceof StaticValue && ((StaticValue) handSize).getValue() == Integer.MAX_VALUE) {
- sb.append("All players have no ");
- } else {
- sb.append("All players ");
- }
- break;
- case OPPONENT:
- if (handSize instanceof StaticValue && ((StaticValue) handSize).getValue() == Integer.MAX_VALUE) {
- sb.append("Each opponent has no ");
- } else {
- sb.append("Each opponent's ");
- }
- break;
- case YOU:
- if (handSize instanceof StaticValue && ((StaticValue) handSize).getValue() == Integer.MAX_VALUE) {
- sb.append("You have no ");
- } else {
- sb.append("Your ");
- }
- break;
- }
- sb.append("maximum hand size");
- if (handSizeModification == HandSizeModification.INCREASE) {
- sb.append(" is increased by ");
- } else if (handSizeModification == HandSizeModification.REDUCE) {
- sb.append(" is reduced by ");
- } else if (!((handSize instanceof StaticValue) && ((StaticValue) handSize).getValue() != Integer.MAX_VALUE) || !(handSize instanceof StaticValue)) {
- sb.append(" is ");
- }
- if ((handSize instanceof StaticValue && ((StaticValue) handSize).getValue() != Integer.MAX_VALUE)) {
- sb.append(CardUtil.numberToText(((StaticValue) handSize).getValue()));
- } else if (!(handSize instanceof StaticValue)) {
- sb.append(handSize.getMessage());
+ if(handSize instanceof StaticValue && ((StaticValue) handSize).getValue() == Integer.MAX_VALUE) {
+ switch (targetController) {
+ case ANY:
+ sb.append("Players have no maximum hand size");
+ break;
+ case OPPONENT:
+ sb.append("Each opponent has no maximum hand size");
+ break;
+ case YOU:
+ sb.append("You have no maximum hand size");
+ break;
+ }
+ } else {
+ switch (targetController) {
+ case ANY:
+ sb.append("All players maximum hand size");
+ break;
+ case OPPONENT:
+ sb.append("Each opponent's maximum hand size");
+ break;
+ case YOU:
+ sb.append("Your maximum hand size");
+ break;
+ }
+
+ switch (handSizeModification) {
+ case SET:
+ sb.append(" is ");
+ break;
+ case INCREASE:
+ sb.append(" is increased by ");
+ break;
+ case REDUCE:
+ sb.append(" is reduced by ");
+ break;
+ }
+
+ if (handSize instanceof StaticValue) {
+ sb.append(CardUtil.numberToText(((StaticValue) handSize).getValue()));
+ } else if (!(handSize instanceof StaticValue)) {
+ sb.append(handSize.getMessage());
+ }
}
+
if (duration == Duration.EndOfGame) {
sb.append(" for the rest of the game");
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostIncreasementAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostIncreasementAllEffect.java
index 95d6d6e524b..6b371b0dc49 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostIncreasementAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostIncreasementAllEffect.java
@@ -48,7 +48,7 @@ public class SpellsCostIncreasementAllEffect extends CostModificationEffectImpl
private int amount;
public SpellsCostIncreasementAllEffect(int amount) {
- this(new FilterCard("All Spells "), amount);
+ this(new FilterCard("Spells"), amount);
}
public SpellsCostIncreasementAllEffect(FilterCard filter, int amount) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllEffect.java
index 54bc9bbd81f..0b7af33808d 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionAllEffect.java
@@ -55,7 +55,7 @@ public class SpellsCostReductionAllEffect extends CostModificationEffectImpl {
private final boolean upTo;
public SpellsCostReductionAllEffect(int amount) {
- this(new FilterCard("All Spells "), amount);
+ this(new FilterCard("Spells"), amount);
}
public SpellsCostReductionAllEffect(FilterCard filter, int amount) {
diff --git a/Mage/src/main/java/mage/abilities/keyword/DefenderAbility.java b/Mage/src/main/java/mage/abilities/keyword/DefenderAbility.java
index 293ad9adb2a..a6cf1ce515b 100644
--- a/Mage/src/main/java/mage/abilities/keyword/DefenderAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/DefenderAbility.java
@@ -56,7 +56,7 @@ public class DefenderAbility extends StaticAbility implements MageSingleton {
@Override
public String getRule() {
- return "Defender";
+ return "defender";
}
@Override
diff --git a/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java b/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java
index afe35d923f2..e978cb9dc0e 100644
--- a/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/EchoAbility.java
@@ -187,6 +187,7 @@ class EchoEffect extends OneShotEffect {
if (controller.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + '?', source, game)) {
cost.clearPaid();
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) {
+ game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ECHO_PAID, source.getSourceId(), source.getSourceId(), source.getControllerId()));
return true;
}
}
diff --git a/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java b/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java
index c05f20118f5..aa457aea70a 100644
--- a/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/FlashbackAbility.java
@@ -32,14 +32,13 @@ import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
-import mage.abilities.costs.mana.ManaCost;
import mage.abilities.effects.ContinuousEffect;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.Card;
import mage.cards.SplitCard;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.SpellAbilityCastMode;
import mage.constants.SpellAbilityType;
import mage.constants.TimingRule;
import mage.constants.Zone;
@@ -66,23 +65,21 @@ import mage.target.targetpointer.FixedTarget;
public class FlashbackAbility extends SpellAbility {
private String abilityName;
+ private SpellAbility spellAbilityToResolve;
public FlashbackAbility(Cost cost, TimingRule timingRule) {
- super(null, "", Zone.GRAVEYARD);
+ super(null, "", Zone.GRAVEYARD, SpellAbilityType.BASE_ALTERNATE, SpellAbilityCastMode.FLASHBACK);
this.setAdditionalCostsRuleVisible(false);
this.name = "Flashback " + cost.getText();
- this.addEffect(new FlashbackEffect());
this.addCost(cost);
this.timing = timingRule;
- this.usesStack = false;
- this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
- setCostModificationActive(false);
}
public FlashbackAbility(final FlashbackAbility ability) {
super(ability);
this.spellAbilityType = ability.spellAbilityType;
this.abilityName = ability.abilityName;
+ this.spellAbilityToResolve = ability.spellAbilityToResolve;
}
@Override
@@ -108,6 +105,47 @@ public class FlashbackAbility extends SpellAbility {
return false;
}
+ @Override
+ public SpellAbility getSpellAbilityToResolve(Game game) {
+ Card card = game.getCard(getSourceId());
+ if (card != null) {
+ if (spellAbilityToResolve == null) {
+ SpellAbility spellAbilityCopy = null;
+ if (card.isSplitCard()) {
+ if (((SplitCard) card).getLeftHalfCard().getName().equals(abilityName)) {
+ spellAbilityCopy = ((SplitCard) card).getLeftHalfCard().getSpellAbility().copy();
+ } else if (((SplitCard) card).getRightHalfCard().getName().equals(abilityName)) {
+ spellAbilityCopy = ((SplitCard) card).getRightHalfCard().getSpellAbility().copy();
+ }
+ } else {
+ spellAbilityCopy = card.getSpellAbility().copy();
+ }
+ if (spellAbilityCopy == null) {
+ return null;
+ }
+ spellAbilityCopy.setId(this.getId());
+ spellAbilityCopy.getManaCosts().clear();
+ spellAbilityCopy.getManaCostsToPay().clear();
+ spellAbilityCopy.getCosts().addAll(this.getCosts());
+ spellAbilityCopy.addCost(this.getManaCosts());
+ spellAbilityCopy.setSpellAbilityCastMode(this.getSpellAbilityCastMode());
+ spellAbilityToResolve = spellAbilityCopy;
+ ContinuousEffect effect = new FlashbackReplacementEffect();
+ effect.setTargetPointer(new FixedTarget(getSourceId(), game.getState().getZoneChangeCounter(getSourceId())));
+ game.addEffect(effect, this);
+ }
+ }
+ return spellAbilityToResolve;
+ }
+
+ @Override
+ public Costs getCosts() {
+ if (spellAbilityToResolve == null) {
+ return super.getCosts();
+ }
+ return spellAbilityToResolve.getCosts();
+ }
+
@Override
public FlashbackAbility copy() {
return new FlashbackAbility(this);
@@ -144,102 +182,18 @@ public class FlashbackAbility extends SpellAbility {
return sbRule.toString();
}
- @Override
- public void setSpellAbilityType(SpellAbilityType spellAbilityType) {
- this.spellAbilityType = spellAbilityType;
- }
-
- @Override
- public SpellAbilityType getSpellAbilityType() {
- return this.spellAbilityType;
- }
-
+ /**
+ * Used for split card sin PlayerImpl method:
+ * getOtherUseableActivatedAbilities
+ *
+ * @param abilityName
+ */
public void setAbilityName(String abilityName) {
this.abilityName = abilityName;
}
}
-class FlashbackEffect extends OneShotEffect {
-
- public FlashbackEffect() {
- super(Outcome.Benefit);
- staticText = "";
- }
-
- public FlashbackEffect(final FlashbackEffect effect) {
- super(effect);
- }
-
- @Override
- public FlashbackEffect copy() {
- return new FlashbackEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Card card = (Card) game.getObject(source.getSourceId());
- if (card != null) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- SpellAbility spellAbility;
- switch (((FlashbackAbility) source).getSpellAbilityType()) {
- case SPLIT_LEFT:
- spellAbility = ((SplitCard) card).getLeftHalfCard().getSpellAbility().copy();
- break;
- case SPLIT_RIGHT:
- spellAbility = ((SplitCard) card).getRightHalfCard().getSpellAbility().copy();
- break;
- default:
- spellAbility = card.getSpellAbility().copy();
- }
-
- spellAbility.clear();
- // set the payed flashback costs to the spell ability so abilities like Converge or calculation of {X} values work
- spellAbility.getManaCostsToPay().clear();
- spellAbility.getManaCostsToPay().addAll(source.getManaCosts());
- spellAbility.getManaCosts().clear();
- spellAbility.getManaCosts().addAll(source.getManaCosts());
- // needed to get e.g. paid costs from Conflagrate
-
- for (Cost cost : source.getCosts()) {
- if (cost instanceof Costs) {
- Costs listOfCosts = (Costs) cost;
- for (Cost singleCost : listOfCosts) {
- if (singleCost instanceof ManaCost) {
- singleCost.clearPaid();
- spellAbility.getManaCosts().add((ManaCost) singleCost);
- spellAbility.getManaCostsToPay().add((ManaCost) singleCost);
- } else {
- spellAbility.getCosts().add(singleCost);
- }
- }
-
- } else {
- if (cost instanceof ManaCost) {
- spellAbility.getManaCosts().add((ManaCost) cost);
- spellAbility.getManaCostsToPay().add((ManaCost) cost);
- } else {
- spellAbility.getCosts().add(cost);
- }
- }
- }
- if (!game.isSimulation()) {
- game.informPlayers(controller.getLogName() + " flashbacks " + card.getLogName());
- }
- if (controller.cast(spellAbility, game, false)) {
- ContinuousEffect effect = new FlashbackReplacementEffect();
- effect.setTargetPointer(new FixedTarget(source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId())));
- game.addEffect(effect, source);
- }
- return true;
- }
- }
- return false;
- }
-
-}
-
class FlashbackReplacementEffect extends ReplacementEffectImpl {
public FlashbackReplacementEffect() {
@@ -287,7 +241,7 @@ class FlashbackReplacementEffect extends ReplacementEffectImpl {
&& ((ZoneChangeEvent) event).getToZone() != Zone.EXILED) {
int zcc = game.getState().getZoneChangeCounter(source.getSourceId());
- if (((FixedTarget) getTargetPointer()).getZoneChangeCounter() == zcc) {
+ if (((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == zcc) {
return true;
}
diff --git a/Mage/src/main/java/mage/abilities/keyword/LifelinkAbility.java b/Mage/src/main/java/mage/abilities/keyword/LifelinkAbility.java
index c22dde451aa..7a12b664265 100644
--- a/Mage/src/main/java/mage/abilities/keyword/LifelinkAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/LifelinkAbility.java
@@ -56,7 +56,7 @@ public class LifelinkAbility extends StaticAbility implements MageSingleton {
@Override
public String getRule() {
- return "Lifelink (Damage dealt by this creature also causes you to gain that much life.)";
+ return "lifelink (Damage dealt by this creature also causes you to gain that much life.)";
}
@Override
diff --git a/Mage/src/main/java/mage/abilities/keyword/PersistAbility.java b/Mage/src/main/java/mage/abilities/keyword/PersistAbility.java
index 085d893a495..bf4ca8188f0 100644
--- a/Mage/src/main/java/mage/abilities/keyword/PersistAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/PersistAbility.java
@@ -38,7 +38,6 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
-import mage.target.targetpointer.FixedTarget;
public class PersistAbility extends DiesTriggeredAbility {
@@ -66,8 +65,6 @@ public class PersistAbility extends DiesTriggeredAbility {
if (super.checkTrigger(event, game)) {
Permanent permanent = ((ZoneChangeEvent) event).getTarget();
if (permanent.getCounters(game).getCount(CounterType.M1M1) == 0) {
- FixedTarget fixedTarget = new FixedTarget(permanent.getId());
- fixedTarget.init(game, this);
return true;
}
}
diff --git a/Mage/src/main/java/mage/abilities/keyword/ProtectionAbility.java b/Mage/src/main/java/mage/abilities/keyword/ProtectionAbility.java
index 5f1b480406e..46471af292f 100644
--- a/Mage/src/main/java/mage/abilities/keyword/ProtectionAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/ProtectionAbility.java
@@ -89,7 +89,7 @@ public class ProtectionAbility extends StaticAbility {
@Override
public String getRule() {
- return "Protection from " + filter.getMessage() + (removeAuras ? "" : ". This effect doesn't remove auras.");
+ return "protection from " + filter.getMessage() + (removeAuras ? "" : ". This effect doesn't remove auras.");
}
public boolean canTarget(MageObject source, Game game) {
diff --git a/Mage/src/main/java/mage/abilities/keyword/TotemArmorAbility.java b/Mage/src/main/java/mage/abilities/keyword/TotemArmorAbility.java
index 604f1645040..f31280d1bf3 100644
--- a/Mage/src/main/java/mage/abilities/keyword/TotemArmorAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/TotemArmorAbility.java
@@ -65,7 +65,7 @@ public class TotemArmorAbility extends SimpleStaticAbility {
@Override
public String getRule() {
- return "Totem Armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.)";
+ return "Totem armor (If enchanted creature would be destroyed, instead remove all damage from it and destroy this Aura.)";
}
}
diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java
index d73dd8e6bba..4fc6a220e94 100644
--- a/Mage/src/main/java/mage/cards/CardImpl.java
+++ b/Mage/src/main/java/mage/cards/CardImpl.java
@@ -29,7 +29,6 @@ package mage.cards;
import java.lang.reflect.Constructor;
import java.util.*;
-
import mage.MageObject;
import mage.MageObjectImpl;
import mage.Mana;
@@ -165,6 +164,12 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
secondSideCardClazz = card.secondSideCardClazz;
nightCard = card.nightCard;
}
+ if (card.spellAbility != null) {
+ spellAbility = card.getSpellAbility().copy();
+ } else {
+ spellAbility = null;
+ }
+
flipCard = card.flipCard;
flipCardName = card.flipCardName;
splitCard = card.splitCard;
@@ -177,6 +182,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
this.objectId = UUID.randomUUID();
this.abilities.newOriginalId();
this.abilities.setSourceId(objectId);
+ if (this.spellAbility != null) {
+ this.spellAbility.setSourceId(objectId);
+ }
}
public static Card createCard(String name, CardSetInfo setInfo) {
@@ -508,7 +516,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
Card mainCard = getMainCard();
ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK);
ZoneChangeInfo.Stack info
- = new ZoneChangeInfo.Stack(event, new Spell(this, ability.copy(), controllerId, event.getFromZone()));
+ = new ZoneChangeInfo.Stack(event, new Spell(this, ability.getSpellAbilityToResolve(game), controllerId, event.getFromZone()));
return ZonesHandler.cast(info, game);
}
diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java
index 02b9c5abf57..9538db973e0 100644
--- a/Mage/src/main/java/mage/cards/repository/CardRepository.java
+++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java
@@ -58,7 +58,7 @@ public enum CardRepository {
// raise this if db structure was changed
private static final long CARD_DB_VERSION = 51;
// raise this if new cards were added to the server
- private static final long CARD_CONTENT_VERSION = 104;
+ private static final long CARD_CONTENT_VERSION = 105;
private Dao cardDao;
private Set classNames;
diff --git a/Mage/src/main/java/mage/constants/SpellAbilityCastMode.java b/Mage/src/main/java/mage/constants/SpellAbilityCastMode.java
index 663c8c8f1bf..71aecf37ed5 100644
--- a/Mage/src/main/java/mage/constants/SpellAbilityCastMode.java
+++ b/Mage/src/main/java/mage/constants/SpellAbilityCastMode.java
@@ -33,7 +33,8 @@ package mage.constants;
*/
public enum SpellAbilityCastMode {
NORMAL("Normal"),
- MADNESS("Madness");
+ MADNESS("Madness"),
+ FLASHBACK("Flashback");
private final String text;
diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java
index c724734fa89..e6ccc996578 100644
--- a/Mage/src/main/java/mage/filter/StaticFilters.java
+++ b/Mage/src/main/java/mage/filter/StaticFilters.java
@@ -179,7 +179,13 @@ public final class StaticFilters {
static {
FILTER_CONTROLLED_CREATURE.setLockedFilter(true);
+ }
+ public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_CREATURES = new FilterControlledCreaturePermanent("creatures you control");
+
+ static {
+ FILTER_CONTROLLED_CREATURES.setLockedFilter(true);
}
+
public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_A_CREATURE = new FilterControlledCreaturePermanent("a creature you control");
static {
diff --git a/Mage/src/main/java/mage/filter/predicate/ability/ArtifactSourcePredicate.java b/Mage/src/main/java/mage/filter/predicate/ability/ArtifactSourcePredicate.java
new file mode 100644
index 00000000000..36ff6b00321
--- /dev/null
+++ b/Mage/src/main/java/mage/filter/predicate/ability/ArtifactSourcePredicate.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.filter.predicate.ability;
+
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.filter.predicate.Predicate;
+import mage.game.Game;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class ArtifactSourcePredicate implements Predicate {
+
+ @Override
+ public boolean apply(Ability input, Game game) {
+ MageObject sourceObject = input.getSourceObject(game);
+ return sourceObject != null && sourceObject.isArtifact();
+ }
+
+ @Override
+ public String toString() {
+ return "Source(Artifact)";
+ }
+}
diff --git a/Mage/src/main/java/mage/filter/predicate/other/CardTextPredicate.java b/Mage/src/main/java/mage/filter/predicate/other/CardTextPredicate.java
index 36cf356ce4f..503d290e054 100644
--- a/Mage/src/main/java/mage/filter/predicate/other/CardTextPredicate.java
+++ b/Mage/src/main/java/mage/filter/predicate/other/CardTextPredicate.java
@@ -27,6 +27,7 @@
*/
package mage.filter.predicate.other;
+import java.util.HashMap;
import mage.cards.Card;
import mage.cards.SplitCard;
import mage.constants.SubType;
@@ -44,21 +45,38 @@ public class CardTextPredicate implements Predicate {
private final boolean inNames;
private final boolean inTypes;
private final boolean inRules;
+ private final boolean isUnique;
+ private HashMap seenCards = null;
- public CardTextPredicate(String text, boolean inNames, boolean inTypes, boolean inRules) {
+ public CardTextPredicate(String text, boolean inNames, boolean inTypes, boolean inRules, boolean isUnique) {
this.text = text;
this.inNames = inNames;
this.inTypes = inTypes;
this.inRules = inRules;
+ this.isUnique = isUnique;
+ seenCards = new HashMap<>();
}
@Override
public boolean apply(Card input, Game game) {
- if (text.isEmpty()) {
+ if (text.isEmpty() && !isUnique) {
return true;
}
+
+ if (text.isEmpty() && isUnique) {
+ boolean found = !seenCards.keySet().contains(input.getName());
+ seenCards.put(input.getName(), true);
+ return found;
+ }
+
// first check in card name
if (inNames && input.getName().toLowerCase().contains(text.toLowerCase())) {
+ if (isUnique && seenCards.keySet().contains(input.getName())) {
+ return false;
+ }
+ if (isUnique) {
+ seenCards.put(input.getName(), true);
+ }
return true;
}
@@ -105,11 +123,18 @@ public class CardTextPredicate implements Predicate {
}
}
}
+
+ if (found && isUnique && seenCards.keySet().contains(input.getName())) {
+ found = false;
+ }
if (!found) {
return false;
}
}
+ if (isUnique) {
+ seenCards.put(input.getName(), true);
+ }
return true;
}
diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java
index efb8984d58c..572a2a4307b 100644
--- a/Mage/src/main/java/mage/game/GameImpl.java
+++ b/Mage/src/main/java/mage/game/GameImpl.java
@@ -156,9 +156,12 @@ public abstract class GameImpl implements Game, Serializable {
private final int startLife;
protected PlayerList playerList;
+ // infinite loop check (no copy of this attributes neccessary)
private int infiniteLoopCounter; // used to check if the game is in an infinite loop
private int lastNumberOfAbilitiesOnTheStack; // used to check how long no new ability was put to stack
+ private List lastPlayersLifes = null; // if life is going down, it's no infinite loop
private final LinkedList stackObjectsCheck = new LinkedList<>(); // used to check if different sources used the stack
+
// used to set the counters a permanent adds the battlefield (if no replacement effect is used e.g. Persist)
protected Map enterWithCounters = new HashMap<>();
// used to proceed player conceding requests
@@ -1418,6 +1421,24 @@ public abstract class GameImpl implements Game, Serializable {
protected void checkInfiniteLoop(UUID removedStackObjectSourceId) {
if (stackObjectsCheck.contains(removedStackObjectSourceId)
&& getStack().size() >= lastNumberOfAbilitiesOnTheStack) {
+ // Create a list of players life
+ List newLastPlayersLifes = new ArrayList<>();
+ for (Player player : this.getPlayers().values()) {
+ newLastPlayersLifes.add(player.getLife());
+ }
+ // Check if a player is loosing life
+ if (lastPlayersLifes != null && lastPlayersLifes.size() == newLastPlayersLifes.size()) {
+ for (int i = 0; i < newLastPlayersLifes.size(); i++) {
+ if (newLastPlayersLifes.get(i) < lastPlayersLifes.get(i)) {
+ // player is loosing life
+ lastPlayersLifes = null;
+ infiniteLoopCounter = 0; // reset the infinite counter
+ break;
+ }
+ }
+ } else {
+ lastPlayersLifes = newLastPlayersLifes;
+ }
infiniteLoopCounter++;
if (infiniteLoopCounter > 15) {
Player controller = getPlayer(getControllerId(removedStackObjectSourceId));
diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java
index 97463088660..52b77917ccb 100644
--- a/Mage/src/main/java/mage/game/combat/Combat.java
+++ b/Mage/src/main/java/mage/game/combat/Combat.java
@@ -750,6 +750,78 @@ public class Combat implements Serializable, Copyable {
potentialBlockers.add(creature.getId());
}
}
+ // check the mustBlockAllAttackers requirement for creatures already blocking (Blaze of Glory) -------------------------------
+ if (effect.mustBlockAllAttackers(game)) {
+ // find all the attackers that the creature can block (and no restictions prevent this)
+ Set attackersToBlock = new HashSet<>();
+ boolean mayBlock = false;
+ for (UUID attackingCreatureId : getAttackers()) {
+ if (creature.canBlock(attackingCreatureId, game)) {
+ Permanent attackingCreature = game.getPermanent(attackingCreatureId);
+ if (attackingCreature != null) {
+ // check if the attacker is already blocked by a max of blockers, so blocker can't block it also
+ if (attackingCreature.getMaxBlockedBy() != 0) { // 0 = no restriction about the number of possible blockers
+ int alreadyBlockingCreatures = 0;
+ for (CombatGroup group : getGroups()) {
+ if (group.getAttackers().contains(attackingCreatureId)) {
+ alreadyBlockingCreatures = group.getBlockers().size();
+ break;
+ }
+ }
+ if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) {
+ continue; // Attacker can't be blocked by more blockers so check next attacker
+ }
+ }
+ // check restrictions of the creature to block that prevent it can be blocked (note L_J: not sure what this refers to...)
+
+ // check if enough possible blockers are available, if true, mayBlock can be set to true
+ if (attackingCreature.getMinBlockedBy() > 1) {
+ int alreadyBlockingCreatures = 0;
+ for (CombatGroup group : getGroups()) {
+ if (group.getAttackers().contains(attackingCreatureId)) {
+ alreadyBlockingCreatures = group.getBlockers().size();
+ break;
+ }
+ }
+ if (attackingCreature.getMinBlockedBy() >= alreadyBlockingCreatures) {
+ continue; // Attacker can't be blocked by the current blocker amount so check next attacker
+ }
+ } else {
+ attackersToBlock.add(attackingCreatureId);
+ }
+ }
+ }
+ }
+ if (!attackersToBlock.isEmpty()) {
+ for (UUID attackerId : attackersToBlock) {
+ if (!findGroup(attackerId).getBlockers().contains(creature.getId())) {
+ mayBlock = true;
+ break;
+ }
+ }
+ }
+ // if creature can block more attackers, inform human player or set blocks for AI player
+ if (mayBlock) {
+ if (controller.isHuman()) {
+ if (!game.isSimulation()) {
+ game.informPlayer(controller, "Creature should block all attackers it's able to this turn: " + creature.getIdName());
+ }
+ } else {
+ Player defender = game.getPlayer(creature.getControllerId());
+ if (defender != null) {
+ for (UUID attackingCreatureId : getAttackers()) {
+ if (creature.canBlock(attackingCreatureId, game)
+ && !findGroup(attackingCreatureId).getBlockers().contains(creature.getId())
+ && attackersToBlock.contains(attackingCreatureId)) {
+ // TODO: might need to revisit this (calls some pickBlockerOrder instances even for a single blocker - damage distribution appears to be working correctly however)
+ defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
+ }
+ }
+ }
+ }
+ return false;
+ }
+ }
}
}
@@ -773,10 +845,9 @@ public class Combat implements Serializable, Copyable {
}
}
- // check the mustBlockAny requirement ----------------------------------------
- if (effect.mustBlockAny(game)) {
- // check that it can block at least one of the attackers
- // and no restictions prevent this
+ // check the mustBlockAny requirement (and mustBlockAllAttackers for not blocking creatures) ----------------------------------------
+ if (effect.mustBlockAny(game) || effect.mustBlockAllAttackers(game)) {
+ // check that it can block at least one of the attackers and no restictions prevent this
boolean mayBlock = false;
for (UUID attackingCreatureId : getAttackers()) {
if (creature.canBlock(attackingCreatureId, game)) {
@@ -792,15 +863,23 @@ public class Combat implements Serializable, Copyable {
}
}
if (attackingCreature.getMaxBlockedBy() <= alreadyBlockingCreatures) {
- // Attacker can't be blocked by more blockers so check next attacker
- continue;
+ continue; // Attacker can't be blocked by more blockers so check next attacker
}
}
- // check restrictions of the creature to block that prevent it can be blocked
+ // check restrictions of the creature to block that prevent it can be blocked (note L_J: not sure what this refers to...)
+ // check if enough possible blockers are available, if true, mayBlock can be set to true
if (attackingCreature.getMinBlockedBy() > 1) {
- // TODO: check if enough possible blockers are available, if true, mayBlock can be set to true
-
+ int alreadyBlockingCreatures = 0;
+ for (CombatGroup group : getGroups()) {
+ if (group.getAttackers().contains(attackingCreatureId)) {
+ alreadyBlockingCreatures = group.getBlockers().size();
+ break;
+ }
+ }
+ if (attackingCreature.getMinBlockedBy() >= alreadyBlockingCreatures) {
+ continue; // Attacker can't be blocked by the current blocker amount so check next attacker
+ }
} else {
mayBlock = true;
break;
@@ -808,7 +887,7 @@ public class Combat implements Serializable, Copyable {
}
}
}
- // if so inform human player or set block for AI player
+ // if creature can block, inform human player or set block for AI player
if (mayBlock) {
if (controller.isHuman()) {
if (!game.isSimulation()) {
@@ -818,7 +897,8 @@ public class Combat implements Serializable, Copyable {
Player defender = game.getPlayer(creature.getControllerId());
if (defender != null) {
for (UUID attackingCreatureId : getAttackers()) {
- if (creature.canBlock(attackingCreatureId, game)) {
+ if (creature.canBlock(attackingCreatureId, game)
+ && !findGroup(attackingCreatureId).getBlockers().contains(creature.getId())) {
defender.declareBlocker(defender.getId(), creature.getId(), attackingCreatureId, game);
break;
}
diff --git a/Mage/src/main/java/mage/game/combat/CombatGroup.java b/Mage/src/main/java/mage/game/combat/CombatGroup.java
index 2a42f65b5e9..c66dcd0c06d 100644
--- a/Mage/src/main/java/mage/game/combat/CombatGroup.java
+++ b/Mage/src/main/java/mage/game/combat/CombatGroup.java
@@ -173,21 +173,16 @@ public class CombatGroup implements Serializable, Copyable {
public void assignDamageToAttackers(boolean first, Game game) {
if (!blockers.isEmpty() && (!first || hasFirstOrDoubleStrike(game))) {
// this should only come up if Butcher Orgg is granted the ability to block multiple blockers
- boolean altDamageMethod = false;
for (UUID blockerId : blockers) {
Permanent blocker = game.getPermanent(blockerId);
if (assignsDefendingPlayerAndOrDefendingCreaturesDividedDamage(blocker, blocker.getControllerId(), first, game, false)) {
- altDamageMethod = true;
+ return;
}
}
- if (altDamageMethod) {
- // this could be necessary to remake in the future (banding with Butcher Orgg?)
- return;
- }
- if (attackers.size() == 1) {
- singleAttackerDamage(first, game);
- } else {
+ if (attackers.size() != 1) {
multiAttackerDamage(first, game);
+ // } else {
+ // singleAttackerDamage(first, game);
}
}
}
@@ -462,10 +457,15 @@ public class CombatGroup implements Serializable, Copyable {
* {@link #singleBlockerDamage}.
*
* Handles abilities like "{this} an block any number of creatures.".
+ *
+ * Blocker damage for blockers blocking single creatures is handled in
+ * the single/multi blocker methods, so this shouldn't be used anymore.
*
* @param first
* @param game
+ * @deprecated
*/
+ @Deprecated
private void singleAttackerDamage(boolean first, Game game) {
Permanent blocker = game.getPermanent(blockers.get(0));
Permanent attacker = game.getPermanent(attackers.get(0));
@@ -732,42 +732,35 @@ public class CombatGroup implements Serializable, Copyable {
for (UUID uuid : attackers) {
Permanent attacker = game.getPermanent(uuid);
- // Check if there are enough blockers to have a legal block
- if (attacker != null && this.blocked && attacker.getMinBlockedBy() > 1 && !blockers.isEmpty() && blockers.size() < attacker.getMinBlockedBy()) {
- for (UUID blockerId : blockers) {
- Permanent blocker = game.getPermanent(blockerId);
- if (blocker != null) {
- blocker.setBlocking(blocker.getBlocking() - 1);
+ if (attacker != null && this.blocked) {
+ // Check if there are enough blockers to have a legal block
+ if (attacker.getMinBlockedBy() > 1 && !blockers.isEmpty() && blockers.size() < attacker.getMinBlockedBy()) {
+ for (UUID blockerId : new ArrayList<>(blockers)) {
+ game.getCombat().removeBlocker(blockerId, game);
}
- }
- blockers.clear();
- blockerOrder.clear();
- this.blocked = false;
- if (!game.isSimulation()) {
- game.informPlayers(attacker.getLogName() + " can't be blocked except by " + attacker.getMinBlockedBy() + " or more creatures. Blockers discarded.");
- }
- blockWasLegal = false;
- }
- // Check if there are too many blockers (maxBlockedBy = 0 means no restrictions)
- if (attacker != null && this.blocked && attacker.getMaxBlockedBy() > 0 && attacker.getMaxBlockedBy() < blockers.size()) {
- for (UUID blockerId : blockers) {
- Permanent blocker = game.getPermanent(blockerId);
- if (blocker != null) {
- blocker.setBlocking(blocker.getBlocking() - 1);
+ blockers.clear();
+ blockerOrder.clear();
+ if (!game.isSimulation()) {
+ game.informPlayers(attacker.getLogName() + " can't be blocked except by " + attacker.getMinBlockedBy() + " or more creatures. Blockers discarded.");
}
+ blockWasLegal = false;
}
- blockers.clear();
- blockerOrder.clear();
- this.blocked = false;
- if (!game.isSimulation()) {
- game.informPlayers(new StringBuilder(attacker.getLogName())
- .append(" can't be blocked by more than ").append(attacker.getMaxBlockedBy())
- .append(attacker.getMaxBlockedBy() == 1 ? " creature." : " creatures.")
- .append(" Blockers discarded.").toString());
+ // Check if there are too many blockers (maxBlockedBy = 0 means no restrictions)
+ if (attacker.getMaxBlockedBy() > 0 && attacker.getMaxBlockedBy() < blockers.size()) {
+ for (UUID blockerId : new ArrayList<>(blockers)) {
+ game.getCombat().removeBlocker(blockerId, game);
+ }
+ blockers.clear();
+ blockerOrder.clear();
+ if (!game.isSimulation()) {
+ game.informPlayers(new StringBuilder(attacker.getLogName())
+ .append(" can't be blocked by more than ").append(attacker.getMaxBlockedBy())
+ .append(attacker.getMaxBlockedBy() == 1 ? " creature." : " creatures.")
+ .append(" Blockers discarded.").toString());
+ }
+ blockWasLegal = false;
}
- blockWasLegal = false;
}
-
}
return blockWasLegal;
}
diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java
index 06816e0f4af..ef7ec2b5b38 100644
--- a/Mage/src/main/java/mage/game/events/GameEvent.java
+++ b/Mage/src/main/java/mage/game/events/GameEvent.java
@@ -92,6 +92,7 @@ public class GameEvent implements Serializable {
DRAW_CARDS, // applies to an instruction to draw more than one card before any replacement effects apply to individual cards drawn
DRAW_CARD, DREW_CARD,
EXPLORED,
+ ECHO_PAID,
MIRACLE_CARD_REVEALED,
MADNESS_CARD_EXILED,
INVESTIGATED,
diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java
index 07509f57863..00eabb629a5 100644
--- a/Mage/src/main/java/mage/game/stack/StackAbility.java
+++ b/Mage/src/main/java/mage/game/stack/StackAbility.java
@@ -50,6 +50,7 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
+import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.Targets;
@@ -529,12 +530,17 @@ public class StackAbility extends StackObjImpl implements Ability {
@Override
public MageObject getSourceObject(Game game) {
- return game.getBaseObject(getSourceId());
+ return this.ability.getSourceObject(game);
}
@Override
public MageObject getSourceObjectIfItStillExists(Game game) {
- throw new UnsupportedOperationException("Not supported.");
+ return this.ability.getSourceObjectIfItStillExists(game);
+ }
+
+ @Override
+ public Permanent getSourcePermanentIfItStillExists(Game game) {
+ return this.ability.getSourcePermanentIfItStillExists(game);
}
@Override
diff --git a/Mage/src/main/java/mage/players/ManaPool.java b/Mage/src/main/java/mage/players/ManaPool.java
index 62ddedf6d6b..565e96cac21 100644
--- a/Mage/src/main/java/mage/players/ManaPool.java
+++ b/Mage/src/main/java/mage/players/ManaPool.java
@@ -118,10 +118,19 @@ public class ManaPool implements Serializable {
// if manual payment and the needed mana type was not unlocked, nothing will be paid
return false;
}
+ ManaType possibleAsThoughtPoolManaType = null;
if (autoPayment && autoPaymentRestricted && !wasManaAddedBeyondStock() && manaType != unlockedManaType) {
// if automatic restricted payment and there is already mana in the pool
// and the needed mana type was not unlocked, nothing will be paid
- return false;
+ if (unlockedManaType != null) {
+ ManaPoolItem checkItem = new ManaPoolItem();
+ checkItem.add(unlockedManaType, 1);
+ possibleAsThoughtPoolManaType = game.getContinuousEffects().asThoughMana(manaType, checkItem, ability.getSourceId(), ability, ability.getControllerId(), game);
+ }
+ // Check if it's possible to use mana as thought for the unlocked manatype in the mana pool for this ability
+ if (possibleAsThoughtPoolManaType == null || possibleAsThoughtPoolManaType != unlockedManaType) {
+ return false; // if it's not possible return
+ }
}
if (getConditional(manaType, ability, filter, game, costToPay) > 0) {
@@ -138,7 +147,7 @@ public class ManaPool implements Serializable {
}
}
}
- if (manaType != unlockedManaType && autoPayment && autoPaymentRestricted && mana.count() == mana.getStock()) {
+ if (possibleAsThoughtPoolManaType == null && manaType != unlockedManaType && autoPayment && autoPaymentRestricted && mana.count() == mana.getStock()) {
// no mana added beyond the stock so don't auto pay this
continue;
}
diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java
index ceb43d787f0..b47fab6df90 100644
--- a/Mage/src/main/java/mage/players/PlayerImpl.java
+++ b/Mage/src/main/java/mage/players/PlayerImpl.java
@@ -1158,7 +1158,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
} else {
int bookmark = game.bookmarkState();
- if (ability.activate(game, ability instanceof FlashbackAbility)) {
+ if (ability.activate(game, false)) {
ability.resolve(game);
game.removeBookmark(bookmark);
resetStoredBookmark(game);
@@ -1219,11 +1219,7 @@ public abstract class PlayerImpl implements Player, Serializable {
result = playManaAbility((ActivatedManaAbilityImpl) ability.copy(), game);
break;
case SPELL:
- if (ability instanceof FlashbackAbility) {
- result = playAbility(ability.copy(), game);
- } else {
- result = cast((SpellAbility) ability, game, false);
- }
+ result = cast((SpellAbility) ability.copy(), game, false);
break;
default:
result = playAbility(ability.copy(), game);
@@ -1278,7 +1274,7 @@ public abstract class PlayerImpl implements Player, Serializable {
return false;
}
- protected LinkedHashMap getSpellAbilities(MageObject object, Zone zone, Game game) {
+ public LinkedHashMap getSpellAbilities(MageObject object, Zone zone, Game game) {
LinkedHashMap useable = new LinkedHashMap<>();
for (Ability ability : object.getAbilities()) {
if (ability instanceof SpellAbility) {
diff --git a/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java b/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java
index 00e65d3b11b..b107528f6e6 100644
--- a/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java
+++ b/Mage/src/main/java/mage/target/common/TargetActivatedAbility.java
@@ -57,7 +57,7 @@ public class TargetActivatedAbility extends TargetObject {
this.minNumberOfTargets = 1;
this.maxNumberOfTargets = 1;
this.zone = Zone.STACK;
- this.targetName = "activated ability";
+ this.targetName = filter.getMessage();
this.filter = filter;
}
diff --git a/Mage/src/main/java/mage/target/common/TargetActivatedOrTriggeredAbility.java b/Mage/src/main/java/mage/target/common/TargetActivatedOrTriggeredAbility.java
index 8c9df2be202..3e3eeff5c21 100644
--- a/Mage/src/main/java/mage/target/common/TargetActivatedOrTriggeredAbility.java
+++ b/Mage/src/main/java/mage/target/common/TargetActivatedOrTriggeredAbility.java
@@ -44,7 +44,7 @@ public class TargetActivatedOrTriggeredAbility extends TargetObject {
protected final FilterStackObject filter;
public TargetActivatedOrTriggeredAbility() {
- this(new FilterStackObject());
+ this(new FilterStackObject("activated or triggered ability"));
}
public TargetActivatedOrTriggeredAbility(FilterStackObject filter) {
diff --git a/Mage/src/main/java/mage/target/targetpointer/FirstTargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/FirstTargetPointer.java
index 01d2b3c7db8..82241949ebf 100644
--- a/Mage/src/main/java/mage/target/targetpointer/FirstTargetPointer.java
+++ b/Mage/src/main/java/mage/target/targetpointer/FirstTargetPointer.java
@@ -35,7 +35,7 @@ public class FirstTargetPointer implements TargetPointer {
Card card = game.getCard(target);
if (card != null) {
this.zoneChangeCounter.put(target, card.getZoneChangeCounter(game));
- }
+ }
}
}
}
@@ -66,9 +66,9 @@ public class FirstTargetPointer implements TargetPointer {
if (zoneChangeCounter.containsKey(targetId)) {
Card card = game.getCard(targetId);
if (card != null && zoneChangeCounter.containsKey(targetId)
- && card.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
- // because if dies trigger has to trigger as permanent has already moved zone, we have to check if target was on the battlefield immed. before
- // but no longer if new permanent is already on the battlefield
+ && card.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
+ // because if dies trigger has to trigger as permanent has already moved zone, we have to check if target was on the battlefield immed. before
+ // but no longer if new permanent is already on the battlefield
Permanent permanent = game.getPermanentOrLKIBattlefield(targetId);
if (permanent == null || permanent.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
return null;
@@ -82,4 +82,16 @@ public class FirstTargetPointer implements TargetPointer {
public TargetPointer copy() {
return new FirstTargetPointer(this);
}
+
+ @Override
+ public FixedTarget getFixedTarget(Game game, Ability source) {
+ this.init(game, source);
+ UUID firstId = getFirst(game, source);
+ if (firstId != null) {
+ return new FixedTarget(firstId, game.getState().getZoneChangeCounter(firstId));
+ }
+ return null;
+
+ }
+
}
diff --git a/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java b/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java
index 397e4e7de3d..c931962322d 100644
--- a/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java
+++ b/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java
@@ -1,15 +1,14 @@
package mage.target.targetpointer;
-import mage.abilities.Ability;
-import mage.cards.Card;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
+import mage.abilities.Ability;
+import mage.cards.Card;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
public class FixedTarget implements TargetPointer {
@@ -65,10 +64,7 @@ public class FixedTarget implements TargetPointer {
public void init(Game game, Ability source) {
if (!initialized) {
initialized = true;
- Card card = game.getCard(targetId);
- if (card != null) {
- this.zoneChangeCounter = card.getZoneChangeCounter(game);
- }
+ this.zoneChangeCounter = game.getState().getZoneChangeCounter(targetId);
}
}
@@ -121,4 +117,10 @@ public class FixedTarget implements TargetPointer {
return permanent;
}
+ @Override
+ public FixedTarget getFixedTarget(Game game, Ability source) {
+ init(game, source);
+ return this;
+ }
+
}
diff --git a/Mage/src/main/java/mage/target/targetpointer/FixedTargets.java b/Mage/src/main/java/mage/target/targetpointer/FixedTargets.java
index bb231a51c71..e220491074e 100644
--- a/Mage/src/main/java/mage/target/targetpointer/FixedTargets.java
+++ b/Mage/src/main/java/mage/target/targetpointer/FixedTargets.java
@@ -21,10 +21,12 @@ import mage.game.permanent.Permanent;
public class FixedTargets implements TargetPointer {
final ArrayList targets = new ArrayList<>();
+ final ArrayList targetsNotInitialized = new ArrayList<>();
+
private boolean initialized;
public FixedTargets(UUID targetId) {
- targets.add(new MageObjectReference(targetId));
+ targetsNotInitialized.add(targetId);
this.initialized = false;
}
@@ -46,6 +48,7 @@ public class FixedTargets implements TargetPointer {
private FixedTargets(final FixedTargets fixedTargets) {
this.targets.addAll(fixedTargets.targets);
+ this.targetsNotInitialized.addAll(fixedTargets.targetsNotInitialized);
this.initialized = fixedTargets.initialized;
}
@@ -53,8 +56,8 @@ public class FixedTargets implements TargetPointer {
public void init(Game game, Ability source) {
if (!initialized) {
initialized = true;
- for (MageObjectReference mor : targets) {
- mor.setZoneChangeCounter(game.getState().getZoneChangeCounter(mor.getSourceId()));
+ for (UUID targetId : targetsNotInitialized) {
+ targets.add(new MageObjectReference(targetId, game.getState().getZoneChangeCounter(targetId), game));
}
}
}
@@ -87,4 +90,20 @@ public class FixedTargets implements TargetPointer {
return new FixedTargets(this);
}
+ /**
+ * Returns a fixed target for (and only) the first taget
+ *
+ * @param game
+ * @param source
+ * @return
+ */
+ @Override
+ public FixedTarget getFixedTarget(Game game, Ability source) {
+ this.init(game, source);
+ UUID firstId = getFirst(game, source);
+ if (firstId != null) {
+ return new FixedTarget(firstId, game.getState().getZoneChangeCounter(firstId));
+ }
+ return null;
+ }
}
diff --git a/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java
index db301a70553..9d2779b4efd 100644
--- a/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java
+++ b/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java
@@ -1,11 +1,10 @@
package mage.target.targetpointer;
+import java.util.*;
import mage.abilities.Ability;
import mage.cards.Card;
import mage.game.Game;
-import java.util.*;
-
public class SecondTargetPointer implements TargetPointer {
private Map zoneChangeCounter = new HashMap<>();
@@ -59,7 +58,7 @@ public class SecondTargetPointer implements TargetPointer {
if (zoneChangeCounter.containsKey(targetId)) {
Card card = game.getCard(targetId);
if (card != null && zoneChangeCounter.containsKey(targetId)
- && card.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
+ && card.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
return null;
}
}
@@ -72,4 +71,14 @@ public class SecondTargetPointer implements TargetPointer {
public TargetPointer copy() {
return new SecondTargetPointer(this);
}
+
+ @Override
+ public FixedTarget getFixedTarget(Game game, Ability source) {
+ this.init(game, source);
+ UUID firstId = getFirst(game, source);
+ if (firstId != null) {
+ return new FixedTarget(firstId, game.getState().getZoneChangeCounter(firstId));
+ }
+ return null;
+ }
}
diff --git a/Mage/src/main/java/mage/target/targetpointer/TargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/TargetPointer.java
index 0b77cd2bf67..6dd021c9ac5 100644
--- a/Mage/src/main/java/mage/target/targetpointer/TargetPointer.java
+++ b/Mage/src/main/java/mage/target/targetpointer/TargetPointer.java
@@ -7,8 +7,14 @@ import mage.abilities.Ability;
import mage.game.Game;
public interface TargetPointer extends Serializable {
+
void init(Game game, Ability source);
+
List getTargets(Game game, Ability source);
+
UUID getFirst(Game game, Ability source);
+
TargetPointer copy();
+
+ FixedTarget getFixedTarget(Game game, Ability source);
}
diff --git a/Mage/src/main/java/mage/target/targetpointer/ThirdTargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/ThirdTargetPointer.java
index 2fdbf05037f..206bfe2eb9e 100644
--- a/Mage/src/main/java/mage/target/targetpointer/ThirdTargetPointer.java
+++ b/Mage/src/main/java/mage/target/targetpointer/ThirdTargetPointer.java
@@ -84,4 +84,15 @@ public class ThirdTargetPointer implements TargetPointer {
public TargetPointer copy() {
return new ThirdTargetPointer(this);
}
+
+ @Override
+ public FixedTarget getFixedTarget(Game game, Ability source) {
+ this.init(game, source);
+ UUID firstId = getFirst(game, source);
+ if (firstId != null) {
+ return new FixedTarget(firstId, game.getState().getZoneChangeCounter(firstId));
+ }
+ return null;
+
+ }
}
diff --git a/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java b/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java
index 23a15d10cd2..e43ed433fee 100644
--- a/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java
+++ b/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java
@@ -89,4 +89,9 @@ public class BlockedAttackerWatcher extends Watcher {
Set blockedAttackers = blockData.get(new MageObjectReference(blocker, game));
return blockedAttackers != null && blockedAttackers.contains(new MageObjectReference(attacker, game));
}
+
+ public boolean creatureHasBlockedAttacker(MageObjectReference attacker, MageObjectReference blocker, Game game) {
+ Set blockedAttackers = blockData.get(blocker);
+ return blockedAttackers != null && blockedAttackers.contains(attacker);
+ }
}
diff --git a/Mage/src/main/java/mage/watchers/common/CreatureAttackedWhichPlayerWatcher.java b/Mage/src/main/java/mage/watchers/common/CreatureAttackedWhichPlayerWatcher.java
new file mode 100644
index 00000000000..7d519e6e043
--- /dev/null
+++ b/Mage/src/main/java/mage/watchers/common/CreatureAttackedWhichPlayerWatcher.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of BetaSteward_at_googlemail.com.
+ */
+package mage.watchers.common;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+import mage.constants.WatcherScope;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.watchers.Watcher;
+
+/**
+ * @author jeffwadsworth
+ *
+ * Return the last player that was attacked by specified creature this turn
+ */
+public class CreatureAttackedWhichPlayerWatcher extends Watcher {
+
+ private final Map getPlayerAttackedThisTurnByCreature = new HashMap<>();
+
+ public CreatureAttackedWhichPlayerWatcher() {
+ super(CreatureAttackedWhichPlayerWatcher.class.getSimpleName(), WatcherScope.GAME);
+ }
+
+ public CreatureAttackedWhichPlayerWatcher(final CreatureAttackedWhichPlayerWatcher watcher) {
+ super(watcher);
+ for (Entry entry : watcher.getPlayerAttackedThisTurnByCreature.entrySet()) {
+ getPlayerAttackedThisTurnByCreature.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) {
+ UUID creatureId = event.getSourceId();
+ UUID playerId = event.getTargetId();
+ if (playerId != null
+ && creatureId != null) {
+ getPlayerAttackedThisTurnByCreature.putIfAbsent(creatureId, playerId);
+ }
+ }
+ }
+
+ public UUID getPlayerAttackedThisTurnByCreature(UUID creatureId) {
+ return getPlayerAttackedThisTurnByCreature.getOrDefault(creatureId, null);
+ }
+
+ @Override
+ public void reset() {
+ getPlayerAttackedThisTurnByCreature.clear();
+ }
+
+ @Override
+ public CreatureAttackedWhichPlayerWatcher copy() {
+ return new CreatureAttackedWhichPlayerWatcher(this);
+ }
+}
diff --git a/Mage/src/main/java/mage/watchers/common/PlayerAttackedStepWatcher.java b/Mage/src/main/java/mage/watchers/common/PlayerAttackedStepWatcher.java
index 03f56c9beb5..0fb1362cd22 100644
--- a/Mage/src/main/java/mage/watchers/common/PlayerAttackedStepWatcher.java
+++ b/Mage/src/main/java/mage/watchers/common/PlayerAttackedStepWatcher.java
@@ -44,7 +44,7 @@ public class PlayerAttackedStepWatcher extends Watcher {
private final Map playerAttacked = new HashMap<>();
public PlayerAttackedStepWatcher() {
- super(PlayerAttackedWatcher.class.getSimpleName(), WatcherScope.GAME);
+ super(PlayerAttackedStepWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public PlayerAttackedStepWatcher(final PlayerAttackedStepWatcher watcher) {
diff --git a/Utils/mtg-sets-data.txt b/Utils/mtg-sets-data.txt
index 9a6faa767d7..ea542b580f8 100644
--- a/Utils/mtg-sets-data.txt
+++ b/Utils/mtg-sets-data.txt
@@ -117,7 +117,7 @@ Magic 2013|M13|
Magic 2014|M14|
Magic 2015|M15|
Core 2019|M19|
-Masters 25|M25|
+Masters 25|A25|
Magic: The Gathering-Commander|CMD|
Magic: The Gathering-Conspiracy|CNS|
Media Inserts|MBP|