counters = new ArrayList<>();
if (card instanceof PermanentView) {
@@ -212,6 +216,8 @@ public final class GuiDisplayUtil {
textLines.setBasicTextLength(textLines.getBasicTextLength() + 50);
}
}
+
+ // damage
if (card.getMageObjectType().isPermanent() && card instanceof PermanentView) {
int damage = ((PermanentView) card).getDamage();
if (damage > 0) {
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java
index a237318a174..5c97f2c59ea 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelComponentImpl.java
@@ -1,5 +1,6 @@
package org.mage.card.arcane;
+import mage.MageInt;
import mage.cards.action.ActionCallback;
import mage.client.constants.Constants;
import mage.client.dialog.PreferencesDialog;
@@ -9,6 +10,7 @@ import mage.client.util.SoftValuesLoadingCache;
import mage.components.ImagePanel;
import mage.components.ImagePanelStyle;
import mage.constants.AbilityType;
+import mage.constants.SubType;
import mage.view.CardView;
import mage.view.CounterView;
import mage.view.PermanentView;
@@ -49,11 +51,16 @@ public class CardPanelComponentImpl extends CardPanel {
private static final int CARD_MIN_SIZE_FOR_ICONS = 60;
private static final int CARD_MAX_SIZE_FOR_ICONS = 200;
+ // text min size for image render mode
+ private static final int CARD_TITLE_FONT_MIN_SIZE = 13;
+ private static final int CARD_PT_FONT_MIN_SIZE = 17;
+
public final ScaledImagePanel imagePanel;
private ImagePanel overlayPanel;
private JPanel iconPanel;
private JButton typeButton;
+ private JPanel ptPanel;
private JPanel counterPanel;
private JLabel loyaltyCounterLabel;
@@ -67,7 +74,9 @@ public class CardPanelComponentImpl extends CardPanel {
private int lastCardWidth;
private final GlowText titleText;
- private final GlowText ptText;
+ private final GlowText ptText1;
+ private final GlowText ptText2;
+ private final GlowText ptText3;
private final JLabel fullImageText;
private String fullImagePath = null;
@@ -280,7 +289,7 @@ public class CardPanelComponentImpl extends CardPanel {
// Title Text
titleText = new GlowText();
- setText(getGameCard());
+ setTitle(getGameCard());
// int fontSize = (int) cardHeight / 11;
// titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
titleText.setForeground(Color.white);
@@ -295,16 +304,19 @@ public class CardPanelComponentImpl extends CardPanel {
add(fullImageText);
// PT Text
- ptText = new GlowText();
- if (getGameCard().isCreature()) {
- ptText.setText(getGameCard().getPower() + '/' + getGameCard().getToughness());
- } else if (getGameCard().isPlanesWalker()) {
- ptText.setText(getGameCard().getLoyalty());
- }
-// ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
- ptText.setForeground(Color.white);
- ptText.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
- add(ptText);
+ ptPanel = new JPanel();
+ ptPanel.setOpaque(false);
+ ptPanel.setLayout(new BoxLayout(ptPanel, BoxLayout.X_AXIS));
+ ptPanel.add(new Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(Integer.MAX_VALUE, 0)));
+ ptText1 = new GlowText();
+ ptText2 = new GlowText();
+ ptText3 = new GlowText();
+ updatePTTexts(getGameCard());
+ ptPanel.add(ptText1);
+ ptPanel.add(ptText2);
+ ptPanel.add(ptText3);
+ //
+ add(ptPanel);
// Sickness overlay
BufferedImage sickness = ImageManagerImpl.instance.getSicknessImage();
@@ -349,7 +361,7 @@ public class CardPanelComponentImpl extends CardPanel {
this.setCounterPanel(null);
}
- private void setText(CardView card) {
+ private void setTitle(CardView card) {
titleText.setText(!displayTitleAnyway && hasImage ? "" : card.getName());
}
@@ -585,12 +597,14 @@ public class CardPanelComponentImpl extends CardPanel {
boolean showText = !isAnimationPanel() && canShowCardIcons(cardWidth, hasImage);
titleText.setVisible(showText);
- ptText.setVisible(showText);
+ ptText1.setVisible(showText && !ptText1.getText().isEmpty());
+ ptText2.setVisible(showText && !ptText2.getText().isEmpty());
+ ptText3.setVisible(showText && !ptText3.getText().isEmpty());
fullImageText.setVisible(fullImagePath != null);
if (showText) {
int fontSize = cardHeight / 13; // startup font size (it same size on all zoom levels)
- titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
+ titleText.setFont(getFont().deriveFont(Font.BOLD, Math.max(CARD_TITLE_FONT_MIN_SIZE, fontSize)));
// margins from card black border to text, not need? text show up good without margins
int titleMarginLeft = 0; //Math.round(28f / 672f * cardWidth);
@@ -607,24 +621,60 @@ public class CardPanelComponentImpl extends CardPanel {
fullImageText.setFont(getFont().deriveFont(Font.PLAIN, 10));
fullImageText.setBounds(titleText.getX(), titleText.getY(), titleText.getBounds().width, titleText.getBounds().height);
- // life points location (font as title)
- ptText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
- Dimension ptSize = ptText.getPreferredSize();
- ptText.setSize(ptSize.width, ptSize.height);
+ // PT (font as title)
+ if (getGameCard().getOriginalCard() != null) {
+ prepareGlowFont(ptText1, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), getGameCard().getOriginalCard().getPower(), false);
+ prepareGlowFont(ptText2, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), null, false);
+ prepareGlowFont(ptText3, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), getGameCard().getOriginalCard().getToughness(), CardRendererUtils.isCardWithDamage(getGameCard()));
- // right bottom corner with margin (sizes from any sample card)
- int ptMarginRight = Math.round(64f / 672f * cardWidth);
- int ptMarginBottom = Math.round(62f / 936f * cardHeight);
+ // right bottom corner with margin (sizes from any sample card)
+ int ptMarginRight = Math.round(64f / 672f * cardWidth);
+ int ptMarginBottom = Math.round(62f / 936f * cardHeight);
- int ptX = cardXOffset + cardWidth - ptMarginRight - ptSize.width;
- int ptY = cardYOffset + cardHeight - ptMarginBottom - ptSize.height;
- ptText.setLocation(ptX, ptY);
+ int ptWidth = cardWidth - ptMarginRight * 2;
+ int ptHeight = ptText2.getHeight();
+ int ptX = cardXOffset + ptMarginRight;
+ int ptY = cardYOffset + cardHeight - ptMarginBottom - ptHeight;
+ ptPanel.setBounds(ptX, ptY, ptWidth, ptHeight);
+ }
// old version was with TEXT_GLOW_SIZE
//ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);
}
}
+ private void prepareGlowFont(GlowText label, int fontSize, MageInt value, boolean drawAsDamaged) {
+ label.setFont(getFont().deriveFont(Font.BOLD, fontSize));
+ label.setForeground(CardRendererUtils.getCardTextColor(value, drawAsDamaged, titleText.getForeground(), true));
+ Dimension ptSize = label.getPreferredSize();
+ label.setSize(ptSize.width, ptSize.height);
+ }
+
+ private void updatePTTexts(CardView card) {
+ if (card.isCreature() || card.getSubTypes().contains(SubType.VEHICLE)) {
+ ptText1.setText(getGameCard().getPower());
+ ptText2.setText("/");
+ ptText3.setText(CardRendererUtils.getCardLifeWithDamage(getGameCard()));
+ } else if (card.isPlanesWalker()) {
+ ptText1.setText("");
+ ptText2.setText("");
+ ptText3.setText(getGameCard().getLoyalty());
+ } else {
+ ptText1.setText("");
+ ptText2.setText("");
+ ptText3.setText("");
+ }
+
+ ptText1.setForeground(Color.white);
+ ptText1.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
+
+ ptText2.setForeground(Color.white);
+ ptText2.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
+
+ ptText3.setForeground(Color.white);
+ ptText3.setGlow(Color.black, TEXT_GLOW_SIZE, TEXT_GLOW_INTENSITY);
+ }
+
@Override
public String toString() {
return getGameCard().toString();
@@ -647,10 +697,14 @@ public class CardPanelComponentImpl extends CardPanel {
// Update components
if (alpha == 0) {
- this.ptText.setVisible(false);
+ this.ptText1.setVisible(false);
+ this.ptText2.setVisible(false);
+ this.ptText3.setVisible(false);
this.titleText.setVisible(false);
} else if (alpha == 1.0f) {
- this.ptText.setVisible(true);
+ this.ptText1.setVisible(true);
+ this.ptText2.setVisible(true);
+ this.ptText3.setVisible(true);
this.titleText.setVisible(true);
}
}
@@ -683,7 +737,7 @@ public class CardPanelComponentImpl extends CardPanel {
UI.invokeLater(() -> {
if (stamp == updateArtImageStamp) {
hasImage = srcImage != null;
- setText(getGameCard());
+ setTitle(getGameCard());
setImage(srcImage);
}
});
@@ -712,7 +766,7 @@ public class CardPanelComponentImpl extends CardPanel {
@Override
public void showCardTitle() {
displayTitleAnyway = true;
- setText(getGameCard());
+ setTitle(getGameCard());
}
@Override
@@ -720,17 +774,8 @@ public class CardPanelComponentImpl extends CardPanel {
// Super
super.update(card);
- // Update card text
- if (card.isCreature() && card.isPlanesWalker()) {
- ptText.setText(card.getPower() + '/' + card.getToughness() + " (" + card.getLoyalty() + ')');
- } else if (card.isCreature()) {
- ptText.setText(card.getPower() + '/' + card.getToughness());
- } else if (card.isPlanesWalker()) {
- ptText.setText(card.getLoyalty());
- } else {
- ptText.setText("");
- }
- setText(card);
+ updatePTTexts(card);
+ setTitle(card);
// Summoning Sickness overlay
if (hasSickness() && card.isCreature() && isPermanent()) {
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 cf62e7cb439..6b7dbc22745 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
@@ -297,6 +297,8 @@ public class CardPanelRenderImpl extends CardPanel {
// Render with Antialialsing
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// Attributes
CardPanelAttributes attribs
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 f32c08e972d..42caffce72b 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
@@ -1,5 +1,9 @@
package org.mage.card.arcane;
+import mage.MageInt;
+import mage.view.CardView;
+import mage.view.PermanentView;
+
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
@@ -10,12 +14,18 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
- * @author stravant@gmail.com
+ * @author stravant@gmail.com, JayDi85
*
* Various static utilities for use in the card renderer
*/
public final class CardRendererUtils {
+ // text colors for PT (mtgo and image render modes)
+ private static final Color CARD_TEXT_COLOR_GOOD_LIGHT = new Color(182, 235, 168);
+ private static final Color CARD_TEXT_COLOR_GOOD_DARK = new Color(52, 135, 88);
+ private static final Color CARD_TEXT_COLOR_BAD_LIGHT = new Color(234, 153, 153);
+ private static final Color CARD_TEXT_COLOR_BAD_DARK = new Color(200, 33, 33);
+
/**
* Convert an abstract image, whose underlying implementation may or may not
* be a BufferedImage into a BufferedImage by creating one and coping the
@@ -53,9 +63,9 @@ public final class CardRendererUtils {
int b = c.getBlue();
int alpha = c.getAlpha();
- int plus_r = (int) ((255 - r) / 2);
- int plus_g = (int) ((255 - g) / 2);
- int plus_b = (int) ((255 - b) / 2);
+ int plus_r = (255 - r) / 2;
+ int plus_g = (255 - g) / 2;
+ int plus_b = (255 - b) / 2;
return new Color(r + plus_r,
g + plus_g,
@@ -69,9 +79,9 @@ public final class CardRendererUtils {
int b = c.getBlue();
int alpha = c.getAlpha();
- int plus_r = (int) (Math.min(255 - r, r) / 2);
- int plus_g = (int) (Math.min(255 - g, g) / 2);
- int plus_b = (int) (Math.min(255 - b, b) / 2);
+ int plus_r = Math.min(255 - r, r) / 2;
+ int plus_g = Math.min(255 - g, g) / 2;
+ int plus_b = Math.min(255 - b, b) / 2;
return new Color(r - plus_r,
g - plus_g,
@@ -195,4 +205,52 @@ public final class CardRendererUtils {
return null;
}
}
+
+ public static String getCardLifeWithDamage(CardView cardView) {
+ // life with damage
+ String originLife = cardView.getToughness();
+ if (cardView instanceof PermanentView) {
+ int damage = ((PermanentView) cardView).getDamage();
+ int life;
+ try {
+ life = Integer.parseInt(originLife);
+ originLife = String.valueOf(Math.max(0, life - damage));
+ } catch (NumberFormatException e) {
+ //
+ }
+ }
+ return originLife;
+ }
+
+ public static boolean isCardWithDamage(CardView cardView) {
+ boolean haveDamage = false;
+ if (cardView instanceof PermanentView) {
+ haveDamage = ((PermanentView) cardView).getDamage() > 0;
+ }
+ return haveDamage;
+ }
+
+ public static Color getCardTextColor(MageInt value, boolean drawAsDamaged, Color defaultColor, boolean textLight) {
+ if (drawAsDamaged) {
+ return textLight ? CARD_TEXT_COLOR_BAD_LIGHT : CARD_TEXT_COLOR_BAD_DARK;
+ }
+
+ // boost colorizing
+ if (value != null) {
+ int current = value.getValue();
+ int origin = value.getBaseValue();
+ if (origin != 0) {
+ if (current < origin) {
+ return textLight ? CARD_TEXT_COLOR_BAD_LIGHT : CARD_TEXT_COLOR_BAD_DARK;
+ } else if (current > origin) {
+ return textLight ? CARD_TEXT_COLOR_GOOD_LIGHT : CARD_TEXT_COLOR_GOOD_DARK;
+ } else {
+ return defaultColor;
+ }
+ }
+ }
+
+ return defaultColor;
+ }
+
}
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java b/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java
index 8d95a11ac04..5600c59b812 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/GlowText.java
@@ -1,5 +1,10 @@
package org.mage.card.arcane;
+import mage.client.util.ImageCaches;
+import mage.client.util.SoftValuesLoadingCache;
+import org.jdesktop.swingx.graphics.GraphicsUtilities;
+
+import javax.swing.*;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
@@ -14,17 +19,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
-import javax.swing.*;
-
-import org.jdesktop.swingx.graphics.GraphicsUtilities;
-
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
-import mage.client.util.ImageCaches;
-import mage.client.util.SoftValuesLoadingCache;
-
public class GlowText extends JLabel {
private static final long serialVersionUID = 1827677946939348001L;
@@ -123,10 +117,7 @@ public class GlowText extends JLabel {
if (!Objects.equals(this.color, other.color)) {
return false;
}
- if (!Objects.equals(this.glowColor, other.glowColor)) {
- return false;
- }
- return true;
+ return Objects.equals(this.glowColor, other.glowColor);
}
}
@@ -158,7 +149,11 @@ public class GlowText extends JLabel {
return;
}
- g.drawImage(IMAGE_CACHE.getOrThrow(new Key(getWidth(), getHeight(), getText(), getFont(), getForeground(), glowSize, glowIntensity, glowColor, wrap)), 0, 0, null);
+ g.drawImage(getGlowImage(), 0, 0, null);
+ }
+
+ public BufferedImage getGlowImage() {
+ return IMAGE_CACHE.getOrThrow(new Key(getWidth(), getHeight(), getText(), getFont(), getForeground(), glowSize, glowIntensity, glowColor, wrap));
}
private static BufferedImage createGlowImage(Key key) {
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 fbdac1c3fa4..566931ef971 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
@@ -1,8 +1,3 @@
-/*
- * 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 org.mage.card.arcane;
import mage.ObjectColor;
@@ -56,13 +51,14 @@ import static org.mage.card.arcane.ManaSymbols.getSizedManaSymbol;
*/
/**
- * @author stravant@gmail.com
+ * @author stravant@gmail.com, JayDi85
*
* Base rendering class for new border cards
*/
public class ModernCardRenderer extends CardRenderer {
private static final Logger LOGGER = Logger.getLogger(ModernCardRenderer.class);
+ private static final GlowText glowTextRenderer = new GlowText();
///////////////////////////////////////////////////////////////////////////
// Textures for modern frame cards
@@ -98,7 +94,7 @@ public class ModernCardRenderer extends CardRenderer {
return new Font("Arial", Font.PLAIN, 1);
}
- public static final Font BASE_BELEREN_FONT = loadFont("beleren-bold");
+ // public static final Font BASE_BELEREN_FONT = loadFont("beleren-bold");
public static final Paint BG_TEXTURE_WHITE = loadBackgroundTexture("white");
public static final Paint BG_TEXTURE_BLUE = loadBackgroundTexture("blue");
@@ -252,16 +248,13 @@ public class ModernCardRenderer extends CardRenderer {
// Box text height
boxTextHeight = getTextHeightForBoxHeight(boxHeight);
boxTextOffset = (boxHeight - boxTextHeight) / 2;
- // Not using Beleren for now because it looks bad at small font sizes. Maybe we want to in the future?
- //boxTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, boxTextHeight);
boxTextFont = new Font("Arial", Font.PLAIN, boxTextHeight);
boxTextFontNarrow = new Font("Arial Narrow", Font.PLAIN, boxTextHeight);
// Box text height
ptTextHeight = getPTTextHeightForLineHeight(boxHeight);
ptTextOffset = (boxHeight - ptTextHeight) / 2;
- // Beleren font does work well for numbers though
- ptTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, ptTextHeight);
+ ptTextFont = new Font("Arial", Font.BOLD, ptTextHeight);
}
@Override
@@ -933,6 +926,51 @@ public class ModernCardRenderer extends CardRenderer {
}
}
+ public void paintOutlineTextByGlow(Graphics2D g, String text, Color color, int x, int y) {
+ GlowText label = new GlowText();
+ label.setGlow(Color.black, 6, 3);
+ label.setText(text);
+ label.setFont(g.getFont().deriveFont(Font.BOLD));
+ label.setForeground(color);
+ Dimension ptSize = label.getPreferredSize();
+ label.setSize(ptSize.width, ptSize.height);
+ g.drawImage(label.getGlowImage(), x, y, null);
+ }
+
+ public void paintOutlineTextByStroke(Graphics2D g, String text, Color color, int x, int y) {
+ // https://stackoverflow.com/a/35222059/1276632
+ Color outlineColor = Color.black;
+ Color fillColor = color;
+ BasicStroke outlineStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
+
+ // remember original settings
+ Color originalColor = g.getColor();
+ Stroke originalStroke = g.getStroke();
+ RenderingHints originalHints = g.getRenderingHints();
+
+ // create a glyph vector from your text
+ GlyphVector glyphVector = g.getFont().createGlyphVector(g.getFontRenderContext(), text);
+ // get the shape object
+ Shape textShape = glyphVector.getOutline(x, y);
+
+ // activate anti aliasing for text rendering (if you want it to look nice)
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+
+ g.setColor(outlineColor);
+ g.setStroke(outlineStroke);
+ g.draw(textShape); // draw outline
+
+ g.setColor(fillColor);
+ g.fill(textShape); // fill the shape
+
+ // reset to original settings after painting
+ g.setColor(originalColor);
+ g.setStroke(originalStroke);
+ g.setRenderingHints(originalHints);
+ }
+
// Draw the P/T and/or Loyalty boxes
protected void drawBottomRight(Graphics2D g, Paint borderPaint, Color fill) {
// No bottom right for abilities
@@ -944,17 +982,31 @@ public class ModernCardRenderer extends CardRenderer {
int curY = cardHeight - (int) (0.03f * cardHeight);
// Width of the boxes
- int partWidth = (int) Math.max(30, 0.20f * cardWidth);
+ int partBoxWidth = (int) Math.max(30, 0.20f * cardWidth);
// Is it a creature?
boolean isVehicle = cardView.getSubTypes().contains(SubType.VEHICLE);
if (cardView.isCreature() || isVehicle) {
- int x = cardWidth - borderWidth - partWidth;
+
+ // draws p/t by parts
+ int ptDeviderSpace = 1; // Arial font is too narrow for devider (2/2) and needs extra space
+ String ptText1 = cardView.getPower();
+ String ptText2 = "/";
+ String ptText3 = CardRendererUtils.getCardLifeWithDamage(cardView);
+ int ptTextWidth1 = g.getFontMetrics(ptTextFont).stringWidth(ptText1);
+ int ptTextWidth2 = g.getFontMetrics(ptTextFont).stringWidth(ptText2) + 2 * ptDeviderSpace;
+ int ptTextWidth3 = g.getFontMetrics(ptTextFont).stringWidth(ptText3);
+
+ // PT max size
+ int ptContentWidth = contentInset + ptTextWidth1 + ptDeviderSpace + ptTextWidth2 + ptDeviderSpace + ptTextWidth3 + contentInset;
+ partBoxWidth = Math.max(ptContentWidth, partBoxWidth);
+
+ int x = cardWidth - borderWidth - partBoxWidth;
// Draw PT box
CardRendererUtils.drawRoundedBox(g,
x, curY - boxHeight,
- partWidth, boxHeight,
+ partBoxWidth, boxHeight,
contentInset,
borderPaint,
isVehicle ? BOX_VEHICLE : fill);
@@ -963,27 +1015,42 @@ public class ModernCardRenderer extends CardRenderer {
g.setColor(new Color(0, 0, 0, 150));
g.fillRect(
x + contentInset, curY - boxHeight - 1,
- partWidth - 2 * contentInset, 1);
+ partBoxWidth - 2 * contentInset, 1);
// Draw text
- Color textColor;
+ Color defaultTextColor;
+ boolean defaultTextLight;
if (isVehicle) {
boolean isAnimated = !(cardView instanceof PermanentView) || cardView.isCreature();
if (isAnimated) {
- textColor = Color.white;
+ defaultTextColor = Color.white;
} else {
- textColor = new Color(180, 180, 180);
+ defaultTextColor = new Color(180, 180, 180);
}
-
+ defaultTextLight = true;
} else {
- textColor = getBoxTextColor();
+ defaultTextColor = getBoxTextColor();
+ defaultTextLight = !defaultTextColor.equals(Color.black);
}
- g.setColor(textColor);
+ g.setColor(defaultTextColor);
g.setFont(ptTextFont);
- String ptText = cardView.getPower() + '/' + cardView.getToughness();
- int ptTextWidth = g.getFontMetrics().stringWidth(ptText);
- g.drawString(ptText,
- x + (partWidth - ptTextWidth) / 2, curY - ptTextOffset - 1);
+
+ // draws
+ int ptEmptySpace = (partBoxWidth - ptContentWidth) / 2;
+ int ptPosStart1 = x + contentInset + ptEmptySpace;
+ int ptPosStart2 = ptPosStart1 + ptTextWidth1 + ptDeviderSpace;
+ int ptPosStart3 = ptPosStart2 + ptTextWidth2 + ptDeviderSpace;
+ // p
+ g.setColor(CardRendererUtils.getCardTextColor(cardView.getOriginalCard().getPower(), false, defaultTextColor, defaultTextLight));
+ g.drawString(ptText1, ptPosStart1, curY - ptTextOffset - 1); // left
+ // /
+ g.setColor(defaultTextColor);
+ g.drawString(ptText2, ptPosStart2, curY - ptTextOffset - 1); // center
+ // t
+ g.setColor(CardRendererUtils.getCardTextColor(cardView.getOriginalCard().getPower(), CardRendererUtils.isCardWithDamage(cardView), defaultTextColor, defaultTextLight));
+ g.drawString(ptText3, ptPosStart3, curY - ptTextOffset - 1); // right
+ //
+ g.setColor(defaultTextColor);
// Advance
curY -= boxHeight;
@@ -994,9 +1061,9 @@ public class ModernCardRenderer extends CardRenderer {
if (cardView.isPlanesWalker()
&& (cardView instanceof PermanentView || !cardView.getStartingLoyalty().equals("0"))) {
// Draw the PW loyalty box
- int w = partWidth;
- int h = partWidth / 2;
- int x = cardWidth - partWidth - borderWidth;
+ int w = partBoxWidth;
+ int h = partBoxWidth / 2;
+ int x = cardWidth - partBoxWidth - borderWidth;
int y = curY - h;
Polygon symbol = new Polygon(
@@ -1047,16 +1114,16 @@ public class ModernCardRenderer extends CardRenderer {
// does it have damage on it?
if ((cardView instanceof PermanentView) && ((PermanentView) cardView).getDamage() > 0) {
- int x = cardWidth - partWidth - borderWidth;
+ int x = cardWidth - partBoxWidth - borderWidth;
int y = curY - boxHeight;
String damage = String.valueOf(((PermanentView) cardView).getDamage());
g.setFont(ptTextFont);
int txWidth = g.getFontMetrics().stringWidth(damage);
g.setColor(Color.red);
- g.fillRect(x, y, partWidth, boxHeight);
+ g.fillRect(x, y, partBoxWidth, boxHeight);
g.setColor(Color.white);
- g.drawRect(x, y, partWidth, boxHeight);
- g.drawString(damage, x + (partWidth - txWidth) / 2, curY - 1);
+ g.drawRect(x, y, partBoxWidth, boxHeight);
+ g.drawString(damage, x + (partBoxWidth - txWidth) / 2, curY - 1);
}
}
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java
index 4e690bf1a56..c43151d60ac 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java
@@ -2,7 +2,6 @@ package org.mage.plugins.card;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
-import mage.client.dialog.PreferencesDialog;
import mage.client.util.GUISizeHelper;
import mage.interfaces.plugin.CardPlugin;
import mage.view.CardView;
@@ -99,25 +98,28 @@ public class CardPluginImpl implements CardPlugin {
* Temporary card rendering shim. Split card rendering isn't implemented
* yet, so use old component based rendering for the split cards.
*/
- private CardPanel makePanel(CardView view, UUID gameId, boolean loadImage, ActionCallback callback, boolean isFoil, Dimension dimension) {
- String fallback = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_FALLBACK, "false");
- if (fallback.equals("true")) {
- return new CardPanelComponentImpl(view, gameId, loadImage, callback, isFoil, dimension);
- } else {
- return new CardPanelRenderImpl(view, gameId, loadImage, callback, isFoil, dimension);
+ private CardPanel makePanel(CardView view, UUID gameId, boolean loadImage, ActionCallback callback, boolean isFoil, Dimension dimension, int renderMode) {
+ switch (renderMode) {
+ case 0:
+ return new CardPanelRenderImpl(view, gameId, loadImage, callback, isFoil, dimension);
+ case 1:
+ return new CardPanelComponentImpl(view, gameId, loadImage, callback, isFoil, dimension);
+ default:
+ throw new IllegalStateException("Unknown render mode " + renderMode);
+
}
}
@Override
- public MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
- CardPanel cardPanel = makePanel(permanent, gameId, loadImage, callback, false, dimension);
+ public MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode) {
+ CardPanel cardPanel = makePanel(permanent, gameId, loadImage, callback, false, dimension, renderMode);
cardPanel.setShowCastingCost(true);
return cardPanel;
}
@Override
- public MagePermanent getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage) {
- CardPanel cardPanel = makePanel(cardView, gameId, loadImage, callback, false, dimension);
+ public MagePermanent getMageCard(CardView cardView, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode) {
+ CardPanel cardPanel = makePanel(cardView, gameId, loadImage, callback, false, dimension, renderMode);
cardPanel.setShowCastingCost(true);
return cardPanel;
}
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java
index c7dae393558..a22e0667b3f 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/utils/CardImageUtils.java
@@ -52,7 +52,7 @@ public final class CardImageUtils {
return filePath;
}
- log.warn("Token image file not found. Set: " + card.getSet() + " Token Set Code: " + card.getTokenSetCode() + " Name: " + card.getName() + " File path: " + getTokenImagePath(card));
+ //log.warn("Token image file not found. Set: " + card.getSet() + " Token Set Code: " + card.getTokenSetCode() + " Name: " + card.getName() + " File path: " + getTokenImagePath(card));
} else {
log.warn("Trying to get token path for non token card. Set: " + card.getSet() + " Set Code: " + card.getTokenSetCode() + " Name: " + card.getName());
}
diff --git a/Mage.Client/src/main/resources/cardrender/beleren-bold.ttf b/Mage.Client/src/main/resources/cardrender/beleren-bold.ttf
deleted file mode 100644
index 7dd1bff6a75..00000000000
Binary files a/Mage.Client/src/main/resources/cardrender/beleren-bold.ttf and /dev/null differ
diff --git a/Mage.Common/src/main/java/mage/interfaces/plugin/CardPlugin.java b/Mage.Common/src/main/java/mage/interfaces/plugin/CardPlugin.java
index 7aab71f8b5f..138c71073f3 100644
--- a/Mage.Common/src/main/java/mage/interfaces/plugin/CardPlugin.java
+++ b/Mage.Common/src/main/java/mage/interfaces/plugin/CardPlugin.java
@@ -1,30 +1,28 @@
package mage.interfaces.plugin;
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.util.Map;
-import java.util.UUID;
-import javax.swing.*;
import mage.cards.MagePermanent;
import mage.cards.action.ActionCallback;
import mage.view.CardView;
import mage.view.PermanentView;
import net.xeoh.plugins.base.Plugin;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.util.Map;
+import java.util.UUID;
+
/**
* Interface for card plugins
*
- * @version 0.6 17.07.2011 added options to #sortPermanents
- * @version 0.3 21.11.2010 #getMageCard
- * @version 0.2 07.11.2010 #downloadImages
- * @version 0.1 31.10.2010 #getMagePermanent, #sortPermanents
* @author nantuko
+ * @version 0.1 31.10.2010 #getMagePermanent, #sortPermanents
*/
public interface CardPlugin extends Plugin {
- MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage);
+ MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode);
- MagePermanent getMageCard(CardView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage);
+ MagePermanent getMageCard(CardView permanent, Dimension dimension, UUID gameId, ActionCallback callback, boolean canBeFoil, boolean loadImage, int renderMode);
int sortPermanents(Map ui, Map cards, boolean nonPermanentsOwnRow, boolean topPanel);
diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java
index cbf339b7796..858c0dc6eb3 100644
--- a/Mage.Common/src/main/java/mage/utils/MageVersion.java
+++ b/Mage.Common/src/main/java/mage/utils/MageVersion.java
@@ -13,9 +13,9 @@ public class MageVersion implements Serializable, Comparable {
public static final int MAGE_VERSION_MINOR = 4;
public static final int MAGE_VERSION_PATCH = 35;
public static final String MAGE_EDITION_INFO = ""; // set "-beta" for 1.4.32-betaV0
- public static final String MAGE_VERSION_MINOR_PATCH = "V2"; // default
+ public static final String MAGE_VERSION_MINOR_PATCH = "V5"; // default
// strict mode
- private static final boolean MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME = false; // set true on uncompatible github changes, set false after new major release (after MAGE_VERSION_PATCH changes)
+ private static final boolean MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME = true; // set true on uncompatible github changes, set false after new major release (after MAGE_VERSION_PATCH changes)
public static final boolean MAGE_VERSION_SHOW_BUILD_TIME = true;
private final int major;
diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/pom.xml
new file mode 100644
index 00000000000..96f60f12a15
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/pom.xml
@@ -0,0 +1,50 @@
+
+
+
+ 4.0.0
+
+
+ org.mage
+ mage-server-plugins
+ 1.4.35
+
+
+ mage-game-freeformcommanderduel
+ jar
+ Mage Game Freeform Commander Two Player
+
+
+
+ ${project.groupId}
+ mage
+ ${project.version}
+
+
+
+
+ src
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+
+
+ maven-resources-plugin
+
+ UTF-8
+
+
+
+
+
+ mage-game-freeformcommanderduel
+
+
+
+
+
diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuel.java b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuel.java
new file mode 100644
index 00000000000..d57f520f079
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuel.java
@@ -0,0 +1,36 @@
+package mage.game;
+
+import mage.constants.MultiplayerAttackOption;
+import mage.constants.RangeOfInfluence;
+import mage.game.match.MatchType;
+import mage.game.mulligan.Mulligan;
+
+/**
+ * @author JayDi85
+ */
+public class FreeformCommanderDuel extends GameCommanderImpl {
+
+ public FreeformCommanderDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
+ super(attackOption, range, mulligan, startLife);
+ }
+
+ public FreeformCommanderDuel(final FreeformCommanderDuel game) {
+ super(game);
+ }
+
+ @Override
+ public MatchType getGameType() {
+ return new FreeformCommanderDuelType();
+ }
+
+ @Override
+ public int getNumPlayers() {
+ return 2;
+ }
+
+ @Override
+ public FreeformCommanderDuel copy() {
+ return new FreeformCommanderDuel(this);
+ }
+
+}
diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelMatch.java b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelMatch.java
new file mode 100644
index 00000000000..1f3e141929d
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelMatch.java
@@ -0,0 +1,31 @@
+package mage.game;
+
+import mage.game.match.MatchImpl;
+import mage.game.match.MatchOptions;
+import mage.game.mulligan.Mulligan;
+
+/**
+ * @author JayDi85
+ */
+public class FreeformCommanderDuelMatch extends MatchImpl {
+
+ public FreeformCommanderDuelMatch(MatchOptions options) {
+ super(options);
+ }
+
+ @Override
+ public void startGame() throws GameException {
+ int startLife = 20;
+ boolean alsoHand = true;
+ boolean checkCommanderDamage = true;
+
+ Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans());
+ FreeformCommanderDuel game = new FreeformCommanderDuel(options.getAttackOption(), options.getRange(), mulligan, startLife);
+ game.setCheckCommanderDamage(checkCommanderDamage);
+ game.setStartMessage(this.createGameStartMessage());
+ game.setAlsoHand(alsoHand);
+ game.setAlsoLibrary(true);
+ initGame(game);
+ games.add(game);
+ }
+}
diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelType.java b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelType.java
new file mode 100644
index 00000000000..586617ee518
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelType.java
@@ -0,0 +1,29 @@
+package mage.game;
+
+import mage.game.match.MatchType;
+
+/**
+ * @author JayDi85
+ */
+public class FreeformCommanderDuelType extends MatchType {
+
+ public FreeformCommanderDuelType() {
+ this.name = "Freeform Commander Two Player Duel";
+ this.maxPlayers = 2;
+ this.minPlayers = 2;
+ this.numTeams = 0;
+ this.useAttackOption = false;
+ this.useRange = false;
+ this.sideboardingAllowed = false;
+ }
+
+ protected FreeformCommanderDuelType(final FreeformCommanderDuelType matchType) {
+ super(matchType);
+ }
+
+ @Override
+ public FreeformCommanderDuelType copy() {
+ return new FreeformCommanderDuelType(this);
+ }
+
+}
diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java
index 879718fdc10..3e6603d7b93 100644
--- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java
+++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java
@@ -669,12 +669,26 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (target.getOriginalTarget() instanceof TargetPlayerOrPlaneswalker) {
List targets;
TargetPlayerOrPlaneswalker origTarget = ((TargetPlayerOrPlaneswalker) target);
+
+ // TODO: if effect is bad and no opponent's targets available then AI can't target yourself but must by rules
+ /*
+ battlefield:Computer:Mountain:5
+ hand:Computer:Viashino Pyromancer:3
+ battlefield:Human:Shalai, Voice of Plenty:1
+ */
+ // TODO: in multiplayer game there many opponents - if random opponents don't have targets then AI must use next opponent, but it skips
+ // (e.g. you randomOpponentId must be replaced by List randomOpponents)
+
+ // normal cycle (good for you, bad for opponents)
+
+ // possible good/bad permanents
if (outcome.isGood()) {
targets = threats(abilityControllerId, source.getSourceId(), ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
} else {
targets = threats(randomOpponentId, source.getSourceId(), ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets());
}
+ // possible good/bad players
if (targets.isEmpty()) {
if (outcome.isGood()) {
if (target.canTarget(getId(), abilityControllerId, source, game)) {
@@ -685,9 +699,12 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
+ // can't find targets (e.g. effect is bad, but you need take targets from yourself)
if (targets.isEmpty() && target.isRequired(source)) {
- targets = game.getBattlefield().getActivePermanents(((TargetPlayerOrPlaneswalker) origTarget.getFilter()).getFilterPermanent(), playerId, game);
+ targets = game.getBattlefield().getActivePermanents(origTarget.getFilterPermanent(), playerId, game);
}
+
+ // try target permanent
for (Permanent permanent : targets) {
List alreadyTargeted = target.getTargets();
if (target.canTarget(abilityControllerId, permanent.getId(), source, game)) {
@@ -697,6 +714,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
+ // try target player as normal
if (outcome.isGood()) {
if (target.canTarget(getId(), abilityControllerId, source, game)) {
return tryAddTarget(target, abilityControllerId, source, game);
diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml
index cf0611b51e3..248976e2124 100644
--- a/Mage.Server.Plugins/pom.xml
+++ b/Mage.Server.Plugins/pom.xml
@@ -25,8 +25,9 @@
Mage.Game.TinyLeadersDuel
Mage.Game.CanadianHighlanderDuel
Mage.Game.PennyDreadfulCommanderFreeForAll
- Mage.Game.FreeformCommanderFreeForAll
- Mage.Game.BrawlDuel
+ Mage.Game.FreeformCommanderDuel
+ Mage.Game.FreeformCommanderFreeForAll
+ Mage.Game.BrawlDuel
Mage.Game.BrawlFreeForAll
Mage.Game.TwoPlayerDuel
Mage.Player.AI
diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml
index 0475c3cbe67..aa2223ceab4 100644
--- a/Mage.Server/config/config.xml
+++ b/Mage.Server/config/config.xml
@@ -79,6 +79,7 @@
+
diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml
index 9386469d6c0..72d63a77d60 100644
--- a/Mage.Server/pom.xml
+++ b/Mage.Server/pom.xml
@@ -184,6 +184,12 @@
${project.version}
runtime
+
+ ${project.groupId}
+ mage-game-freeformcommanderduel
+ ${project.version}
+ runtime
+
${project.groupId}
diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml
index 2a294b3093d..bea0cd3d653 100644
--- a/Mage.Server/release/config/config.xml
+++ b/Mage.Server/release/config/config.xml
@@ -73,6 +73,7 @@
+
diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java
index 382021e4cf6..ae2a758128b 100644
--- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java
+++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java
@@ -12,6 +12,7 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
+import mage.game.GameCommanderImpl;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.RandomUtil;
@@ -31,7 +32,8 @@ import java.util.stream.Collectors;
*/
public final class SystemUtil {
- private SystemUtil(){}
+ private SystemUtil() {
+ }
public static final DateFormat dateFormat = new SimpleDateFormat("yy-M-dd HH:mm:ss");
@@ -485,6 +487,8 @@ public final class SystemUtil {
gameZone = Zone.COMMAND;
} else if ("plane".equalsIgnoreCase(command.zone)) {
gameZone = Zone.COMMAND;
+ } else if ("commander".equalsIgnoreCase(command.zone)) {
+ gameZone = Zone.COMMAND;
} else {
logger.warn("Unknown zone [" + command.zone + "]: " + line);
continue;
@@ -513,8 +517,23 @@ public final class SystemUtil {
}
}
game.loadCards(cardsToLoad, player.getId());
- for (Card card : cardsToLoad) {
- swapWithAnyCard(game, player, card, gameZone);
+
+ if ("commander".equalsIgnoreCase(command.zone) && cardsToLoad.size() > 0) {
+ // as commander (only commander games, look at init code in GameCommanderImpl)
+ if (game instanceof GameCommanderImpl) {
+ GameCommanderImpl gameCommander = (GameCommanderImpl) game;
+ for (Card card : cardsToLoad) {
+ player.addCommanderId(card.getId());
+ gameCommander.initCommander(card, player);
+ }
+ } else {
+ logger.fatal("Commander card can be used in commander game only: " + command.cardName);
+ }
+ } else {
+ // as other card
+ for (Card card : cardsToLoad) {
+ swapWithAnyCard(game, player, card, gameZone);
+ }
}
}
} catch (Exception e) {
diff --git a/Mage.Sets/src/mage/cards/a/AllHallowsEve.java b/Mage.Sets/src/mage/cards/a/AllHallowsEve.java
index e033af793ad..d61463522c9 100644
--- a/Mage.Sets/src/mage/cards/a/AllHallowsEve.java
+++ b/Mage.Sets/src/mage/cards/a/AllHallowsEve.java
@@ -1,7 +1,5 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
@@ -9,7 +7,9 @@ import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSpellEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
-import mage.cards.*;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
@@ -19,8 +19,9 @@ import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
*/
public final class AllHallowsEve extends CardImpl {
@@ -72,7 +73,7 @@ class AllHallowsEveEffect extends OneShotEffect {
if (allHallowsEve != null
&& controller != null
&& game.getExile().getCard(allHallowsEve.getId(), game) != null) {
- allHallowsEve.getCounters(game).removeCounter(CounterType.SCREAM, 1);
+ allHallowsEve.removeCounters(CounterType.SCREAM.getName(), 1, game);
if (allHallowsEve.getCounters(game).getCount(CounterType.SCREAM) == 0) {
allHallowsEve.moveToZone(Zone.GRAVEYARD, source.getId(), game, false);
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
diff --git a/Mage.Sets/src/mage/cards/a/ArmoryAutomaton.java b/Mage.Sets/src/mage/cards/a/ArmoryAutomaton.java
index f4fe5b25bb4..f56d6acc10b 100644
--- a/Mage.Sets/src/mage/cards/a/ArmoryAutomaton.java
+++ b/Mage.Sets/src/mage/cards/a/ArmoryAutomaton.java
@@ -88,7 +88,9 @@ class ArmoryAutomatonEffect extends OneShotEffect {
while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.Benefit, "Select and attach a target Equipment?", source, game)) {
Target targetEquipment = new TargetPermanent(currentFilter);
targetEquipment.setRequired(false);
- if (player.choose(Outcome.Benefit, targetEquipment, source.getSourceId(), game)) {
+ if (player.choose(Outcome.Benefit, targetEquipment, source.getSourceId(), game) && targetEquipment.getFirstTarget() != null) {
+ currentFilter.add(Predicates.not(new PermanentIdPredicate(targetEquipment.getFirstTarget()))); // exclude selected for next time
+
Permanent aura = game.getPermanent(targetEquipment.getFirstTarget());
if (aura != null) {
Permanent attachedTo = game.getPermanent(aura.getAttachedTo());
@@ -96,10 +98,9 @@ class ArmoryAutomatonEffect extends OneShotEffect {
attachedTo.removeAttachment(aura.getId(), game);
}
sourcePermanent.addAttachment(aura.getId(), game);
-
- // exclude selected
- currentFilter.add(Predicates.not(new PermanentIdPredicate(aura.getId())));
}
+ } else {
+ break;
}
countBattlefield = game.getBattlefield().getAllActivePermanents(currentFilter, game).size();
}
diff --git a/Mage.Sets/src/mage/cards/a/AshiokDreamRender.java b/Mage.Sets/src/mage/cards/a/AshiokDreamRender.java
index 9b383b89f57..ac680020c0d 100644
--- a/Mage.Sets/src/mage/cards/a/AshiokDreamRender.java
+++ b/Mage.Sets/src/mage/cards/a/AshiokDreamRender.java
@@ -7,6 +7,7 @@ import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.common.ExileGraveyardAllPlayersEffect;
+import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@@ -17,8 +18,6 @@ import mage.players.Player;
import mage.target.TargetPlayer;
import java.util.UUID;
-import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect;
-import mage.target.TargetPlayer;
/**
* @author TheElk801
@@ -37,7 +36,6 @@ public final class AshiokDreamRender extends CardImpl {
// -1: Target player puts the top four cards of their library into their graveyard. Then exile each opponent's graveyard.
Ability ability = new LoyaltyAbility(new PutLibraryIntoGraveTargetEffect(4), -1);
- ability.addTarget(new TargetPlayer());
ability.addEffect(new ExileGraveyardAllPlayersEffect(StaticFilters.FILTER_CARD, TargetController.OPPONENT).setText("Then exile each opponent's graveyard."));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/a/Aurification.java b/Mage.Sets/src/mage/cards/a/Aurification.java
index ef96fbf8ceb..3d85d0f83e7 100644
--- a/Mage.Sets/src/mage/cards/a/Aurification.java
+++ b/Mage.Sets/src/mage/cards/a/Aurification.java
@@ -1,7 +1,5 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
@@ -24,8 +22,9 @@ import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
import mage.util.SubTypeList;
+import java.util.UUID;
+
/**
- *
* @author andyfries
*/
@@ -40,7 +39,7 @@ public final class Aurification extends CardImpl {
static final String rule = "Each creature with a gold counter on it is a Wall in addition to its other creature types and has defender.";
public Aurification(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
// Whenever a creature deals damage to you, put a gold counter on it.
this.addAbility(new AddGoldCountersAbility());
@@ -127,8 +126,11 @@ public final class Aurification extends CardImpl {
@Override
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(CardType.CREATURE)) {
- if (permanent != null){
- permanent.getCounters(game).removeAllCounters(CounterType.GOLD);
+ if (permanent != null) {
+ int numToRemove = permanent.getCounters(game).getCount(CounterType.GOLD);
+ if (numToRemove > 0) {
+ permanent.removeCounters(CounterType.GOLD.getName(), numToRemove, game);
+ }
}
}
return true;
diff --git a/Mage.Sets/src/mage/cards/b/BolassCitadel.java b/Mage.Sets/src/mage/cards/b/BolassCitadel.java
index f7f617045d1..b66b461f2bf 100644
--- a/Mage.Sets/src/mage/cards/b/BolassCitadel.java
+++ b/Mage.Sets/src/mage/cards/b/BolassCitadel.java
@@ -23,6 +23,7 @@ import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
+import mage.abilities.costs.Cost;
/**
* @author jeffwadsworth
@@ -98,9 +99,16 @@ class BolassCitadelPlayTheTopCardEffect extends AsThoughEffectImpl {
Player controller = game.getPlayer(cardOnTop.getOwnerId());
if (controller != null
&& cardOnTop.equals(controller.getLibrary().getFromTop(game))) {
+ // add the life cost first
PayLifeCost cost = new PayLifeCost(cardOnTop.getManaCost().convertedManaCost());
Costs costs = new CostsImpl();
costs.add(cost);
+ // check for additional costs that must be paid
+ if (cardOnTop.getSpellAbility() != null) {
+ for (Cost additionalCost : cardOnTop.getSpellAbility().getCosts()) {
+ costs.add(additionalCost);
+ }
+ }
controller.setCastSourceIdWithAlternateMana(cardOnTop.getId(), null, costs);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/b/BosiumStrip.java b/Mage.Sets/src/mage/cards/b/BosiumStrip.java
new file mode 100644
index 00000000000..1a008842c76
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BosiumStrip.java
@@ -0,0 +1,142 @@
+
+package mage.cards.b;
+
+import java.util.UUID;
+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.AsThoughEffectImpl;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.keyword.FlashbackAbility;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.AsThoughEffectType;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.ZoneChangeEvent;
+import mage.players.Player;
+import mage.watchers.common.CastFromGraveyardWatcher;
+
+/**
+ *
+ * @author spjspj & L_J
+ */
+public final class BosiumStrip extends CardImpl {
+
+ public BosiumStrip(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
+
+ // {3}, {T}: Until end of turn, if the top card of your graveyard is an instant or sorcery card, you may cast that card. If a card cast this way would be put into a graveyard this turn, exile it instead.
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BosiumStripCastFromGraveyardEffect(), new ManaCostsImpl("{3}"));
+ ability.addCost(new TapSourceCost());
+ ability.addEffect(new BosiumStripReplacementEffect());
+ this.addAbility(ability, new CastFromGraveyardWatcher());
+ }
+
+ public BosiumStrip(final BosiumStrip card) {
+ super(card);
+ }
+
+ @Override
+ public BosiumStrip copy() {
+ return new BosiumStrip(this);
+ }
+}
+
+class BosiumStripCastFromGraveyardEffect extends AsThoughEffectImpl {
+
+ BosiumStripCastFromGraveyardEffect() {
+ super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
+ staticText = "Until end of turn, if the top card of your graveyard is an instant or sorcery card, you may cast that card";
+ }
+
+ BosiumStripCastFromGraveyardEffect(final BosiumStripCastFromGraveyardEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public BosiumStripCastFromGraveyardEffect copy() {
+ return new BosiumStripCastFromGraveyardEffect(this);
+ }
+
+ @Override
+ public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
+ if (!(source instanceof FlashbackAbility)
+ && affectedControllerId.equals(source.getControllerId())) {
+ Player player = game.getPlayer(affectedControllerId);
+ Card card = game.getCard(objectId);
+ if (card != null
+ && player != null
+ && card.equals(player.getGraveyard().getTopCard(game))
+ && StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(card, game)
+ && game.getState().getZone(objectId) == Zone.GRAVEYARD) {
+ game.getState().setValue("BosiumStrip", card);
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+class BosiumStripReplacementEffect extends ReplacementEffectImpl {
+
+ BosiumStripReplacementEffect() {
+ super(Duration.EndOfTurn, Outcome.Exile);
+ staticText = "If a card cast this way would be put into a graveyard this turn, exile it instead";
+ }
+
+ BosiumStripReplacementEffect(final BosiumStripReplacementEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public BosiumStripReplacementEffect copy() {
+ return new BosiumStripReplacementEffect(this);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ Card card = (Card) game.getState().getValue("BosiumStrip");
+ if (card != null) {
+ controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.STACK, true);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ZONE_CHANGE;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
+ if (zEvent.getToZone() == Zone.GRAVEYARD) {
+ Card card = game.getCard(event.getSourceId());
+ if (card != null
+ && StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY.match(card, game)) {
+ CastFromGraveyardWatcher watcher = game.getState().getWatcher(CastFromGraveyardWatcher.class);
+ return watcher != null
+ && watcher.spellWasCastFromGraveyard(event.getTargetId(),
+ game.getState().getZoneChangeCounter(event.getTargetId()));
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java b/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java
index 21da232f164..f442083da90 100644
--- a/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java
+++ b/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java
@@ -1,4 +1,3 @@
-
package mage.cards.b;
import java.util.UUID;
@@ -13,7 +12,7 @@ import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
-import mage.filter.predicate.permanent.ControllerPredicate;
+import mage.filter.predicate.other.OwnerPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -28,23 +27,24 @@ import mage.players.Player;
*/
public final class BridgeFromBelow extends CardImpl {
-
private static final FilterCreaturePermanent filter1 = new FilterCreaturePermanent("Whenever a nontoken creature is put into your graveyard from the battlefield");
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("When a creature is put into an opponent's graveyard from the battlefield");
-
- static{
- filter1.add(new ControllerPredicate(TargetController.YOU));
+
+ static {
+ filter1.add(new OwnerPredicate(TargetController.YOU));
filter1.add(Predicates.not(TokenPredicate.instance));
- filter2.add(new ControllerPredicate(TargetController.OPPONENT));
+ filter2.add(new OwnerPredicate(TargetController.OPPONENT));
}
-
+
public BridgeFromBelow(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{B}{B}");
// Whenever a nontoken creature is put into your graveyard from the battlefield, if Bridge from Below is in your graveyard, create a 2/2 black Zombie creature token.
this.addAbility(new BridgeFromBelowAbility(new CreateTokenEffect(new ZombieToken()), filter1));
+
// When a creature is put into an opponent's graveyard from the battlefield, if Bridge from Below is in your graveyard, exile Bridge from Below.
this.addAbility(new BridgeFromBelowAbility(new ExileSourceEffect(), filter2));
+
}
public BridgeFromBelow(final BridgeFromBelow card) {
@@ -86,7 +86,8 @@ class BridgeFromBelowAbility extends TriggeredAbilityImpl {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent()) {
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
- if (permanent != null && filter.match(permanent, sourceId, controllerId, game)) {
+ if (permanent != null
+ && filter.match(permanent, sourceId, controllerId, game)) {
return true;
}
}
@@ -96,11 +97,12 @@ class BridgeFromBelowAbility extends TriggeredAbilityImpl {
@Override
public boolean checkInterveningIfClause(Game game) {
Player controller = game.getPlayer(this.getControllerId());
- return controller != null && controller.getGraveyard().contains(this.getSourceId());
+ return controller != null
+ && controller.getGraveyard().contains(this.getSourceId());
}
-
+
@Override
public String getRule() {
- return filter.getMessage() +", if {this} is in your graveyard, " + super.getRule();
+ return filter.getMessage() + ", if {this} is in your graveyard, " + super.getRule();
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CorpsejackMenace.java b/Mage.Sets/src/mage/cards/c/CorpsejackMenace.java
index cb0f555675a..5032f414fce 100644
--- a/Mage.Sets/src/mage/cards/c/CorpsejackMenace.java
+++ b/Mage.Sets/src/mage/cards/c/CorpsejackMenace.java
@@ -1,29 +1,25 @@
-
package mage.cards.c;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
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.constants.*;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
+import java.util.UUID;
+
/**
* http://www.wizards.com/magic/magazine/article.aspx?x=mtg/faq/rtr
- *
+ *
* If a creature you control would enter the battlefield with a number of +1/+1
* counters on it, it enters with twice that many instead.
- *
+ *
* If you control two Corpsejack Menaces, the number of +1/+1 counters placed is
* four times the original number. Three Corpsejack Menaces multiplies the
* original number by eight, and so on.
@@ -33,7 +29,7 @@ import mage.game.permanent.Permanent;
public final class CorpsejackMenace extends CardImpl {
public CorpsejackMenace(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{G}");
this.subtype.add(SubType.FUNGUS);
this.power = new MageInt(4);
@@ -67,7 +63,7 @@ class CorpsejackMenaceReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- event.setAmount(event.getAmount() * 2);
+ event.setAmountForCounters(event.getAmount() * 2, true);
return false;
}
@@ -78,15 +74,13 @@ class CorpsejackMenaceReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
- if (event.getData().equals(CounterType.P1P1.getName())) {
+ if (event.getData().equals(CounterType.P1P1.getName()) && event.getAmount() > 0) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent == null) {
permanent = game.getPermanentEntering(event.getTargetId());
}
- if (permanent != null && permanent.isControlledBy(source.getControllerId())
- && permanent.isCreature()) {
- return true;
- }
+ return permanent != null && permanent.isControlledBy(source.getControllerId())
+ && permanent.isCreature();
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/c/CrovaxTheCursed.java b/Mage.Sets/src/mage/cards/c/CrovaxTheCursed.java
index a1f7a602a2f..a7598d50587 100644
--- a/Mage.Sets/src/mage/cards/c/CrovaxTheCursed.java
+++ b/Mage.Sets/src/mage/cards/c/CrovaxTheCursed.java
@@ -1,7 +1,5 @@
-
package mage.cards.c;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@@ -22,14 +20,15 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class CrovaxTheCursed extends CardImpl {
public CrovaxTheCursed(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.VAMPIRE);
this.power = new MageInt(0);
@@ -82,7 +81,7 @@ class CrovaxTheCursedEffect extends OneShotEffect {
if (creatures > 0 && controller.chooseUse(outcome, "Sacrifice a creature?", source, game)) {
if (new SacrificeControllerEffect(StaticFilters.FILTER_PERMANENT_CREATURES, 1, "").apply(game, source)) {
if (sourceObject != null) {
- sourceObject.getCounters(game).addCounter(CounterType.P1P1.createInstance());
+ sourceObject.addCounters(CounterType.P1P1.createInstance(), source, game);
game.informPlayers(controller.getLogName() + " puts a +1/+1 counter on " + sourceObject.getName());
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CurseOfPredation.java b/Mage.Sets/src/mage/cards/c/CurseOfPredation.java
index a130d376858..7616a3cc564 100644
--- a/Mage.Sets/src/mage/cards/c/CurseOfPredation.java
+++ b/Mage.Sets/src/mage/cards/c/CurseOfPredation.java
@@ -1,4 +1,3 @@
-
package mage.cards.c;
import java.util.UUID;
@@ -29,10 +28,9 @@ import mage.target.targetpointer.FixedTarget;
public final class CurseOfPredation extends CardImpl {
public CurseOfPredation(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
this.subtype.add(SubType.AURA, SubType.CURSE);
-
// Enchant player
TargetPlayer auraTarget = new TargetPlayer();
this.getSpellAbility().addTarget(auraTarget);
@@ -75,17 +73,11 @@ class CurseOfPredationTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Player defender = game.getPlayer(event.getTargetId());
- if (defender == null) {
- Permanent planeswalker = game.getPermanent(event.getTargetId());
- if (planeswalker != null) {
- defender = game.getPlayer(planeswalker.getControllerId());
- }
- }
if (defender != null) {
Permanent enchantment = game.getPermanent(this.getSourceId());
if (enchantment != null
&& enchantment.isAttachedTo(defender.getId())) {
- for (Effect effect: this.getEffects()) {
+ for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(event.getSourceId()));
}
return true;
diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java b/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java
index 18040ebb79d..1d12b1daf59 100644
--- a/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java
+++ b/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java
@@ -1,4 +1,3 @@
-
package mage.cards.c;
import mage.abilities.Ability;
@@ -29,16 +28,16 @@ import java.util.UUID;
public final class CurseOfTheBloodyTome extends CardImpl {
public CurseOfTheBloodyTome(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
this.subtype.add(SubType.AURA, SubType.CURSE);
-
// Enchant player
TargetPlayer target = new TargetPlayer();
this.getSpellAbility().addTarget(target);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility));
Ability ability = new EnchantAbility(target.getTargetName());
this.addAbility(ability);
+
// At the beginning of enchanted player's upkeep, that player puts the top two cards of their library into their graveyard.
this.addAbility(new CurseOfTheBloodyTomeAbility());
diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java b/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java
index 8e2ab315d4e..0c4554afc9d 100644
--- a/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java
+++ b/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java
@@ -1,4 +1,3 @@
-
package mage.cards.c;
import mage.abilities.Ability;
@@ -42,10 +41,13 @@ public final class CurseOfTheCabal extends CardImpl {
// Target player sacrifices half the permanents he or she controls, rounded down.
this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().addEffect(new CurseOfTheCabalSacrificeEffect());
+
// Suspend 2-{2}{B}{B}
this.addAbility(new SuspendAbility(2, new ManaCostsImpl("{2}{B}{B}"), this));
+
// At the beginning of each player's upkeep, if Curse of the Cabal is suspended, that player may sacrifice a permanent. If he or she does, put two time counters on Curse of the Cabal.
this.addAbility(new CurseOfTheCabalInterveningIfTriggeredAbility());
+
}
public CurseOfTheCabal(final CurseOfTheCabal card) {
@@ -84,7 +86,8 @@ class CurseOfTheCabalSacrificeEffect extends OneShotEffect {
}
Target target = new TargetControlledPermanent(amount, amount, StaticFilters.FILTER_CONTROLLED_PERMANENT, true);
if (target.canChoose(targetPlayer.getId(), game)) {
- while (!target.isChosen() && target.canChoose(targetPlayer.getId(), game) && targetPlayer.canRespond()) {
+ while (!target.isChosen()
+ && target.canChoose(targetPlayer.getId(), game) && targetPlayer.canRespond()) {
targetPlayer.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
}
//sacrifice all chosen (non null) permanents
@@ -107,7 +110,9 @@ class CurseOfTheCabalInterveningIfTriggeredAbility extends ConditionalIntervenin
TargetController.ANY, false, true
),
SuspendedCondition.instance,
- "At the beginning of each player's upkeep, if {this} is suspended, that player may sacrifice a permanent. If he or she does, put two time counters on {this}."
+ "At the beginning of each player's upkeep, if {this} is suspended, "
+ + "that player may sacrifice a permanent. If he or she does, "
+ + "put two time counters on {this}."
);
// controller has to sac a permanent
// counters aren't placed
diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheForsaken.java b/Mage.Sets/src/mage/cards/c/CurseOfTheForsaken.java
index f240a0e5d6f..ee09485bc1f 100644
--- a/Mage.Sets/src/mage/cards/c/CurseOfTheForsaken.java
+++ b/Mage.Sets/src/mage/cards/c/CurseOfTheForsaken.java
@@ -1,4 +1,3 @@
-
package mage.cards.c;
import mage.abilities.TriggeredAbilityImpl;
@@ -29,7 +28,7 @@ import java.util.UUID;
public final class CurseOfTheForsaken extends CardImpl {
public CurseOfTheForsaken(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
this.subtype.add(SubType.AURA, SubType.CURSE);
// Enchant player
@@ -40,6 +39,7 @@ public final class CurseOfTheForsaken extends CardImpl {
// Whenever a creature attacks enchanted player, its controller gains 1 life.
this.addAbility(new CurseOfTheForsakenTriggeredAbility());
+
}
public CurseOfTheForsaken(final CurseOfTheForsaken card) {
@@ -74,12 +74,6 @@ class CurseOfTheForsakenTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Player defender = game.getPlayer(event.getTargetId());
- if (defender == null) {
- Permanent planeswalker = game.getPermanent(event.getTargetId());
- if (planeswalker != null) {
- defender = game.getPlayer(planeswalker.getControllerId());
- }
- }
if (defender != null) {
Permanent enchantment = game.getPermanent(this.getSourceId());
if (enchantment != null
diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java b/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java
index 6332c7987e7..ece104889a3 100644
--- a/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java
+++ b/Mage.Sets/src/mage/cards/c/CurseOfTheSwine.java
@@ -1,4 +1,3 @@
-
package mage.cards.c;
import mage.abilities.Ability;
@@ -29,8 +28,10 @@ public final class CurseOfTheSwine extends CardImpl {
// Exile X target creatures. For each creature exiled this way, its controller creates a 2/2 green Boar creature token.
this.getSpellAbility().addEffect(new CurseOfTheSwineEffect());
+
// Correct number of targets will be set in adjustTargets
this.getSpellAbility().setTargetAdjuster(CurseOfTheSwineAdjuster.instance);
+
}
public CurseOfTheSwine(final CurseOfTheSwine card) {
@@ -57,7 +58,8 @@ class CurseOfTheSwineEffect extends OneShotEffect {
public CurseOfTheSwineEffect() {
super(Outcome.Exile);
- this.staticText = "Exile X target creatures. For each creature exiled this way, its controller creates a 2/2 green Boar creature token";
+ this.staticText = "Exile X target creatures. For each creature exiled this way, "
+ + "its controller creates a 2/2 green Boar creature token";
}
public CurseOfTheSwineEffect(final CurseOfTheSwineEffect effect) {
@@ -78,13 +80,15 @@ class CurseOfTheSwineEffect extends OneShotEffect {
Permanent creature = game.getPermanent(targetId);
if (creature != null) {
if (controller.moveCards(creature, Zone.EXILED, source, game)) {
- playersWithTargets.put(creature.getControllerId(), playersWithTargets.getOrDefault(creature.getControllerId(), 0) + 1);
+ playersWithTargets.put(creature.getControllerId(),
+ playersWithTargets.getOrDefault(creature.getControllerId(), 0) + 1);
}
}
}
CurseOfTheSwineBoarToken swineToken = new CurseOfTheSwineBoarToken();
for (Map.Entry exiledByController : playersWithTargets.entrySet()) {
- swineToken.putOntoBattlefield(exiledByController.getValue(), game, source.getSourceId(), exiledByController.getKey());
+ swineToken.putOntoBattlefield(exiledByController.getValue(),
+ game, source.getSourceId(), exiledByController.getKey());
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/c/CurseOfThirst.java b/Mage.Sets/src/mage/cards/c/CurseOfThirst.java
index 97c1c9c1eac..05e564079e5 100644
--- a/Mage.Sets/src/mage/cards/c/CurseOfThirst.java
+++ b/Mage.Sets/src/mage/cards/c/CurseOfThirst.java
@@ -1,4 +1,3 @@
-
package mage.cards.c;
import mage.abilities.Ability;
@@ -31,10 +30,9 @@ import java.util.UUID;
public final class CurseOfThirst extends CardImpl {
public CurseOfThirst(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{B}");
this.subtype.add(SubType.AURA, SubType.CURSE);
-
// Enchant player
TargetPlayer auraTarget = new TargetPlayer();
this.getSpellAbility().addTarget(auraTarget);
@@ -91,7 +89,8 @@ class CurseOfThirstAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "At the beginning of enchanted player's upkeep, Curse of Thirst deals damage to that player equal to the number of Curses attached to him or her.";
+ return "At the beginning of enchanted player's upkeep, Curse of Thirst "
+ + "deals damage to that player equal to the number of Curses attached to him or her.";
}
}
@@ -108,10 +107,11 @@ class CursesAttachedCount implements DynamicValue {
if (enchantment != null && enchantment.getAttachedTo() != null) {
Player player = game.getPlayer(enchantment.getAttachedTo());
if (player != null) {
- for (UUID attachmentId: player.getAttachments()) {
+ for (UUID attachmentId : player.getAttachments()) {
Permanent attachment = game.getPermanent(attachmentId);
- if (attachment != null && attachment.hasSubtype(SubType.CURSE, game))
+ if (attachment != null && attachment.hasSubtype(SubType.CURSE, game)) {
count++;
+ }
}
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java b/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java
index 318a99d37e8..e12fb3e6da9 100644
--- a/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java
+++ b/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java
@@ -1,4 +1,3 @@
-
package mage.cards.c;
import java.util.UUID;
@@ -130,7 +129,8 @@ class CurseOfVengeancePlayerLosesTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "When enchanted player loses the game, you gain X life and draw X cards, where X is the number of spite counters on {this}";
+ return "When enchanted player loses the game, you gain X life and "
+ + "draw X cards, where X is the number of spite counters on {this}";
}
}
@@ -138,7 +138,8 @@ class CurseOfVengeanceDrawLifeEffect extends OneShotEffect {
public CurseOfVengeanceDrawLifeEffect() {
super(Outcome.Benefit);
- staticText = "you gain X life and draw X cards, where X is the number of spite counters on {this}";
+ staticText = "you gain X life and draw X cards, where X is the "
+ + "number of spite counters on {this}";
}
public CurseOfVengeanceDrawLifeEffect(final CurseOfVengeanceDrawLifeEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/d/DetectionTower.java b/Mage.Sets/src/mage/cards/d/DetectionTower.java
index 3f0ec089949..6737f549a01 100644
--- a/Mage.Sets/src/mage/cards/d/DetectionTower.java
+++ b/Mage.Sets/src/mage/cards/d/DetectionTower.java
@@ -72,12 +72,12 @@ class DetectionTowerEffect extends AsThoughEffectImpl {
}
@Override
- public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
- if (affectedControllerId.equals(source.getControllerId())) {
- if (game.getOpponents(source.getControllerId()).contains(sourceId)) {
+ public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
+ if (affectedControllerId.equals(source.getControllerId())) { //
+ if (game.getOpponents(source.getControllerId()).contains(objectId)) {
return true;
}
- Permanent creature = game.getPermanent(sourceId);
+ Permanent creature = game.getPermanent(objectId);
if (creature != null
&& game.getOpponents(source.getControllerId()).contains(creature.getControllerId())) {
return true;
diff --git a/Mage.Sets/src/mage/cards/d/DoublingSeason.java b/Mage.Sets/src/mage/cards/d/DoublingSeason.java
index fab6ae021d2..5620ad24036 100644
--- a/Mage.Sets/src/mage/cards/d/DoublingSeason.java
+++ b/Mage.Sets/src/mage/cards/d/DoublingSeason.java
@@ -1,7 +1,5 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
@@ -16,8 +14,9 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class DoublingSeason extends CardImpl {
@@ -58,7 +57,7 @@ class DoublingSeasonCounterEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- event.setAmount(event.getAmount() * 2);
+ event.setAmountForCounters(event.getAmount() * 2, true);
return false;
}
@@ -80,6 +79,7 @@ class DoublingSeasonCounterEffect extends ReplacementEffectImpl {
}
return permanent != null
&& permanent.isControlledBy(source.getControllerId())
+ && event.getAmount() > 0
&& !landPlayed; // example: gemstone mine being played as a land drop
}
diff --git a/Mage.Sets/src/mage/cards/d/DovinHandOfControl.java b/Mage.Sets/src/mage/cards/d/DovinHandOfControl.java
index 734bef43bdc..34eaf023bcc 100644
--- a/Mage.Sets/src/mage/cards/d/DovinHandOfControl.java
+++ b/Mage.Sets/src/mage/cards/d/DovinHandOfControl.java
@@ -18,6 +18,8 @@ import mage.target.TargetPermanent;
import mage.util.CardUtil;
import java.util.UUID;
+import mage.abilities.mana.ManaAbility;
+import mage.game.stack.Spell;
/**
* @author TheElk801
@@ -76,7 +78,12 @@ class DovinHandOfControlEffect extends CostModificationEffectImpl {
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
Card card = game.getCard(abilityToModify.getSourceId());
- return card != null && (card.isInstantOrSorcery() || card.isArtifact())
+ if (!(abilityToModify instanceof SpellAbility)) {
+ return false;
+ }
+ return card != null
+ && (card.isInstantOrSorcery()
+ || card.isArtifact())
&& game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId());
}
diff --git a/Mage.Sets/src/mage/cards/d/DreadhordeInvasion.java b/Mage.Sets/src/mage/cards/d/DreadhordeInvasion.java
index 5deecbca9d2..98092d6deb4 100644
--- a/Mage.Sets/src/mage/cards/d/DreadhordeInvasion.java
+++ b/Mage.Sets/src/mage/cards/d/DreadhordeInvasion.java
@@ -10,11 +10,12 @@ import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
-import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.filter.predicate.permanent.TokenPredicate;
import java.util.UUID;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.permanent.ControllerPredicate;
/**
* @author TheElk801
@@ -27,6 +28,7 @@ public final class DreadhordeInvasion extends CardImpl {
static {
filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 5));
filter.add(TokenPredicate.instance);
+ filter.add(new ControllerPredicate(TargetController.YOU));
}
public DreadhordeInvasion(UUID ownerId, CardSetInfo setInfo) {
diff --git a/Mage.Sets/src/mage/cards/e/EntrailsFeaster.java b/Mage.Sets/src/mage/cards/e/EntrailsFeaster.java
index b9715cbc129..90b8131918f 100644
--- a/Mage.Sets/src/mage/cards/e/EntrailsFeaster.java
+++ b/Mage.Sets/src/mage/cards/e/EntrailsFeaster.java
@@ -1,7 +1,5 @@
-
package mage.cards.e;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@@ -9,11 +7,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
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.Zone;
+import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
@@ -21,14 +15,15 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInGraveyard;
+import java.util.UUID;
+
/**
- *
* @author L_J
*/
public final class EntrailsFeaster extends CardImpl {
public EntrailsFeaster(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.CAT);
this.power = new MageInt(1);
@@ -81,7 +76,7 @@ class EntrailsFeasterEffect extends OneShotEffect {
if (cardChosen != null) {
controller.moveCardsToExile(cardChosen, source, game, true, null, "");
if (sourceObject != null) {
- sourceObject.getCounters(game).addCounter(CounterType.P1P1.createInstance());
+ sourceObject.addCounters(CounterType.P1P1.createInstance(), source, game);
game.informPlayers(controller.getLogName() + " puts a +1/+1 counter on " + sourceObject.getLogName());
}
}
diff --git a/Mage.Sets/src/mage/cards/e/EverythingamajigE.java b/Mage.Sets/src/mage/cards/e/EverythingamajigE.java
index 439a921abd7..bad33f9ba52 100644
--- a/Mage.Sets/src/mage/cards/e/EverythingamajigE.java
+++ b/Mage.Sets/src/mage/cards/e/EverythingamajigE.java
@@ -129,7 +129,7 @@ class UrzasHotTubPredicate implements Predicate {
}
private boolean sharesWordWithName(String str) {
- if (referenceName == null || referenceName == "") {
+ if (referenceName == null || referenceName.equals("")) {
return false;
}
String[] arr = referenceName.split("\\s+");
diff --git a/Mage.Sets/src/mage/cards/e/ExpelFromOrazca.java b/Mage.Sets/src/mage/cards/e/ExpelFromOrazca.java
index 8feec699189..9c979fb627b 100644
--- a/Mage.Sets/src/mage/cards/e/ExpelFromOrazca.java
+++ b/Mage.Sets/src/mage/cards/e/ExpelFromOrazca.java
@@ -1,10 +1,10 @@
-
package mage.cards.e;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.keyword.AscendEffect;
+import mage.abilities.hint.common.CitysBlessingHint;
+import mage.abilities.hint.common.PermanentsYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -16,8 +16,9 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetNonlandPermanent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class ExpelFromOrazca extends CardImpl {
@@ -25,8 +26,10 @@ public final class ExpelFromOrazca extends CardImpl {
public ExpelFromOrazca(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
- // Ascend
+ // Ascend (If you control ten or more permanents, you get the city’s blessing for the rest of the game.)
this.getSpellAbility().addEffect(new AscendEffect());
+ this.getSpellAbility().addHint(CitysBlessingHint.instance);
+ this.getSpellAbility().addHint(PermanentsYouControlHint.instance);
// Return target nonland permanent to its owner's hand. If you have the city's blessing, you may put that permanent on top of its owner's library instead.
this.getSpellAbility().addEffect(new ExpelFromOrazcaEffect());
diff --git a/Mage.Sets/src/mage/cards/e/Expropriate.java b/Mage.Sets/src/mage/cards/e/Expropriate.java
index 81761c64af3..318fa8342f4 100644
--- a/Mage.Sets/src/mage/cards/e/Expropriate.java
+++ b/Mage.Sets/src/mage/cards/e/Expropriate.java
@@ -1,8 +1,5 @@
package mage.cards.e;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
@@ -22,6 +19,10 @@ import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
/**
* @author JRHerlehy
*/
@@ -30,7 +31,8 @@ public final class Expropriate extends CardImpl {
public Expropriate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{7}{U}{U}");
- // Council's dilemma — Starting with you, each player votes for time or money. For each time vote, take an extra turn after this one. For each money vote, choose a permanent owned by the voter and gain control of it. Exile Expropriate
+ // Council's dilemma — Starting with you, each player votes for time or money. For each time vote,
+ // take an extra turn after this one. For each money vote, choose a permanent owned by the voter and gain control of it. Exile Expropriate
this.getSpellAbility().addEffect(new ExpropriateDilemmaEffect());
this.getSpellAbility().addEffect(ExileSpellEffect.getInstance());
}
diff --git a/Mage.Sets/src/mage/cards/f/FeatherTheRedeemed.java b/Mage.Sets/src/mage/cards/f/FeatherTheRedeemed.java
index 74de65b44f7..ebb28bb5b93 100644
--- a/Mage.Sets/src/mage/cards/f/FeatherTheRedeemed.java
+++ b/Mage.Sets/src/mage/cards/f/FeatherTheRedeemed.java
@@ -167,11 +167,9 @@ class FeatherTheRedeemedEffect extends ReplacementEffectImpl {
if (zEvent.getFromZone() == Zone.STACK
&& zEvent.getToZone() == Zone.GRAVEYARD
&& event.getSourceId() != null) {
- if (event.getSourceId().equals(event.getTargetId())) {
+ if (event.getSourceId().equals(event.getTargetId()) && mor.getZoneChangeCounter() == game.getState().getZoneChangeCounter(event.getSourceId())) {
Spell spell = game.getStack().getSpell(mor.getSourceId());
- if (spell != null && spell.isInstantOrSorcery()) {
- return true;
- }
+ return spell != null && spell.isInstantOrSorcery();
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/f/Frightcrawler.java b/Mage.Sets/src/mage/cards/f/Frightcrawler.java
index d1123538e1e..dcca2568ac3 100644
--- a/Mage.Sets/src/mage/cards/f/Frightcrawler.java
+++ b/Mage.Sets/src/mage/cards/f/Frightcrawler.java
@@ -1,31 +1,27 @@
-
package mage.cards.f;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CardsInControllerGraveCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.decorator.ConditionalRestrictionEffect;
import mage.abilities.effects.common.combat.CantBlockSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.FearAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AbilityWord;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Duration;
-import mage.constants.Zone;
+import mage.constants.*;
+
+import java.util.UUID;
/**
- *
* @author cbt33
*/
public final class Frightcrawler extends CardImpl {
public Frightcrawler(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.HORROR);
this.power = new MageInt(1);
@@ -37,14 +33,14 @@ public final class Frightcrawler extends CardImpl {
Ability thresholdAbility = new SimpleStaticAbility(
Zone.BATTLEFIELD,
new ConditionalContinuousEffect(
- new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
- new CardsInControllerGraveCondition(7),
- "If seven or more cards are in your graveyard, {this} gets +2/+2 "
+ new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
+ new CardsInControllerGraveCondition(7),
+ "If seven or more cards are in your graveyard, {this} gets +2/+2 "
));
- thresholdAbility.addEffect(new ConditionalContinuousEffect(
- new CantBlockSourceEffect(Duration.WhileOnBattlefield),
- new CardsInControllerGraveCondition(7),
- "and can't block."));
+ thresholdAbility.addEffect(new ConditionalRestrictionEffect(
+ new CantBlockSourceEffect(Duration.WhileOnBattlefield),
+ new CardsInControllerGraveCondition(7),
+ "and can't block."));
thresholdAbility.setAbilityWord(AbilityWord.THRESHOLD);
this.addAbility(thresholdAbility);
}
diff --git a/Mage.Sets/src/mage/cards/f/Fylgja.java b/Mage.Sets/src/mage/cards/f/Fylgja.java
new file mode 100644
index 00000000000..49df5677476
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/f/Fylgja.java
@@ -0,0 +1,66 @@
+package mage.cards.f;
+
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.RemoveCountersSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.AttachEffect;
+import mage.abilities.effects.common.PreventDamageToAttachedEffect;
+import mage.abilities.effects.common.counter.AddCountersSourceEffect;
+import mage.abilities.keyword.EnchantAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.AttachmentType;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.counters.CounterType;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+/**
+ *
+ * @author LevelX2
+ */
+public final class Fylgja extends CardImpl {
+
+ public Fylgja(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}");
+
+ this.subtype.add(SubType.AURA);
+
+ // Enchant creature
+ TargetPermanent auraTarget = new TargetCreaturePermanent();
+ this.getSpellAbility().addTarget(auraTarget);
+ this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
+ Ability ability = new EnchantAbility(auraTarget.getTargetName());
+ this.addAbility(ability);
+
+ // Fylgja enters the battlefield with four healing counters on it.
+ this.addAbility(new EntersBattlefieldAbility(
+ new AddCountersSourceEffect(CounterType.HEALING.createInstance(4))
+ .setText("with four healing counters on it.")));
+
+ // Remove a healing counter from Fylgja: Prevent the next 1 damage that would be dealt to enchanted creature this turn.
+ this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreventDamageToAttachedEffect(Duration.EndOfTurn, AttachmentType.AURA, 1, false)
+ .setText("Prevent the next 1 damage that would be dealt to enchanted creature this turn"),
+ new RemoveCountersSourceCost(CounterType.HEALING.createInstance(1))));
+
+ // {2}{W}: Put a healing counter on Fylgja.
+ this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.HEALING.createInstance(1)),
+ new ManaCostsImpl("{2}{W}")));
+ }
+
+ private Fylgja(final Fylgja card) {
+ super(card);
+ }
+
+ @Override
+ public Fylgja copy() {
+ return new Fylgja(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GideonBlackblade.java b/Mage.Sets/src/mage/cards/g/GideonBlackblade.java
index c45c68e9be3..f57cd82e970 100644
--- a/Mage.Sets/src/mage/cards/g/GideonBlackblade.java
+++ b/Mage.Sets/src/mage/cards/g/GideonBlackblade.java
@@ -7,6 +7,7 @@ import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.decorator.ConditionalPreventionEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.PreventAllDamageToSourceEffect;
@@ -61,7 +62,7 @@ public final class GideonBlackblade extends CardImpl {
)));
// Prevent all damage that would be dealt to Gideon Blackblade during your turn.
- this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
+ this.addAbility(new SimpleStaticAbility(new ConditionalPreventionEffect(
new PreventAllDamageToSourceEffect(Duration.WhileOnBattlefield),
MyTurnCondition.instance, "Prevent all damage that would be dealt to {this} during your turn."
)));
@@ -96,7 +97,7 @@ class GideonBlackbladeToken extends TokenImpl {
subtype.add(SubType.SOLDIER);
power = new MageInt(4);
toughness = new MageInt(4);
- addAbility(IndestructibleAbility.getInstance());
+ this.addAbility(IndestructibleAbility.getInstance());
}
private GideonBlackbladeToken(final GideonBlackbladeToken token) {
diff --git a/Mage.Sets/src/mage/cards/g/GodEternalRhonas.java b/Mage.Sets/src/mage/cards/g/GodEternalRhonas.java
index 6195751ad21..4ba9c292ad8 100644
--- a/Mage.Sets/src/mage/cards/g/GodEternalRhonas.java
+++ b/Mage.Sets/src/mage/cards/g/GodEternalRhonas.java
@@ -7,20 +7,18 @@ import mage.abilities.common.GodEternalDiesTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
-import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
-import mage.filter.FilterPermanent;
-import mage.filter.common.FilterControlledCreaturePermanent;
-import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.filter.common.FilterControlledCreaturePermanent;
/**
* @author TheElk801
@@ -57,17 +55,13 @@ public final class GodEternalRhonas extends CardImpl {
}
class GodEternalRhonasEffect extends OneShotEffect {
-
- private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
-
- static {
- filter.add(AnotherPredicate.instance);
- }
+
+ private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
GodEternalRhonasEffect() {
super(Outcome.Benefit);
- staticText = "double the power of each other creature you control until end of turn. " +
- "Those creatures gain vigilance until end of turn.";
+ staticText = "double the power of each other creature you control until end of turn. "
+ + "Those creatures gain vigilance until end of turn.";
}
private GodEternalRhonasEffect(final GodEternalRhonasEffect effect) {
@@ -81,8 +75,11 @@ class GodEternalRhonasEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
- if (permanent == null) {
+ Permanent godEternalRhonas = game.getPermanent(source.getSourceId());
+ for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
+ if (permanent == null
+ || godEternalRhonas != null
+ && permanent == godEternalRhonas) {
continue;
}
ContinuousEffect effect = new BoostTargetEffect(
@@ -91,11 +88,14 @@ class GodEternalRhonasEffect extends OneShotEffect {
);
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
+
+ ContinuousEffect effect2 = new GainAbilityTargetEffect(
+ VigilanceAbility.getInstance(),
+ Duration.EndOfTurn
+ );
+ effect2.setTargetPointer(new FixedTarget(permanent, game));
+ game.addEffect(effect2, source);
}
- game.addEffect(new GainAbilityControlledEffect(
- VigilanceAbility.getInstance(),
- Duration.EndOfTurn, filter
- ), source);
return true;
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/g/GoldenDemise.java b/Mage.Sets/src/mage/cards/g/GoldenDemise.java
index 91641ac77da..f4a14a8c98a 100644
--- a/Mage.Sets/src/mage/cards/g/GoldenDemise.java
+++ b/Mage.Sets/src/mage/cards/g/GoldenDemise.java
@@ -5,6 +5,7 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.abilities.effects.keyword.AscendEffect;
import mage.abilities.hint.common.CitysBlessingHint;
+import mage.abilities.hint.common.PermanentsYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -23,8 +24,10 @@ public final class GoldenDemise extends CardImpl {
public GoldenDemise(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{B}");
- // Ascend
+ // Ascend (If you control ten or more permanents, you get the city’s blessing for the rest of the game.)
this.getSpellAbility().addEffect(new AscendEffect());
+ this.getSpellAbility().addHint(CitysBlessingHint.instance);
+ this.getSpellAbility().addHint(PermanentsYouControlHint.instance);
// All creatures get -2/-2 until end of turn. If you have the city's blessing, instead only creatures your opponents control get -2/-2 until end of turn.
FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures your opponents control");
@@ -35,7 +38,6 @@ public final class GoldenDemise extends CardImpl {
CitysBlessingCondition.instance,
"All creatures get -2/-2 until end of turn. If you have the city's blessing, instead only creatures your opponents control get -2/-2 until end of turn"
));
- this.getSpellAbility().addHint(CitysBlessingHint.instance);
}
public GoldenDemise(final GoldenDemise card) {
diff --git a/Mage.Sets/src/mage/cards/g/GontiLordOfLuxury.java b/Mage.Sets/src/mage/cards/g/GontiLordOfLuxury.java
index cae0b235300..0755e3a2824 100644
--- a/Mage.Sets/src/mage/cards/g/GontiLordOfLuxury.java
+++ b/Mage.Sets/src/mage/cards/g/GontiLordOfLuxury.java
@@ -184,7 +184,15 @@ class GontiLordOfLuxurySpendAnyManaEffect extends AsThoughEffectImpl implements
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- objectId = game.getCard(objectId).getMainCard().getId(); // for split cards
+ Card theCard = game.getCard(objectId);
+ if(theCard == null){
+ return false;
+ }
+ Card mainCard = theCard.getMainCard();
+ if(mainCard == null){
+ return false;
+ }
+ objectId = mainCard.getId(); // for split cards
if (objectId.equals(((FixedTarget) getTargetPointer()).getTarget())
&& game.getState().getZoneChangeCounter(objectId) <= ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1) {
if (affectedControllerId.equals(source.getControllerId())) {
@@ -229,7 +237,15 @@ class GontiLordOfLuxuryLookEffect extends AsThoughEffectImpl {
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- objectId = game.getCard(objectId).getMainCard().getId(); // for split cards
+ Card theCard = game.getCard(objectId);
+ if(theCard == null){
+ return false;
+ }
+ Card mainCard = theCard.getMainCard();
+ if(mainCard == null){
+ return false;
+ }
+ objectId = mainCard.getId(); // for split cards
if (affectedControllerId.equals(source.getControllerId())
&& game.getState().getZone(objectId) == Zone.EXILED) {
Player controller = game.getPlayer(source.getControllerId());
diff --git a/Mage.Sets/src/mage/cards/g/GuidedStrike.java b/Mage.Sets/src/mage/cards/g/GuidedStrike.java
index 486caf88f37..6df08e69568 100644
--- a/Mage.Sets/src/mage/cards/g/GuidedStrike.java
+++ b/Mage.Sets/src/mage/cards/g/GuidedStrike.java
@@ -1,4 +1,3 @@
-
package mage.cards.g;
import java.util.UUID;
@@ -16,23 +15,25 @@ import mage.target.common.TargetCreaturePermanent;
/**
*
* @author LoneFox
-
+ *
*/
public final class GuidedStrike extends CardImpl {
public GuidedStrike(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Target creature gets +1/+0 and gains first strike until end of turn.
- this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent());
Effect effect = new BoostTargetEffect(1, 0, Duration.EndOfTurn);
effect.setText("Target creature gets +1/+0");
this.getSpellAbility().addEffect(effect);
effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn);
effect.setText("and gains first strike until end of turn");
this.getSpellAbility().addEffect(effect);
+
// Draw a card.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
+
}
public GuidedStrike(final GuidedStrike card) {
diff --git a/Mage.Sets/src/mage/cards/g/GuildpactInformant.java b/Mage.Sets/src/mage/cards/g/GuildpactInformant.java
index 47d833255f3..564d26a6375 100644
--- a/Mage.Sets/src/mage/cards/g/GuildpactInformant.java
+++ b/Mage.Sets/src/mage/cards/g/GuildpactInformant.java
@@ -27,7 +27,8 @@ public final class GuildpactInformant extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
- // Whenever Guildpact Informant deals combat damage to a player or planeswalker, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
+ // Whenever Guildpact Informant deals combat damage to a player or planeswalker,
+ // proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
new ProliferateEffect(), false
).setOrPlaneswalker(true));
diff --git a/Mage.Sets/src/mage/cards/h/HardenedScales.java b/Mage.Sets/src/mage/cards/h/HardenedScales.java
index ce764544f94..8d4390296f9 100644
--- a/Mage.Sets/src/mage/cards/h/HardenedScales.java
+++ b/Mage.Sets/src/mage/cards/h/HardenedScales.java
@@ -1,7 +1,5 @@
-
package mage.cards.h;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
@@ -17,14 +15,15 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class HardenedScales extends CardImpl {
public HardenedScales(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}");
// If one or more +1/+1 counters would be put on a creature you control, that many plus one +1/+1 counters are put on it instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new HardenedScalesEffect()));
@@ -54,10 +53,7 @@ class HardenedScalesEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- int amount = event.getAmount();
- if (amount >= 1) {
- event.setAmount(amount + 1);
- }
+ event.setAmountForCounters(event.getAmount() + 1, true);
return false;
}
@@ -68,15 +64,13 @@ class HardenedScalesEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
- if (event.getData().equals(CounterType.P1P1.getName())) {
+ if (event.getData().equals(CounterType.P1P1.getName()) && event.getAmount() > 0) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent == null) {
permanent = game.getPermanentEntering(event.getTargetId());
}
- if (permanent != null && permanent.isControlledBy(source.getControllerId())
- && permanent.isCreature()) {
- return true;
- }
+ return permanent != null && permanent.isControlledBy(source.getControllerId())
+ && permanent.isCreature();
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/i/Inhumaniac.java b/Mage.Sets/src/mage/cards/i/Inhumaniac.java
index 8525bb3b53d..e7ae91e038c 100644
--- a/Mage.Sets/src/mage/cards/i/Inhumaniac.java
+++ b/Mage.Sets/src/mage/cards/i/Inhumaniac.java
@@ -1,7 +1,5 @@
-
package mage.cards.i;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@@ -17,8 +15,9 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author spjspj
*/
public final class Inhumaniac extends CardImpl {
@@ -71,7 +70,10 @@ class InhumaniacEffect extends OneShotEffect {
} else if (amount >= 5) {
permanent.addCounters(CounterType.P1P1.createInstance(2), source, game);
} else if (amount == 1) {
- permanent.getCounters(game).removeAllCounters(CounterType.P1P1);
+ int numToRemove = permanent.getCounters(game).getCount(CounterType.P1P1);
+ if (numToRemove > 0) {
+ permanent.removeCounters(CounterType.P1P1.getName(), numToRemove, game);
+ }
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/j/JacesSentinel.java b/Mage.Sets/src/mage/cards/j/JacesSentinel.java
index a60f5c14b26..da20a95e49f 100644
--- a/Mage.Sets/src/mage/cards/j/JacesSentinel.java
+++ b/Mage.Sets/src/mage/cards/j/JacesSentinel.java
@@ -1,28 +1,24 @@
-
package mage.cards.j;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.decorator.ConditionalRestrictionEffect;
import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.SubType;
-import mage.constants.TargetController;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class JacesSentinel extends CardImpl {
@@ -48,7 +44,7 @@ public final class JacesSentinel extends CardImpl {
new BoostSourceEffect(1, 0, Duration.WhileOnBattlefield),
new PermanentsOnTheBattlefieldCondition(filter),
"As long as you control a Jace planeswalker, {this} gets +1/+0"));
- ability.addEffect(new ConditionalContinuousEffect(
+ ability.addEffect(new ConditionalRestrictionEffect(
new CantBeBlockedSourceEffect(),
new PermanentsOnTheBattlefieldCondition(filter),
"and can't be blocked"));
diff --git a/Mage.Sets/src/mage/cards/k/KirtarsDesire.java b/Mage.Sets/src/mage/cards/k/KirtarsDesire.java
index f42a3e25b13..9f987a41c7d 100644
--- a/Mage.Sets/src/mage/cards/k/KirtarsDesire.java
+++ b/Mage.Sets/src/mage/cards/k/KirtarsDesire.java
@@ -1,28 +1,22 @@
-
package mage.cards.k;
-import java.util.UUID;
-import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CardsInControllerGraveCondition;
-import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.decorator.ConditionalRestrictionEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.combat.CantAttackAttachedEffect;
import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect;
-import mage.constants.Outcome;
-import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AbilityWord;
-import mage.constants.AttachmentType;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Zone;
+import mage.constants.*;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
/**
- *
* @author TheElk801
*/
public final class KirtarsDesire extends CardImpl {
@@ -43,8 +37,9 @@ public final class KirtarsDesire extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect(AttachmentType.AURA)));
// Threshold - Enchanted creature can't block as long as seven or more cards are in your graveyard.
- ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
- new CantAttackBlockAttachedEffect(AttachmentType.AURA), new CardsInControllerGraveCondition(7),
+ ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalRestrictionEffect(
+ new CantAttackBlockAttachedEffect(AttachmentType.AURA),
+ new CardsInControllerGraveCondition(7),
"Enchanted creature can't block as long as seven or more cards are in your graveyard"));
ability.setAbilityWord(AbilityWord.THRESHOLD);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/m/MartyrsOfKorlis.java b/Mage.Sets/src/mage/cards/m/MartyrsOfKorlis.java
index bdd3efdb713..15edb14fd07 100644
--- a/Mage.Sets/src/mage/cards/m/MartyrsOfKorlis.java
+++ b/Mage.Sets/src/mage/cards/m/MartyrsOfKorlis.java
@@ -1,40 +1,44 @@
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.SourceTappedCondition;
-import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.decorator.ConditionalReplacementEffect;
+import mage.abilities.effects.Effect;
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.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
/**
- *
* @author MarcoMarin
*/
public final class MartyrsOfKorlis extends CardImpl {
public MartyrsOfKorlis(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.HUMAN);
this.power = new MageInt(1);
this.toughness = new MageInt(6);
// As long as Martyrs of Korlis is untapped, all damage that would be dealt to you by artifacts is dealt to Martyrs of Korlis instead.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
+ Effect effect = new ConditionalReplacementEffect(
new RedirectArtifactDamageFromPlayerToSourceEffect(Duration.WhileOnBattlefield),
new InvertCondition(SourceTappedCondition.instance),
- "{this} redirects artifact damage from controller as long as it's untapped")));
+ null);
+ effect.setText("{this} redirects artifact damage from controller as long as it's untapped");
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public MartyrsOfKorlis(final MartyrsOfKorlis card) {
@@ -50,7 +54,7 @@ public final class MartyrsOfKorlis extends CardImpl {
class RedirectArtifactDamageFromPlayerToSourceEffect extends RedirectionEffect {
public RedirectArtifactDamageFromPlayerToSourceEffect(Duration duration) {
- super(duration);
+ super(duration);
}
public RedirectArtifactDamageFromPlayerToSourceEffect(final RedirectArtifactDamageFromPlayerToSourceEffect effect) {
@@ -64,9 +68,13 @@ class RedirectArtifactDamageFromPlayerToSourceEffect extends RedirectionEffect {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
- if (event.getTargetId().equals(source.getControllerId())&&
+ if (event.getTargetId().equals(source.getControllerId()) &&
game.getPermanentOrLKIBattlefield(event.getSourceId()).isArtifact()) {
- this.redirectTarget.updateTarget(source.getSourceId(), game);
+
+ TargetPermanent target = new TargetPermanent();
+ target.add(source.getSourceId(), game);
+ this.redirectTarget = target;
+
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java b/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java
index d3d868a2e25..3c6124c9463 100644
--- a/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java
+++ b/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java
@@ -1,8 +1,5 @@
-
package mage.cards.m;
-import java.util.Set;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
@@ -19,14 +16,16 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author BetaSteward
*/
public final class MeliraSylvokOutcast extends CardImpl {
public MeliraSylvokOutcast(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SCOUT);
@@ -78,7 +77,7 @@ class MeliraSylvokOutcastEffect extends ReplacementEffectImpl {
@Override
public boolean checksEventType(GameEvent event, Game game) {
- return event.getType() == EventType.ADD_COUNTER;
+ return event.getType() == EventType.ADD_COUNTERS;
}
@Override
@@ -111,7 +110,7 @@ class MeliraSylvokOutcastEffect2 extends ReplacementEffectImpl {
@Override
public boolean checksEventType(GameEvent event, Game game) {
- return event.getType() == EventType.ADD_COUNTER;
+ return event.getType() == EventType.ADD_COUNTERS;
}
@Override
@@ -121,13 +120,10 @@ class MeliraSylvokOutcastEffect2 extends ReplacementEffectImpl {
if (perm == null) {
perm = game.getPermanentEntering(event.getTargetId());
}
- if (perm != null && perm.isCreature() && perm.isControlledBy(source.getControllerId())) {
- return true;
- }
+ return perm != null && perm.isCreature() && perm.isControlledBy(source.getControllerId());
}
return false;
}
-
}
class MeliraSylvokOutcastEffect3 extends ContinuousEffectImpl {
diff --git a/Mage.Sets/src/mage/cards/m/MineLayer.java b/Mage.Sets/src/mage/cards/m/MineLayer.java
index 113cb6f6917..1932c318edd 100644
--- a/Mage.Sets/src/mage/cards/m/MineLayer.java
+++ b/Mage.Sets/src/mage/cards/m/MineLayer.java
@@ -1,7 +1,5 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BecomesTappedTriggeredAbility;
@@ -12,11 +10,11 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
-import mage.constants.SubType;
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.counters.CounterType;
import mage.filter.common.FilterLandPermanent;
@@ -25,8 +23,9 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetLandPermanent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class MineLayer extends CardImpl {
@@ -87,7 +86,10 @@ class RemoveAllMineCountersEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(CardType.LAND)) {
if (permanent != null) {
- permanent.getCounters(game).removeAllCounters(CounterType.MINE);
+ int numToRemove = permanent.getCounters(game).getCount(CounterType.MINE);
+ if (numToRemove > 0) {
+ permanent.removeCounters(CounterType.MINE.getName(), numToRemove, game);
+ }
}
}
return true;
diff --git a/Mage.Sets/src/mage/cards/m/MowuLoyalCompanion.java b/Mage.Sets/src/mage/cards/m/MowuLoyalCompanion.java
index 6b3fdc2c7ca..946b515178e 100644
--- a/Mage.Sets/src/mage/cards/m/MowuLoyalCompanion.java
+++ b/Mage.Sets/src/mage/cards/m/MowuLoyalCompanion.java
@@ -63,10 +63,7 @@ class MowuLoyalCompanionEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- int amount = event.getAmount();
- if (amount > 0) {
- event.setAmount(amount + 1);
- }
+ event.setAmountForCounters(event.getAmount() + 1, true);
return false;
}
@@ -77,15 +74,13 @@ class MowuLoyalCompanionEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
- if (event.getData().equals(CounterType.P1P1.getName())) {
+ if (event.getData().equals(CounterType.P1P1.getName()) && event.getAmount() > 0) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent == null) {
permanent = game.getPermanentEntering(event.getTargetId());
}
- if (permanent != null && permanent.getId().equals(source.getSourceId())
- && permanent.isCreature()) {
- return true;
- }
+ return permanent != null && permanent.getId().equals(source.getSourceId())
+ && permanent.isCreature();
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/n/NahiriStormOfStone.java b/Mage.Sets/src/mage/cards/n/NahiriStormOfStone.java
index 0b044b2aeaf..133cb368781 100644
--- a/Mage.Sets/src/mage/cards/n/NahiriStormOfStone.java
+++ b/Mage.Sets/src/mage/cards/n/NahiriStormOfStone.java
@@ -8,6 +8,7 @@ import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.PayVariableLoyaltyCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.decorator.ConditionalCostModificationEffect;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -56,7 +57,7 @@ public final class NahiriStormOfStone extends CardImpl {
), MyTurnCondition.instance, "As long as it's your turn, " +
"creatures you control have first strike"
));
- ability.addEffect(new ConditionalContinuousEffect(
+ ability.addEffect(new ConditionalCostModificationEffect(
new AbilitiesCostReductionControllerEffect(
EquipAbility.class, "Equip"
), MyTurnCondition.instance, "and equip abilities you activate cost {1} less to activate"
diff --git a/Mage.Sets/src/mage/cards/n/NaturesBlessing.java b/Mage.Sets/src/mage/cards/n/NaturesBlessing.java
index 0b24af291c0..4a400381679 100644
--- a/Mage.Sets/src/mage/cards/n/NaturesBlessing.java
+++ b/Mage.Sets/src/mage/cards/n/NaturesBlessing.java
@@ -1,9 +1,5 @@
-
package mage.cards.n;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.DiscardCardCost;
@@ -27,14 +23,17 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author L_J
*/
public final class NaturesBlessing extends CardImpl {
public NaturesBlessing(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{W}");
// {G}{W}, Discard a card: Put a +1/+1 counter on target creature or that creature gains banding, first strike, or trample.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new NaturesBlessingEffect(), new ManaCostsImpl("{G}{W}"));
@@ -102,7 +101,7 @@ class NaturesBlessingEffect extends OneShotEffect {
if (gainedAbility != null) {
game.addEffect(new GainAbilityTargetEffect(gainedAbility, Duration.Custom), source);
} else {
- targetPermanent.getCounters(game).addCounter(CounterType.P1P1.createInstance());
+ targetPermanent.addCounters(CounterType.P1P1.createInstance(), source, game);
game.informPlayers(controller.getLogName() + " puts a +1/+1 counter on " + targetPermanent.getLogName());
}
return true;
diff --git a/Mage.Sets/src/mage/cards/n/NivMizzetReborn.java b/Mage.Sets/src/mage/cards/n/NivMizzetReborn.java
index 2e034d48786..fe55aa3aae4 100644
--- a/Mage.Sets/src/mage/cards/n/NivMizzetReborn.java
+++ b/Mage.Sets/src/mage/cards/n/NivMizzetReborn.java
@@ -113,9 +113,9 @@ class NivMizzetRebornEffect extends OneShotEffect {
NivMizzetRebornEffect() {
super(Outcome.Benefit);
- staticText = "reveal the top ten cards of your library. For each color pair, " +
- "choose a card that's exactly those colors from among them. " +
- "Put the chosen cards into your hand and the rest on the bottom of your library in a random order.";
+ staticText = "reveal the top ten cards of your library. For each color pair, "
+ + "choose a card that's exactly those colors from among them. "
+ + "Put the chosen cards into your hand and the rest on the bottom of your library in a random order.";
}
private NivMizzetRebornEffect(final NivMizzetRebornEffect effect) {
@@ -153,7 +153,11 @@ class NivMizzetRebornEffect extends OneShotEffect {
}
cards.removeAll(cards2);
player.putCardsOnBottomOfLibrary(cards, game, source, false);
- player.moveCards(cards2, Zone.HAND, source, game);
+ if (player.moveCards(cards2, Zone.HAND, source, game)) {
+ for (Card card : cards2.getCards(game)) {
+ game.informPlayers(player.getName() + " chose " + card.getName() + " and put it into his or her hand.");
+ }
+ }
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/o/OrimsPrayer.java b/Mage.Sets/src/mage/cards/o/OrimsPrayer.java
index b171246ae47..61a6a42b8d7 100644
--- a/Mage.Sets/src/mage/cards/o/OrimsPrayer.java
+++ b/Mage.Sets/src/mage/cards/o/OrimsPrayer.java
@@ -2,7 +2,6 @@ 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;
@@ -11,6 +10,8 @@ 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;
/**
*
@@ -36,9 +37,11 @@ public final class OrimsPrayer extends CardImpl {
}
class OrimsPrayerTriggeredAbility extends TriggeredAbilityImpl {
+
+ int numberAttackingController = 0;
public OrimsPrayerTriggeredAbility() {
- super(Zone.BATTLEFIELD, new GainLifeEffect(new AttackingCreatureCount()));
+ super(Zone.BATTLEFIELD, null);
}
public OrimsPrayerTriggeredAbility(final OrimsPrayerTriggeredAbility ability) {
@@ -57,12 +60,28 @@ class OrimsPrayerTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- return game.getCombat().getDefenders().contains(getControllerId())
- && game.getCombat().getAttackers().size() > 0;
+ boolean applied = false;
+ Player controller = game.getPlayer(getControllerId());
+ if (controller == null) {
+ return false;
+ }
+ for (UUID attackersId : game.getCombat().getAttackers()) {
+ Permanent attackingCreature = game.getPermanent(attackersId);
+ if (attackingCreature != null
+ && game.getCombat().getDefenderId(attackersId) == this.getControllerId()) {
+ numberAttackingController += 1;
+ applied = true;
+ }
+ }
+ if (applied
+ && numberAttackingController > 0) {
+ this.getEffects().add(new GainLifeEffect(numberAttackingController));
+ }
+ return applied;
}
@Override
public String getRule() {
- return "Whenever one or more creatures attack you, " + super.getRule();
+ return "Whenever one or more creatures attack you, you gain 1 life for each attacking creature.";
}
}
diff --git a/Mage.Sets/src/mage/cards/o/OtarianJuggernaut.java b/Mage.Sets/src/mage/cards/o/OtarianJuggernaut.java
index 3a5f723f346..39369dff34d 100644
--- a/Mage.Sets/src/mage/cards/o/OtarianJuggernaut.java
+++ b/Mage.Sets/src/mage/cards/o/OtarianJuggernaut.java
@@ -1,29 +1,24 @@
-
package mage.cards.o;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleEvasionAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CardsInControllerGraveCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
-import mage.abilities.effects.Effect;
+import mage.abilities.decorator.ConditionalRequirementEffect;
import mage.abilities.effects.common.combat.AttacksIfAbleSourceEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
-import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AbilityWord;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class OtarianJuggernaut extends CardImpl {
@@ -49,12 +44,11 @@ public final class OtarianJuggernaut extends CardImpl {
new BoostSourceEffect(3, 0, Duration.WhileOnBattlefield),
new CardsInControllerGraveCondition(7),
"As long as seven or more cards are in your graveyard, {this} gets +3/+0"));
- Effect effect = new ConditionalContinuousEffect(
+ ability.addEffect(new ConditionalRequirementEffect(
new AttacksIfAbleSourceEffect(Duration.WhileOnBattlefield, true),
new CardsInControllerGraveCondition(7),
"and attacks each combat if able"
- );
- ability.addEffect(effect);
+ ));
ability.setAbilityWord(AbilityWord.THRESHOLD);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/o/Oubliette.java b/Mage.Sets/src/mage/cards/o/Oubliette.java
index 57514db4384..9e933be1310 100644
--- a/Mage.Sets/src/mage/cards/o/Oubliette.java
+++ b/Mage.Sets/src/mage/cards/o/Oubliette.java
@@ -1,9 +1,5 @@
-
package mage.cards.o;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -27,8 +23,11 @@ import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author MarcoMarin
*/
public final class Oubliette extends CardImpl {
@@ -137,7 +136,7 @@ class OublietteReturnEffect extends OneShotEffect {
if (counters != null) {
for (Counter counter : counters.values()) {
if (counter != null) {
- newPermanent.getCounters(game).addCounter(counter);
+ newPermanent.getCounters(game).addCounter(counter); // it's restore counters, not add (e.g. without add events)
}
}
}
diff --git a/Mage.Sets/src/mage/cards/p/PirImaginativeRascal.java b/Mage.Sets/src/mage/cards/p/PirImaginativeRascal.java
index 3679e5533d3..3f2bc145daa 100644
--- a/Mage.Sets/src/mage/cards/p/PirImaginativeRascal.java
+++ b/Mage.Sets/src/mage/cards/p/PirImaginativeRascal.java
@@ -1,27 +1,21 @@
-
package mage.cards.p;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.keyword.PartnerWithAbility;
-import mage.constants.SubType;
-import mage.constants.SuperType;
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.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class PirImaginativeRascal extends CardImpl {
@@ -65,10 +59,7 @@ class PirImaginativeRascalEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- int amount = event.getAmount();
- if (amount >= 1) {
- event.setAmount(amount + 1);
- }
+ event.setAmountForCounters(event.getAmount() + 1, true);
return false;
}
@@ -84,7 +75,7 @@ class PirImaginativeRascalEffect extends ReplacementEffectImpl {
if (permanent == null) {
permanent = game.getPermanentEntering(event.getTargetId());
}
- return permanent != null && player != null
+ return permanent != null && player != null && event.getAmount() > 0
&& !player.hasOpponent(permanent.getControllerId(), game);
}
diff --git a/Mage.Sets/src/mage/cards/p/PrideOfConquerors.java b/Mage.Sets/src/mage/cards/p/PrideOfConquerors.java
index 00b7eefb386..02a41fe5383 100644
--- a/Mage.Sets/src/mage/cards/p/PrideOfConquerors.java
+++ b/Mage.Sets/src/mage/cards/p/PrideOfConquerors.java
@@ -5,6 +5,7 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.keyword.AscendEffect;
import mage.abilities.hint.common.CitysBlessingHint;
+import mage.abilities.hint.common.PermanentsYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -22,12 +23,13 @@ public final class PrideOfConquerors extends CardImpl {
// Ascend (If you control ten or more permanents, you get the city's blessing for the rest of the game.)
this.getSpellAbility().addEffect(new AscendEffect());
+ this.getSpellAbility().addHint(CitysBlessingHint.instance);
+ this.getSpellAbility().addHint(PermanentsYouControlHint.instance);
// Creatures you control get +1/+1 until end of turn. If you have the city's blessing, those creatures get +2/+2 until end of turn instead.
this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new BoostControlledEffect(2, 2, Duration.EndOfTurn),
new BoostControlledEffect(1, 1, Duration.EndOfTurn), CitysBlessingCondition.instance,
"Creatures you control get +1/+1 until end of turn. If you have the city's blessing, those creatures get +2/+2 until end of turn instead"));
- this.getSpellAbility().addHint(CitysBlessingHint.instance);
}
public PrideOfConquerors(final PrideOfConquerors card) {
diff --git a/Mage.Sets/src/mage/cards/p/PrimalVigor.java b/Mage.Sets/src/mage/cards/p/PrimalVigor.java
index 184b1bc499e..7443eca630f 100644
--- a/Mage.Sets/src/mage/cards/p/PrimalVigor.java
+++ b/Mage.Sets/src/mage/cards/p/PrimalVigor.java
@@ -1,7 +1,5 @@
-
package mage.cards.p;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
@@ -15,14 +13,15 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class PrimalVigor extends CardImpl {
public PrimalVigor(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}");
// If one or more tokens would be created, twice that many of those tokens are created instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PrimalVigorTokenEffect()));
@@ -93,7 +92,7 @@ class PrimalVigorCounterEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- event.setAmount(event.getAmount() * 2);
+ event.setAmountForCounters(event.getAmount() * 2, true);
return false;
}
@@ -108,11 +107,8 @@ class PrimalVigorCounterEffect extends ReplacementEffectImpl {
if (permanent == null) {
permanent = game.getPermanentEntering(event.getTargetId());
}
- if (permanent != null && permanent.isCreature()
- && event.getData() != null && event.getData().equals("+1/+1")) {
- return true;
- }
- return false;
+ return permanent != null && event.getAmount() > 0 && permanent.isCreature()
+ && event.getData() != null && event.getData().equals("+1/+1");
}
@Override
diff --git a/Mage.Sets/src/mage/cards/s/SecretsOfTheGoldenCity.java b/Mage.Sets/src/mage/cards/s/SecretsOfTheGoldenCity.java
index 705800cd94b..02245199ab0 100644
--- a/Mage.Sets/src/mage/cards/s/SecretsOfTheGoldenCity.java
+++ b/Mage.Sets/src/mage/cards/s/SecretsOfTheGoldenCity.java
@@ -5,6 +5,7 @@ import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.keyword.AscendEffect;
import mage.abilities.hint.common.CitysBlessingHint;
+import mage.abilities.hint.common.PermanentsYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -21,6 +22,8 @@ public final class SecretsOfTheGoldenCity extends CardImpl {
// Ascend
this.getSpellAbility().addEffect(new AscendEffect());
+ this.getSpellAbility().addHint(CitysBlessingHint.instance);
+ this.getSpellAbility().addHint(PermanentsYouControlHint.instance);
// Draw two cards. If you have the city's blessing, draw three cards instead.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
@@ -28,7 +31,6 @@ public final class SecretsOfTheGoldenCity extends CardImpl {
new DrawCardSourceControllerEffect(2),
CitysBlessingCondition.instance,
"Draw two cards. If you have the city's blessing, draw three cards instead"));
- this.getSpellAbility().addHint(CitysBlessingHint.instance);
}
public SecretsOfTheGoldenCity(final SecretsOfTheGoldenCity card) {
diff --git a/Mage.Sets/src/mage/cards/s/Solemnity.java b/Mage.Sets/src/mage/cards/s/Solemnity.java
index 0ce74644dac..858d9c85f29 100644
--- a/Mage.Sets/src/mage/cards/s/Solemnity.java
+++ b/Mage.Sets/src/mage/cards/s/Solemnity.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
@@ -21,8 +19,9 @@ import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author spjspj
*/
public final class Solemnity extends CardImpl {
@@ -70,7 +69,7 @@ class SolemnityEffect extends ReplacementEffectImpl {
@Override
public boolean checksEventType(GameEvent event, Game game) {
- return event.getType() == EventType.ADD_COUNTER;
+ return event.getType() == EventType.ADD_COUNTERS;
}
@Override
@@ -113,7 +112,7 @@ class SolemnityEffect2 extends ReplacementEffectImpl {
@Override
public boolean checksEventType(GameEvent event, Game game) {
- return event.getType() == EventType.ADD_COUNTER || event.getType() == EventType.ADD_COUNTERS;
+ return event.getType() == EventType.ADD_COUNTERS;
}
@Override
@@ -124,21 +123,13 @@ class SolemnityEffect2 extends ReplacementEffectImpl {
Permanent permanent3 = game.getPermanentEntering(event.getTargetId());
if (object instanceof Permanent) {
- if (filter.match((Permanent) object, game)) {
- return true;
- }
+ return filter.match((Permanent) object, game);
} else if (permanent != null) {
- if (filter.match(permanent, game)) {
- return true;
- }
+ return filter.match(permanent, game);
} else if (permanent2 != null) {
- if (filter.match(permanent2, game)) {
- return true;
- }
+ return filter.match(permanent2, game);
} else if (permanent3 != null) {
- if (filter.match(permanent3, game)) {
- return true;
- }
+ return filter.match(permanent3, game);
}
return false;
diff --git a/Mage.Sets/src/mage/cards/s/SowerOfDiscord.java b/Mage.Sets/src/mage/cards/s/SowerOfDiscord.java
index 18d91f47571..a277ee931e7 100644
--- a/Mage.Sets/src/mage/cards/s/SowerOfDiscord.java
+++ b/Mage.Sets/src/mage/cards/s/SowerOfDiscord.java
@@ -8,12 +8,12 @@ import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
-import mage.constants.SubType;
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;
@@ -124,7 +124,7 @@ class SowerOfDiscordTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
+ return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/s/StoneTongueBasilisk.java b/Mage.Sets/src/mage/cards/s/StoneTongueBasilisk.java
index d26774fce18..a64a30f7459 100644
--- a/Mage.Sets/src/mage/cards/s/StoneTongueBasilisk.java
+++ b/Mage.Sets/src/mage/cards/s/StoneTongueBasilisk.java
@@ -1,14 +1,12 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.condition.common.CardsInControllerGraveCondition;
-import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.decorator.ConditionalRequirementEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
@@ -20,14 +18,15 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class StoneTongueBasilisk extends CardImpl {
public StoneTongueBasilisk(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}{G}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}{G}");
this.subtype.add(SubType.BASILISK);
this.power = new MageInt(4);
this.toughness = new MageInt(5);
@@ -39,9 +38,11 @@ public final class StoneTongueBasilisk extends CardImpl {
this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(effect, false, true));
// Threshold - As long as seven or more cards are in your graveyard, all creatures able to block Stone-Tongue Basilisk do so.
- Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
- new MustBeBlockedByAllSourceEffect(), new CardsInControllerGraveCondition(7),
- "As long as seven or more cards are in your graveyard, all creatures able to block {this} do so"));
+ Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalRequirementEffect(
+ new MustBeBlockedByAllSourceEffect(),
+ new CardsInControllerGraveCondition(7),
+ "As long as seven or more cards are in your graveyard, all creatures able to block {this} do so"
+ ));
ability.setAbilityWord(AbilityWord.THRESHOLD);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/t/TawnossCoffin.java b/Mage.Sets/src/mage/cards/t/TawnossCoffin.java
index af280935ff3..45fef01174d 100644
--- a/Mage.Sets/src/mage/cards/t/TawnossCoffin.java
+++ b/Mage.Sets/src/mage/cards/t/TawnossCoffin.java
@@ -1,8 +1,5 @@
package mage.cards.t;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@@ -32,8 +29,11 @@ import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author MarcoMarin
*/
public final class TawnossCoffin extends CardImpl {
@@ -194,7 +194,7 @@ class TawnossCoffinReturnEffect extends OneShotEffect {
if (notedCounters != null) {
for (Counter c : notedCounters.values()) { //would be nice if could just use that copy function to set the whole field
if (c != null) {
- newPermanent.getCounters(game).addCounter(c);
+ newPermanent.getCounters(game).addCounter(c); // it's restore counters, not add (e.g. without add events)
}
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TeferiTimeRaveler.java b/Mage.Sets/src/mage/cards/t/TeferiTimeRaveler.java
index f35b55d7b48..803f9475ec0 100644
--- a/Mage.Sets/src/mage/cards/t/TeferiTimeRaveler.java
+++ b/Mage.Sets/src/mage/cards/t/TeferiTimeRaveler.java
@@ -58,7 +58,7 @@ public final class TeferiTimeRaveler extends CardImpl {
// -3: Return up to one target artifact, creature, or enchantment to its owner's hand. Draw a card.
Ability ability = new LoyaltyAbility(new ReturnToHandTargetEffect(), -3);
ability.addEffect(new DrawCardSourceControllerEffect(1).setText("Draw a card"));
- ability.addTarget(new TargetPermanent(filter2));
+ ability.addTarget(new TargetPermanent(0, 1, filter2, false));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/t/TerentatekCub.java b/Mage.Sets/src/mage/cards/t/TerentatekCub.java
index 77f191bad00..0634db6c4cf 100644
--- a/Mage.Sets/src/mage/cards/t/TerentatekCub.java
+++ b/Mage.Sets/src/mage/cards/t/TerentatekCub.java
@@ -1,11 +1,12 @@
-
package mage.cards.t;
-import java.util.UUID;
import mage.MageInt;
+import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.OpponentControlsPermanentCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.decorator.ConditionalRequirementEffect;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.common.combat.AttacksIfAbleSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
@@ -18,8 +19,9 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
+import java.util.UUID;
+
/**
- *
* @author Styxo
*/
public final class TerentatekCub extends CardImpl {
@@ -36,17 +38,15 @@ public final class TerentatekCub extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
- // As long as an opponent controls a Jedi or Sith, {this} gets +1/+1 and attacks each turn if able
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
+ // As long as an opponent controls a Jedi or Sith, {this} gets +1/+1 and attacks each turn if able
+ Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
new BoostSourceEffect(1, 1, Duration.Custom),
new OpponentControlsPermanentCondition(filter),
- "As long as an opponent controls a Jedi or Sith, {this} gets +1/+1 ")
- ));
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
- new AttacksIfAbleSourceEffect(Duration.Custom),
- new OpponentControlsPermanentCondition(filter),
- "and attacks each turn if able.")
- ));
+ "As long as an opponent controls a Jedi or Sith, {this} gets +1/+1"));
+ Effect effect = new ConditionalRequirementEffect(new AttacksIfAbleSourceEffect(Duration.Custom), new OpponentControlsPermanentCondition(filter));
+ effect.setText("and attacks each turn if able");
+ ability.addEffect(effect);
+ this.addAbility(ability);
}
public TerentatekCub(final TerentatekCub card) {
diff --git a/Mage.Sets/src/mage/cards/t/TheWanderer.java b/Mage.Sets/src/mage/cards/t/TheWanderer.java
index 4bdfe787fce..f1820f59683 100644
--- a/Mage.Sets/src/mage/cards/t/TheWanderer.java
+++ b/Mage.Sets/src/mage/cards/t/TheWanderer.java
@@ -20,12 +20,15 @@ import mage.filter.predicate.permanent.AnotherPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
+import mage.abilities.effects.common.PreventDamageToControllerEffect;
/**
* @author TheElk801
*/
public final class TheWanderer extends CardImpl {
+ private static final String rule = "Prevent all noncombat damage that "
+ + "would be dealt to you and other permanents you control.";
private static final FilterPermanent filter
= new FilterControlledPermanent("other permanents you control");
private static final FilterPermanent filter2
@@ -43,11 +46,15 @@ public final class TheWanderer extends CardImpl {
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// Prevent all noncombat damage that would be dealt to you and other permanents you control.
+ this.addAbility(new SimpleStaticAbility(
+ new PreventDamageToControllerEffect(
+ Duration.WhileOnBattlefield, true, false,
+ Integer.MAX_VALUE
+ ).setText(rule)));
this.addAbility(new SimpleStaticAbility(
new PreventAllNonCombatDamageToAllEffect(
Duration.WhileOnBattlefield, filter, true
- )
- ));
+ ).setText("")));
// -2: Exile target creature with power 4 or greater.
Ability ability = new LoyaltyAbility(new ExileTargetEffect(), -2);
diff --git a/Mage.Sets/src/mage/cards/t/TidehollowSculler.java b/Mage.Sets/src/mage/cards/t/TidehollowSculler.java
index b1e2bacc962..16341e86931 100644
--- a/Mage.Sets/src/mage/cards/t/TidehollowSculler.java
+++ b/Mage.Sets/src/mage/cards/t/TidehollowSculler.java
@@ -17,7 +17,6 @@ import mage.constants.Zone;
import mage.filter.common.FilterNonlandCard;
import mage.game.ExileZone;
import mage.game.Game;
-import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.players.Player;
import mage.target.TargetCard;
@@ -79,11 +78,9 @@ class TidehollowScullerExileEffect extends OneShotEffect {
// 6/7/2013 If Tidehollow Sculler leaves the battlefield before its first ability has resolved,
// its second ability will trigger. This ability will do nothing when it resolves.
// Then its first ability will resolve and exile the chosen card forever.
- Permanent sourcePermanent = (Permanent) source.getSourcePermanentIfItStillExists(game);
if (controller != null
- && opponent != null
- && sourcePermanent != null) {
- opponent.revealCards(sourcePermanent.getName(), opponent.getHand(), game);
+ && opponent != null) {
+ opponent.revealCards("Tidehollow Sculler", opponent.getHand(), game);
TargetCard target = new TargetCard(Zone.HAND, new FilterNonlandCard("nonland card to exile"));
if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) {
Card card = opponent.getHand().get(target.getFirstTarget(), game);
@@ -96,7 +93,7 @@ class TidehollowScullerExileEffect extends OneShotEffect {
CardUtil.getExileZoneId(game,
source.getSourceId(),
source.getSourceObjectZoneChangeCounter()),
- sourcePermanent.getIdName());
+ "Tidehollow Sculler");
}
}
return true;
@@ -126,8 +123,8 @@ class TidehollowScullerLeaveEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
- int zoneChangeCounter = (sourceObject instanceof PermanentToken)
- ? source.getSourceObjectZoneChangeCounter()
+ int zoneChangeCounter = (sourceObject instanceof PermanentToken)
+ ? source.getSourceObjectZoneChangeCounter()
: source.getSourceObjectZoneChangeCounter() - 1;
ExileZone exZone = game.getExile().getExileZone(
CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter));
diff --git a/Mage.Sets/src/mage/cards/u/UginTheIneffable.java b/Mage.Sets/src/mage/cards/u/UginTheIneffable.java
index c8f079335d7..18a511fffac 100644
--- a/Mage.Sets/src/mage/cards/u/UginTheIneffable.java
+++ b/Mage.Sets/src/mage/cards/u/UginTheIneffable.java
@@ -23,15 +23,17 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
-import mage.game.permanent.token.Token;
import mage.game.permanent.token.UginTheIneffableToken;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;
-
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
+import mage.abilities.effects.AsThoughEffectImpl;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.InfoEffect;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import static mage.constants.Outcome.Benefit;
@@ -83,9 +85,9 @@ class UginTheIneffableEffect extends OneShotEffect {
UginTheIneffableEffect() {
super(Benefit);
- staticText = "Exile the top card of your library face down and look at it. " +
- "Create a 2/2 colorless Spirit creature token. When that token leaves the battlefield, " +
- "put the exiled card into your hand.";
+ staticText = "Exile the top card of your library face down and look at it. "
+ + "Create a 2/2 colorless Spirit creature token. When that token leaves the battlefield, "
+ + "put the exiled card into your hand.";
}
private UginTheIneffableEffect(final UginTheIneffableEffect effect) {
@@ -108,15 +110,28 @@ class UginTheIneffableEffect extends OneShotEffect {
player.lookAtCards(sourcePermanent.getIdName(), card, game);
player.moveCards(card, Zone.EXILED, source, game);
card.turnFaceDown(game, source.getControllerId());
- Token token = new UginTheIneffableToken();
- token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
Set tokenObjs = new HashSet<>();
- for (UUID tokenId : token.getLastAddedTokenIds()) {
- tokenObjs.add(new MageObjectReference(tokenId, game));
+ CreateTokenEffect effect = new CreateTokenEffect(new UginTheIneffableToken());
+ effect.apply(game, source);
+ for (UUID addedTokenId : effect.getLastAddedTokenIds()) {
+
+ // display referenced exiled face-down card on token
+ SimpleStaticAbility sa = new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("Referenced object: "
+ + card.getId().toString().substring(0, 3)));
+ GainAbilityTargetEffect gainAbilityEffect = new GainAbilityTargetEffect(sa, Duration.WhileOnBattlefield);
+ gainAbilityEffect.setTargetPointer(new FixedTarget(addedTokenId));
+ game.addEffect(gainAbilityEffect, source);
+
+ // look at face-down card in exile
+ UginTheIneffableLookAtFaceDownEffect lookAtEffect = new UginTheIneffableLookAtFaceDownEffect();
+ lookAtEffect.setTargetPointer(new FixedTarget(card.getId()));
+ game.addEffect(lookAtEffect, source);
+
+ tokenObjs.add(new MageObjectReference(addedTokenId, game));
+ game.addDelayedTriggeredAbility(new UginTheIneffableDelayedTriggeredAbility(
+ tokenObjs, new MageObjectReference(card, game)
+ ), source);
}
- game.addDelayedTriggeredAbility(new UginTheIneffableDelayedTriggeredAbility(
- tokenObjs, new MageObjectReference(card, game)
- ), source);
return true;
}
}
@@ -167,3 +182,35 @@ class UginTheIneffableDelayedTriggeredAbility extends DelayedTriggeredAbility {
return "When this token leaves the battlefield, put the exiled card into your hand.";
}
}
+
+class UginTheIneffableLookAtFaceDownEffect extends AsThoughEffectImpl {
+
+ UginTheIneffableLookAtFaceDownEffect() {
+ super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.EndOfGame, Outcome.Benefit);
+ }
+
+ private UginTheIneffableLookAtFaceDownEffect(final UginTheIneffableLookAtFaceDownEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public UginTheIneffableLookAtFaceDownEffect copy() {
+ return new UginTheIneffableLookAtFaceDownEffect(this);
+ }
+
+ @Override
+ public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
+ UUID cardId = getTargetPointer().getFirst(game, source);
+ if (cardId == null) {
+ this.discard();
+ }
+ return affectedControllerId.equals(source.getControllerId())
+ && objectId.equals(cardId)
+ && game.getState().getExile().containsId(cardId, game);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java b/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java
index d1442674c93..483b834f2b6 100644
--- a/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java
+++ b/Mage.Sets/src/mage/cards/v/VeteranBodyguard.java
@@ -1,20 +1,17 @@
-
package mage.cards.v;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.SourceTappedCondition;
-import mage.abilities.decorator.ConditionalContinuousEffect;
-import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.decorator.ConditionalPreventionEffect;
+import mage.abilities.effects.PreventionEffectImpl;
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.FilterCreaturePermanent;
import mage.filter.predicate.permanent.UnblockedPredicate;
@@ -24,8 +21,9 @@ import mage.game.events.DamagePlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
+import java.util.UUID;
+
/**
- *
* @author MTGfan
*/
public final class VeteranBodyguard extends CardImpl {
@@ -38,7 +36,11 @@ public final class VeteranBodyguard extends CardImpl {
this.toughness = new MageInt(5);
// As long as Veteran Bodyguard is untapped, all damage that would be dealt to you by unblocked creatures is dealt to Veteran Bodyguard instead.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new VeteranBodyguardEffect(), new InvertCondition(SourceTappedCondition.instance), "As long as {this} is untapped, all damage that would be dealt to you by unblocked creatures is dealt to {this} instead.")));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalPreventionEffect(
+ new VeteranBodyguardEffect(),
+ new InvertCondition(SourceTappedCondition.instance),
+ "As long as {this} is untapped, all damage that would be dealt to you by unblocked creatures is dealt to {this} instead."
+ )));
}
public VeteranBodyguard(final VeteranBodyguard card) {
@@ -51,7 +53,7 @@ public final class VeteranBodyguard extends CardImpl {
}
}
-class VeteranBodyguardEffect extends ReplacementEffectImpl {
+class VeteranBodyguardEffect extends PreventionEffectImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("unblocked creatures");
@@ -60,7 +62,7 @@ class VeteranBodyguardEffect extends ReplacementEffectImpl {
}
VeteranBodyguardEffect() {
- super(Duration.WhileOnBattlefield, Outcome.RedirectDamage);
+ super(Duration.WhileOnBattlefield);
staticText = "all combat damage that would be dealt to you by unblocked creatures is dealt to {source} instead";
}
@@ -76,7 +78,7 @@ class VeteranBodyguardEffect extends ReplacementEffectImpl {
permanent.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable());
return true;
}
- return true;
+ return false;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/v/VizierOfRemedies.java b/Mage.Sets/src/mage/cards/v/VizierOfRemedies.java
index 2823ffa75b1..29e2cd99528 100644
--- a/Mage.Sets/src/mage/cards/v/VizierOfRemedies.java
+++ b/Mage.Sets/src/mage/cards/v/VizierOfRemedies.java
@@ -1,24 +1,19 @@
-
package mage.cards.v;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
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.constants.*;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
+import java.util.UUID;
+
/**
- *
* @author Stravant
*/
public final class VizierOfRemedies extends CardImpl {
@@ -64,7 +59,7 @@ class VizierOfRemediesReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- event.setAmount(event.getAmount() - 1);
+ event.setAmountForCounters(event.getAmount() - 1, true);
return false;
}
@@ -76,11 +71,9 @@ class VizierOfRemediesReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (source != null && source.getControllerId() != null) {
- if (source.isControlledBy(game.getControllerId(event.getTargetId()))
+ return source.isControlledBy(game.getControllerId(event.getTargetId()))
&& event.getData() != null && event.getData().equals(CounterType.M1M1.getName())
- && event.getAmount() > 0) {
- return true;
- }
+ && event.getAmount() > 0;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/v/VonasHunger.java b/Mage.Sets/src/mage/cards/v/VonasHunger.java
index 3d4c435349b..ce015602733 100644
--- a/Mage.Sets/src/mage/cards/v/VonasHunger.java
+++ b/Mage.Sets/src/mage/cards/v/VonasHunger.java
@@ -8,6 +8,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeOpponentsEffect;
import mage.abilities.effects.keyword.AscendEffect;
import mage.abilities.hint.common.CitysBlessingHint;
+import mage.abilities.hint.common.PermanentsYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -32,6 +33,8 @@ public final class VonasHunger extends CardImpl {
// Ascend (If you control ten or more permanents, you get the city's blessing for the rest of the game.)
this.getSpellAbility().addEffect(new AscendEffect());
+ this.getSpellAbility().addHint(CitysBlessingHint.instance);
+ this.getSpellAbility().addHint(PermanentsYouControlHint.instance);
// Each opponent sacrifices a creature.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
@@ -43,7 +46,6 @@ public final class VonasHunger extends CardImpl {
new VonasHungerEffect(),
CitysBlessingCondition.instance,
"If you have the city's blessing, instead each opponent sacrifices half the creatures he or she controls rounded up"));
- this.getSpellAbility().addHint(CitysBlessingHint.instance);
}
public VonasHunger(final VonasHunger card) {
diff --git a/Mage.Sets/src/mage/cards/v/VraskaSwarmsEminence.java b/Mage.Sets/src/mage/cards/v/VraskaSwarmsEminence.java
index e1a7d3f2a5f..3dc008f4edb 100644
--- a/Mage.Sets/src/mage/cards/v/VraskaSwarmsEminence.java
+++ b/Mage.Sets/src/mage/cards/v/VraskaSwarmsEminence.java
@@ -1,31 +1,35 @@
package mage.cards.v;
+import java.util.UUID;
import mage.abilities.LoyaltyAbility;
-import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
+import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.constants.SuperType;
+import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
-import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.AbilityPredicate;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
import mage.game.permanent.token.AssassinToken2;
-
-import java.util.UUID;
+import mage.target.targetpointer.FixedTarget;
/**
* @author TheElk801
*/
public final class VraskaSwarmsEminence extends CardImpl {
- private static final FilterPermanent filter = new FilterCreaturePermanent("creature you control with deathtouch");
+ private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creature you control with deathtouch");
static {
filter.add(new AbilityPredicate(DeathtouchAbility.class));
@@ -39,12 +43,9 @@ public final class VraskaSwarmsEminence extends CardImpl {
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// Whenever a creature you control with deathtouch deals damage to a player or planeswalker, put a +1/+1 counter on that creature.
- // TODO: make this trigger on planeswalkers
- this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(
- new AddCountersTargetEffect(
- CounterType.P1P1.createInstance()
- ).setText("put a +1/+1 counter on that creature"),
- filter, false, SetTargetPointer.PERMANENT, false)
+ this.addAbility(new VraskaSwarmsEminenceTriggeredAbility(Zone.BATTLEFIELD,
+ new AddCountersTargetEffect(CounterType.P1P1.createInstance()).setText("put a +1/+1 counter on that creature"),
+ filter)
);
// -2: Create a 1/1 black Assassin creature token with deathtouch and "Whenever this creature deals damage to a planeswalker, destroy that planeswalker."
@@ -60,3 +61,49 @@ public final class VraskaSwarmsEminence extends CardImpl {
return new VraskaSwarmsEminence(this);
}
}
+
+class VraskaSwarmsEminenceTriggeredAbility extends TriggeredAbilityImpl {
+
+ private final FilterPermanent filter;
+
+ public VraskaSwarmsEminenceTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter) {
+ super(zone, effect, false);
+ this.filter = filter;
+ }
+
+ public VraskaSwarmsEminenceTriggeredAbility(final VraskaSwarmsEminenceTriggeredAbility ability) {
+ super(ability);
+ this.filter = ability.filter;
+ }
+
+ @Override
+ public VraskaSwarmsEminenceTriggeredAbility copy() {
+ return new VraskaSwarmsEminenceTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.DAMAGED_PLAYER
+ || event.getType() == GameEvent.EventType.DAMAGED_PLANESWALKER;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ Permanent permanent = game.getPermanent(event.getSourceId());
+ if (permanent != null && filter.match(permanent, getSourceId(), getControllerId(), game)) {
+ for (Effect effect : this.getEffects()) {
+ effect.setValue("damage", event.getAmount());
+ effect.setValue("sourceId", event.getSourceId());
+ effect.setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game)));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever a creature you control with deathtouch deals damage to a player or planeswalker," + super.getRule();
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/w/WindingConstrictor.java b/Mage.Sets/src/mage/cards/w/WindingConstrictor.java
index 3d113229f5e..c5db174c387 100644
--- a/Mage.Sets/src/mage/cards/w/WindingConstrictor.java
+++ b/Mage.Sets/src/mage/cards/w/WindingConstrictor.java
@@ -1,25 +1,20 @@
-
package mage.cards.w;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
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.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class WindingConstrictor extends CardImpl {
@@ -32,7 +27,7 @@ public final class WindingConstrictor extends CardImpl {
this.toughness = new MageInt(3);
// If one or more counters would be put on an artifact or creature you control, that many plus one of each of those kinds of counters are put on that permanent instead.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new WindingConstrictorPermanentEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new WindingConstrictorPermanentEffect()));
// If you would get one or more counters, you get that many plus one of each of those kinds of counters instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new WindingConstrictorPlayerEffect()));
@@ -62,7 +57,7 @@ class WindingConstrictorPermanentEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- event.setAmount(event.getAmount() + 1);
+ event.setAmountForCounters(event.getAmount() + 1, true);
return false;
}
@@ -78,6 +73,7 @@ class WindingConstrictorPermanentEffect extends ReplacementEffectImpl {
permanent = game.getPermanentEntering(event.getTargetId());
}
return permanent != null
+ && event.getAmount() > 0
&& (permanent.isCreature() || permanent.isArtifact())
&& permanent.isControlledBy(source.getControllerId());
}
@@ -106,7 +102,7 @@ class WindingConstrictorPlayerEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- event.setAmount(event.getAmount() + 1);
+ event.setAmountForCounters(event.getAmount() + 1, true);
return false;
}
@@ -118,7 +114,7 @@ class WindingConstrictorPlayerEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Player player = game.getPlayer(event.getTargetId());
- return player != null && player.getId().equals(source.getControllerId());
+ return player != null && player.getId().equals(source.getControllerId()) && event.getAmount() > 0;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/w/WookieeMystic.java b/Mage.Sets/src/mage/cards/w/WookieeMystic.java
index 1d8f1d879d9..655ffc900a7 100644
--- a/Mage.Sets/src/mage/cards/w/WookieeMystic.java
+++ b/Mage.Sets/src/mage/cards/w/WookieeMystic.java
@@ -1,16 +1,12 @@
-
package mage.cards.w;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.effects.mana.BasicManaEffect;
import mage.abilities.effects.common.ManaEffect;
+import mage.abilities.effects.mana.BasicManaEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,14 +22,17 @@ import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.watchers.Watcher;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
/**
- *
* @author Styxo
*/
public final class WookieeMystic extends CardImpl {
public WookieeMystic(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}{G}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{G}{W}");
this.subtype.add(SubType.WOOKIEE);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
@@ -45,21 +44,21 @@ public final class WookieeMystic extends CardImpl {
ManaEffect effect = new BasicManaEffect(mana);
effect.setText("Add {R}. If that mana is spent on a creature spell, it enters the battlefield with a +1/+1 counter on it");
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
- this.addAbility(ability, new WookieeMysticWatcher(ability));
+ this.addAbility(ability, new WookieeMysticWatcher().withParams(ability));
mana = Mana.GreenMana(1);
mana.setFlag(true);
effect = new BasicManaEffect(mana);
effect.setText("Add {G}. If that mana is spent on a creature spell, it enters the battlefield with a +1/+1 counter on it");
ability = new SimpleManaAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
- this.addAbility(ability, new WookieeMysticWatcher(ability));
+ this.addAbility(ability, new WookieeMysticWatcher().withParams(ability));
mana = Mana.WhiteMana(1);
mana.setFlag(true);
effect = new BasicManaEffect(mana);
effect.setText("Add {W}. If that mana is spent on a creature spell, it enters the battlefield with a +1/+1 counter on it");
ability = new SimpleManaAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
- this.addAbility(ability, new WookieeMysticWatcher(ability));
+ this.addAbility(ability, new WookieeMysticWatcher().withParams(ability));
}
public WookieeMystic(final WookieeMystic card) {
@@ -74,23 +73,16 @@ public final class WookieeMystic extends CardImpl {
class WookieeMysticWatcher extends Watcher {
- private final Ability source;
- private final List creatures = new ArrayList<>();
+ private Ability source;
+ private List creatures = new ArrayList<>();
- WookieeMysticWatcher(Ability source) {
+ WookieeMysticWatcher() {
super(WatcherScope.CARD);
+ }
+
+ Watcher withParams(Ability source) {
this.source = source;
- }
-
- WookieeMysticWatcher(final WookieeMysticWatcher watcher) {
- super(watcher);
- this.creatures.addAll(watcher.creatures);
- this.source = watcher.source;
- }
-
- @Override
- public WookieeMysticWatcher copy() {
- return new WookieeMysticWatcher(this);
+ return this;
}
@Override
diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java
index 863417b6bec..5c0ab4bc858 100644
--- a/Mage.Sets/src/mage/sets/IceAge.java
+++ b/Mage.Sets/src/mage/sets/IceAge.java
@@ -1,379 +1,380 @@
-package mage.sets;
-
-import mage.cards.ExpansionSet;
-import mage.constants.Rarity;
-import mage.constants.SetType;
-
-/**
- * @author North
- */
-public final class IceAge extends ExpansionSet {
-
- private static final IceAge instance = new IceAge();
-
- public static IceAge getInstance() {
- return instance;
- }
-
- private IceAge() {
- super("Ice Age", "ICE", ExpansionSet.buildDate(1995, 5, 1), SetType.EXPANSION);
- this.blockName = "Ice Age";
- this.hasBoosters = true;
- this.numBoosterLands = 0;
- this.numBoosterCommon = 11;
- this.numBoosterUncommon = 3;
- this.numBoosterRare = 1;
- this.ratioBoosterMythic = 0;
-
- cards.add(new SetCardInfo("Abyssal Specter", 113, Rarity.UNCOMMON, mage.cards.a.AbyssalSpecter.class));
- cards.add(new SetCardInfo("Adarkar Sentinel", 306, Rarity.UNCOMMON, mage.cards.a.AdarkarSentinel.class));
- cards.add(new SetCardInfo("Adarkar Wastes", 351, Rarity.RARE, mage.cards.a.AdarkarWastes.class));
- cards.add(new SetCardInfo("Aegis of the Meek", 307, Rarity.RARE, mage.cards.a.AegisOfTheMeek.class));
- cards.add(new SetCardInfo("Aggression", 169, Rarity.UNCOMMON, mage.cards.a.Aggression.class));
- cards.add(new SetCardInfo("Altar of Bone", 281, Rarity.RARE, mage.cards.a.AltarOfBone.class));
- cards.add(new SetCardInfo("Anarchy", 170, Rarity.UNCOMMON, mage.cards.a.Anarchy.class));
- cards.add(new SetCardInfo("Arenson's Aura", 3, Rarity.COMMON, mage.cards.a.ArensonsAura.class));
- cards.add(new SetCardInfo("Armor of Faith", 4, Rarity.COMMON, mage.cards.a.ArmorOfFaith.class));
- cards.add(new SetCardInfo("Arnjlot's Ascent", 57, Rarity.COMMON, mage.cards.a.ArnjlotsAscent.class));
- cards.add(new SetCardInfo("Ashen Ghoul", 114, Rarity.UNCOMMON, mage.cards.a.AshenGhoul.class));
- cards.add(new SetCardInfo("Aurochs", 225, Rarity.COMMON, mage.cards.a.Aurochs.class));
- cards.add(new SetCardInfo("Avalanche", 171, Rarity.UNCOMMON, mage.cards.a.Avalanche.class));
- cards.add(new SetCardInfo("Balduvian Barbarians", 172, Rarity.COMMON, mage.cards.b.BalduvianBarbarians.class));
- cards.add(new SetCardInfo("Balduvian Bears", 226, Rarity.COMMON, mage.cards.b.BalduvianBears.class));
- cards.add(new SetCardInfo("Balduvian Conjurer", 58, Rarity.UNCOMMON, mage.cards.b.BalduvianConjurer.class));
- cards.add(new SetCardInfo("Balduvian Hydra", 173, Rarity.RARE, mage.cards.b.BalduvianHydra.class));
- cards.add(new SetCardInfo("Barbed Sextant", 312, Rarity.COMMON, mage.cards.b.BarbedSextant.class));
- cards.add(new SetCardInfo("Baton of Morale", 313, Rarity.UNCOMMON, mage.cards.b.BatonOfMorale.class));
- cards.add(new SetCardInfo("Battle Cry", 5, Rarity.UNCOMMON, mage.cards.b.BattleCry.class));
- cards.add(new SetCardInfo("Battle Frenzy", 175, Rarity.COMMON, mage.cards.b.BattleFrenzy.class));
- cards.add(new SetCardInfo("Binding Grasp", 60, Rarity.UNCOMMON, mage.cards.b.BindingGrasp.class));
- cards.add(new SetCardInfo("Black Scarab", 6, Rarity.UNCOMMON, mage.cards.b.BlackScarab.class));
- cards.add(new SetCardInfo("Blessed Wine", 7, Rarity.COMMON, mage.cards.b.BlessedWine.class));
- cards.add(new SetCardInfo("Blinking Spirit", 8, Rarity.RARE, mage.cards.b.BlinkingSpirit.class));
- cards.add(new SetCardInfo("Blizzard", 227, Rarity.RARE, mage.cards.b.Blizzard.class));
- cards.add(new SetCardInfo("Blue Scarab", 9, Rarity.UNCOMMON, mage.cards.b.BlueScarab.class));
- cards.add(new SetCardInfo("Brainstorm", 61, Rarity.COMMON, mage.cards.b.Brainstorm.class));
- cards.add(new SetCardInfo("Brand of Ill Omen", 177, Rarity.RARE, mage.cards.b.BrandOfIllOmen.class));
- cards.add(new SetCardInfo("Breath of Dreams", 62, Rarity.UNCOMMON, mage.cards.b.BreathOfDreams.class));
- cards.add(new SetCardInfo("Brine Shaman", 115, Rarity.COMMON, mage.cards.b.BrineShaman.class));
- cards.add(new SetCardInfo("Brown Ouphe", 228, Rarity.COMMON, mage.cards.b.BrownOuphe.class));
- cards.add(new SetCardInfo("Brushland", 352, Rarity.RARE, mage.cards.b.Brushland.class));
- cards.add(new SetCardInfo("Burnt Offering", 116, Rarity.COMMON, mage.cards.b.BurntOffering.class));
- cards.add(new SetCardInfo("Call to Arms", 10, Rarity.RARE, mage.cards.c.CallToArms.class));
- cards.add(new SetCardInfo("Caribou Range", 11, Rarity.RARE, mage.cards.c.CaribouRange.class));
- cards.add(new SetCardInfo("Celestial Sword", 314, Rarity.RARE, mage.cards.c.CelestialSword.class));
- cards.add(new SetCardInfo("Centaur Archer", 282, Rarity.UNCOMMON, mage.cards.c.CentaurArcher.class));
- cards.add(new SetCardInfo("Chaos Lord", 178, Rarity.RARE, mage.cards.c.ChaosLord.class));
- cards.add(new SetCardInfo("Chaos Moon", 179, Rarity.RARE, mage.cards.c.ChaosMoon.class));
- cards.add(new SetCardInfo("Chub Toad", 229, Rarity.COMMON, mage.cards.c.ChubToad.class));
- cards.add(new SetCardInfo("Circle of Protection: Black", 12, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlack.class));
- cards.add(new SetCardInfo("Circle of Protection: Blue", 13, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlue.class));
- cards.add(new SetCardInfo("Circle of Protection: Green", 14, Rarity.COMMON, mage.cards.c.CircleOfProtectionGreen.class));
- cards.add(new SetCardInfo("Circle of Protection: Red", 15, Rarity.COMMON, mage.cards.c.CircleOfProtectionRed.class));
- cards.add(new SetCardInfo("Circle of Protection: White", 16, Rarity.COMMON, mage.cards.c.CircleOfProtectionWhite.class));
- cards.add(new SetCardInfo("Clairvoyance", 63, Rarity.COMMON, mage.cards.c.Clairvoyance.class));
- cards.add(new SetCardInfo("Cloak of Confusion", 117, Rarity.COMMON, mage.cards.c.CloakOfConfusion.class));
- cards.add(new SetCardInfo("Cold Snap", 17, Rarity.UNCOMMON, mage.cards.c.ColdSnap.class));
- cards.add(new SetCardInfo("Conquer", 180, Rarity.UNCOMMON, mage.cards.c.Conquer.class));
- cards.add(new SetCardInfo("Cooperation", 18, Rarity.COMMON, mage.cards.c.Cooperation.class));
- cards.add(new SetCardInfo("Counterspell", 64, Rarity.COMMON, mage.cards.c.Counterspell.class));
- cards.add(new SetCardInfo("Crown of the Ages", 315, Rarity.RARE, mage.cards.c.CrownOfTheAges.class));
- cards.add(new SetCardInfo("Curse of Marit Lage", 181, Rarity.RARE, mage.cards.c.CurseOfMaritLage.class));
- cards.add(new SetCardInfo("Dance of the Dead", 118, Rarity.UNCOMMON, mage.cards.d.DanceOfTheDead.class));
- cards.add(new SetCardInfo("Dark Banishing", 119, Rarity.COMMON, mage.cards.d.DarkBanishing.class));
- cards.add(new SetCardInfo("Dark Ritual", 120, Rarity.COMMON, mage.cards.d.DarkRitual.class));
- cards.add(new SetCardInfo("Death Ward", 19, Rarity.COMMON, mage.cards.d.DeathWard.class));
- cards.add(new SetCardInfo("Deflection", 65, Rarity.RARE, mage.cards.d.Deflection.class));
- cards.add(new SetCardInfo("Demonic Consultation", 121, Rarity.UNCOMMON, mage.cards.d.DemonicConsultation.class));
- cards.add(new SetCardInfo("Despotic Scepter", 316, Rarity.RARE, mage.cards.d.DespoticScepter.class));
- cards.add(new SetCardInfo("Diabolic Vision", 284, Rarity.UNCOMMON, mage.cards.d.DiabolicVision.class));
- cards.add(new SetCardInfo("Dire Wolves", 230, Rarity.COMMON, mage.cards.d.DireWolves.class));
- cards.add(new SetCardInfo("Disenchant", 20, Rarity.COMMON, mage.cards.d.Disenchant.class));
- cards.add(new SetCardInfo("Dread Wight", 122, Rarity.RARE, mage.cards.d.DreadWight.class));
- cards.add(new SetCardInfo("Dreams of the Dead", 66, Rarity.UNCOMMON, mage.cards.d.DreamsOfTheDead.class));
- cards.add(new SetCardInfo("Drift of the Dead", 123, Rarity.UNCOMMON, mage.cards.d.DriftOfTheDead.class));
- cards.add(new SetCardInfo("Drought", 21, Rarity.UNCOMMON, mage.cards.d.Drought.class));
- cards.add(new SetCardInfo("Dwarven Armory", 182, Rarity.RARE, mage.cards.d.DwarvenArmory.class));
- cards.add(new SetCardInfo("Earthlink", 285, Rarity.RARE, mage.cards.e.Earthlink.class));
- cards.add(new SetCardInfo("Earthlore", 231, Rarity.COMMON, mage.cards.e.Earthlore.class));
- cards.add(new SetCardInfo("Elder Druid", 232, Rarity.RARE, mage.cards.e.ElderDruid.class));
- cards.add(new SetCardInfo("Elemental Augury", 286, Rarity.RARE, mage.cards.e.ElementalAugury.class));
- cards.add(new SetCardInfo("Elkin Bottle", 317, Rarity.RARE, mage.cards.e.ElkinBottle.class));
- cards.add(new SetCardInfo("Enduring Renewal", 23, Rarity.RARE, mage.cards.e.EnduringRenewal.class));
- cards.add(new SetCardInfo("Energy Storm", 24, Rarity.RARE, mage.cards.e.EnergyStorm.class));
- cards.add(new SetCardInfo("Enervate", 67, Rarity.COMMON, mage.cards.e.Enervate.class));
- cards.add(new SetCardInfo("Errant Minion", 68, Rarity.COMMON, mage.cards.e.ErrantMinion.class));
- cards.add(new SetCardInfo("Errantry", 183, Rarity.COMMON, mage.cards.e.Errantry.class));
- cards.add(new SetCardInfo("Essence Filter", 233, Rarity.COMMON, mage.cards.e.EssenceFilter.class));
- cards.add(new SetCardInfo("Essence Flare", 69, Rarity.COMMON, mage.cards.e.EssenceFlare.class));
- cards.add(new SetCardInfo("Fanatical Fever", 234, Rarity.UNCOMMON, mage.cards.f.FanaticalFever.class));
- cards.add(new SetCardInfo("Fear", 124, Rarity.COMMON, mage.cards.f.Fear.class));
- cards.add(new SetCardInfo("Fiery Justice", 288, Rarity.RARE, mage.cards.f.FieryJustice.class));
- cards.add(new SetCardInfo("Fire Covenant", 289, Rarity.UNCOMMON, mage.cards.f.FireCovenant.class));
- cards.add(new SetCardInfo("Flame Spirit", 184, Rarity.UNCOMMON, mage.cards.f.FlameSpirit.class));
- cards.add(new SetCardInfo("Flare", 185, Rarity.COMMON, mage.cards.f.Flare.class));
- cards.add(new SetCardInfo("Flooded Woodlands", 290, Rarity.RARE, mage.cards.f.FloodedWoodlands.class));
- cards.add(new SetCardInfo("Flow of Maggots", 125, Rarity.RARE, mage.cards.f.FlowOfMaggots.class));
- cards.add(new SetCardInfo("Folk of the Pines", 235, Rarity.COMMON, mage.cards.f.FolkOfThePines.class));
- cards.add(new SetCardInfo("Forbidden Lore", 236, Rarity.RARE, mage.cards.f.ForbiddenLore.class));
- cards.add(new SetCardInfo("Force Void", 70, Rarity.UNCOMMON, mage.cards.f.ForceVoid.class));
- cards.add(new SetCardInfo("Forest", 380, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Forest", 381, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Forest", 382, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Forgotten Lore", 237, Rarity.UNCOMMON, mage.cards.f.ForgottenLore.class));
- cards.add(new SetCardInfo("Formation", 25, Rarity.RARE, mage.cards.f.Formation.class));
- cards.add(new SetCardInfo("Foul Familiar", 126, Rarity.COMMON, mage.cards.f.FoulFamiliar.class));
- cards.add(new SetCardInfo("Foxfire", 238, Rarity.COMMON, mage.cards.f.Foxfire.class));
- cards.add(new SetCardInfo("Freyalise Supplicant", 239, Rarity.UNCOMMON, mage.cards.f.FreyaliseSupplicant.class));
- cards.add(new SetCardInfo("Freyalise's Charm", 240, Rarity.UNCOMMON, mage.cards.f.FreyalisesCharm.class));
- cards.add(new SetCardInfo("Freyalise's Winds", 241, Rarity.RARE, mage.cards.f.FreyalisesWinds.class));
- cards.add(new SetCardInfo("Fumarole", 291, Rarity.UNCOMMON, mage.cards.f.Fumarole.class));
- cards.add(new SetCardInfo("Fyndhorn Bow", 318, Rarity.UNCOMMON, mage.cards.f.FyndhornBow.class));
- cards.add(new SetCardInfo("Fyndhorn Brownie", 242, Rarity.COMMON, mage.cards.f.FyndhornBrownie.class));
- cards.add(new SetCardInfo("Fyndhorn Elder", 243, Rarity.UNCOMMON, mage.cards.f.FyndhornElder.class));
- cards.add(new SetCardInfo("Fyndhorn Elves", 244, Rarity.COMMON, mage.cards.f.FyndhornElves.class));
- cards.add(new SetCardInfo("Fyndhorn Pollen", 245, Rarity.RARE, mage.cards.f.FyndhornPollen.class));
- cards.add(new SetCardInfo("Game of Chaos", 186, Rarity.RARE, mage.cards.g.GameOfChaos.class));
- cards.add(new SetCardInfo("Gangrenous Zombies", 127, Rarity.COMMON, mage.cards.g.GangrenousZombies.class));
- cards.add(new SetCardInfo("Gaze of Pain", 128, Rarity.COMMON, mage.cards.g.GazeOfPain.class));
- cards.add(new SetCardInfo("General Jarkeld", 27, Rarity.RARE, mage.cards.g.GeneralJarkeld.class));
- cards.add(new SetCardInfo("Giant Growth", 246, Rarity.COMMON, mage.cards.g.GiantGrowth.class));
- cards.add(new SetCardInfo("Giant Trap Door Spider", 293, Rarity.UNCOMMON, mage.cards.g.GiantTrapDoorSpider.class));
- cards.add(new SetCardInfo("Glacial Chasm", 353, Rarity.UNCOMMON, mage.cards.g.GlacialChasm.class));
- cards.add(new SetCardInfo("Glacial Crevasses", 187, Rarity.RARE, mage.cards.g.GlacialCrevasses.class));
- cards.add(new SetCardInfo("Glacial Wall", 71, Rarity.UNCOMMON, mage.cards.g.GlacialWall.class));
- cards.add(new SetCardInfo("Glaciers", 294, Rarity.RARE, mage.cards.g.Glaciers.class));
- cards.add(new SetCardInfo("Goblin Lyre", 319, Rarity.RARE, mage.cards.g.GoblinLyre.class));
- cards.add(new SetCardInfo("Goblin Mutant", 188, Rarity.UNCOMMON, mage.cards.g.GoblinMutant.class));
- cards.add(new SetCardInfo("Goblin Snowman", 191, Rarity.UNCOMMON, mage.cards.g.GoblinSnowman.class));
- cards.add(new SetCardInfo("Gorilla Pack", 247, Rarity.COMMON, mage.cards.g.GorillaPack.class));
- cards.add(new SetCardInfo("Gravebind", 129, Rarity.RARE, mage.cards.g.Gravebind.class));
- cards.add(new SetCardInfo("Green Scarab", 28, Rarity.UNCOMMON, mage.cards.g.GreenScarab.class));
- cards.add(new SetCardInfo("Hallowed Ground", 29, Rarity.UNCOMMON, mage.cards.h.HallowedGround.class));
- cards.add(new SetCardInfo("Halls of Mist", 354, Rarity.RARE, mage.cards.h.HallsOfMist.class));
- cards.add(new SetCardInfo("Heal", 30, Rarity.COMMON, mage.cards.h.Heal.class));
- cards.add(new SetCardInfo("Hecatomb", 130, Rarity.RARE, mage.cards.h.Hecatomb.class));
- cards.add(new SetCardInfo("Hematite Talisman", 320, Rarity.UNCOMMON, mage.cards.h.HematiteTalisman.class));
- cards.add(new SetCardInfo("Hoar Shade", 131, Rarity.COMMON, mage.cards.h.HoarShade.class));
- cards.add(new SetCardInfo("Hot Springs", 248, Rarity.RARE, mage.cards.h.HotSprings.class));
- cards.add(new SetCardInfo("Howl from Beyond", 132, Rarity.COMMON, mage.cards.h.HowlFromBeyond.class));
- cards.add(new SetCardInfo("Hurricane", 249, Rarity.UNCOMMON, mage.cards.h.Hurricane.class));
- cards.add(new SetCardInfo("Hyalopterous Lemure", 133, Rarity.UNCOMMON, mage.cards.h.HyalopterousLemure.class));
- cards.add(new SetCardInfo("Hydroblast", 72, Rarity.COMMON, mage.cards.h.Hydroblast.class));
- cards.add(new SetCardInfo("Hymn of Rebirth", 295, Rarity.UNCOMMON, mage.cards.h.HymnOfRebirth.class));
- cards.add(new SetCardInfo("Ice Cauldron", 321, Rarity.RARE, mage.cards.i.IceCauldron.class));
- cards.add(new SetCardInfo("Ice Floe", 355, Rarity.UNCOMMON, mage.cards.i.IceFloe.class));
- cards.add(new SetCardInfo("Iceberg", 73, Rarity.UNCOMMON, mage.cards.i.Iceberg.class));
- cards.add(new SetCardInfo("Icequake", 134, Rarity.UNCOMMON, mage.cards.i.Icequake.class));
- cards.add(new SetCardInfo("Icy Manipulator", 322, Rarity.UNCOMMON, mage.cards.i.IcyManipulator.class));
- cards.add(new SetCardInfo("Icy Prison", 74, Rarity.RARE, mage.cards.i.IcyPrison.class));
- cards.add(new SetCardInfo("Illusionary Forces", 75, Rarity.COMMON, mage.cards.i.IllusionaryForces.class));
- cards.add(new SetCardInfo("Illusionary Presence", 76, Rarity.RARE, mage.cards.i.IllusionaryPresence.class));
- cards.add(new SetCardInfo("Illusionary Terrain", 77, Rarity.UNCOMMON, mage.cards.i.IllusionaryTerrain.class));
- cards.add(new SetCardInfo("Illusionary Wall", 78, Rarity.COMMON, mage.cards.i.IllusionaryWall.class));
- cards.add(new SetCardInfo("Illusions of Grandeur", 79, Rarity.RARE, mage.cards.i.IllusionsOfGrandeur.class));
- cards.add(new SetCardInfo("Imposing Visage", 193, Rarity.COMMON, mage.cards.i.ImposingVisage.class));
- cards.add(new SetCardInfo("Incinerate", 194, Rarity.COMMON, mage.cards.i.Incinerate.class));
- cards.add(new SetCardInfo("Infernal Darkness", 135, Rarity.RARE, mage.cards.i.InfernalDarkness.class));
- cards.add(new SetCardInfo("Infernal Denizen", 136, Rarity.RARE, mage.cards.i.InfernalDenizen.class));
- cards.add(new SetCardInfo("Infinite Hourglass", 323, Rarity.RARE, mage.cards.i.InfiniteHourglass.class));
- cards.add(new SetCardInfo("Infuse", 80, Rarity.COMMON, mage.cards.i.Infuse.class));
- cards.add(new SetCardInfo("Island", 368, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Island", 369, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Island", 370, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Jester's Cap", 324, Rarity.RARE, mage.cards.j.JestersCap.class));
- cards.add(new SetCardInfo("Jester's Mask", 325, Rarity.RARE, mage.cards.j.JestersMask.class));
- cards.add(new SetCardInfo("Jeweled Amulet", 326, Rarity.UNCOMMON, mage.cards.j.JeweledAmulet.class));
- cards.add(new SetCardInfo("Johtull Wurm", 250, Rarity.UNCOMMON, mage.cards.j.JohtullWurm.class));
- cards.add(new SetCardInfo("Jokulhaups", 195, Rarity.RARE, mage.cards.j.Jokulhaups.class));
- cards.add(new SetCardInfo("Juniper Order Druid", 251, Rarity.COMMON, mage.cards.j.JuniperOrderDruid.class));
- cards.add(new SetCardInfo("Justice", 32, Rarity.UNCOMMON, mage.cards.j.Justice.class));
- cards.add(new SetCardInfo("Karplusan Forest", 356, Rarity.RARE, mage.cards.k.KarplusanForest.class));
- cards.add(new SetCardInfo("Karplusan Giant", 196, Rarity.UNCOMMON, mage.cards.k.KarplusanGiant.class));
- cards.add(new SetCardInfo("Karplusan Yeti", 197, Rarity.RARE, mage.cards.k.KarplusanYeti.class));
- cards.add(new SetCardInfo("Kelsinko Ranger", 33, Rarity.COMMON, mage.cards.k.KelsinkoRanger.class));
- cards.add(new SetCardInfo("Kjeldoran Dead", 137, Rarity.COMMON, mage.cards.k.KjeldoranDead.class));
- cards.add(new SetCardInfo("Kjeldoran Frostbeast", 296, Rarity.UNCOMMON, mage.cards.k.KjeldoranFrostbeast.class));
- cards.add(new SetCardInfo("Kjeldoran Knight", 36, Rarity.RARE, mage.cards.k.KjeldoranKnight.class));
- cards.add(new SetCardInfo("Kjeldoran Phalanx", 37, Rarity.RARE, mage.cards.k.KjeldoranPhalanx.class));
- cards.add(new SetCardInfo("Kjeldoran Royal Guard", 38, Rarity.RARE, mage.cards.k.KjeldoranRoyalGuard.class));
- cards.add(new SetCardInfo("Kjeldoran Skycaptain", 39, Rarity.UNCOMMON, mage.cards.k.KjeldoranSkycaptain.class));
- cards.add(new SetCardInfo("Kjeldoran Skyknight", 40, Rarity.COMMON, mage.cards.k.KjeldoranSkyknight.class));
- cards.add(new SetCardInfo("Kjeldoran Warrior", 41, Rarity.COMMON, mage.cards.k.KjeldoranWarrior.class));
- cards.add(new SetCardInfo("Knight of Stromgald", 138, Rarity.UNCOMMON, mage.cards.k.KnightOfStromgald.class));
- cards.add(new SetCardInfo("Krovikan Elementalist", 139, Rarity.UNCOMMON, mage.cards.k.KrovikanElementalist.class));
- cards.add(new SetCardInfo("Krovikan Fetish", 140, Rarity.COMMON, mage.cards.k.KrovikanFetish.class));
- cards.add(new SetCardInfo("Krovikan Sorcerer", 81, Rarity.COMMON, mage.cards.k.KrovikanSorcerer.class));
- cards.add(new SetCardInfo("Krovikan Vampire", 141, Rarity.UNCOMMON, mage.cards.k.KrovikanVampire.class));
- cards.add(new SetCardInfo("Land Cap", 357, Rarity.RARE, mage.cards.l.LandCap.class));
- cards.add(new SetCardInfo("Lapis Lazuli Talisman", 327, Rarity.UNCOMMON, mage.cards.l.LapisLazuliTalisman.class));
- cards.add(new SetCardInfo("Lava Tubes", 358, Rarity.RARE, mage.cards.l.LavaTubes.class));
- cards.add(new SetCardInfo("Legions of Lim-Dul", 142, Rarity.COMMON, mage.cards.l.LegionsOfLimDul.class));
- cards.add(new SetCardInfo("Leshrac's Rite", 143, Rarity.UNCOMMON, mage.cards.l.LeshracsRite.class));
- cards.add(new SetCardInfo("Leshrac's Sigil", 144, Rarity.UNCOMMON, mage.cards.l.LeshracsSigil.class));
- cards.add(new SetCardInfo("Lhurgoyf", 252, Rarity.RARE, mage.cards.l.Lhurgoyf.class));
- cards.add(new SetCardInfo("Lightning Blow", 42, Rarity.RARE, mage.cards.l.LightningBlow.class));
- cards.add(new SetCardInfo("Lim-Dul's Cohort", 145, Rarity.COMMON, mage.cards.l.LimDulsCohort.class));
- cards.add(new SetCardInfo("Lim-Dul's Hex", 146, Rarity.UNCOMMON, mage.cards.l.LimDulsHex.class));
- cards.add(new SetCardInfo("Lost Order of Jarkeld", 43, Rarity.RARE, mage.cards.l.LostOrderOfJarkeld.class));
- cards.add(new SetCardInfo("Lure", 253, Rarity.UNCOMMON, mage.cards.l.Lure.class));
- cards.add(new SetCardInfo("Magus of the Unseen", 82, Rarity.RARE, mage.cards.m.MagusOfTheUnseen.class));
- cards.add(new SetCardInfo("Malachite Talisman", 328, Rarity.UNCOMMON, mage.cards.m.MalachiteTalisman.class));
- cards.add(new SetCardInfo("Marton Stromgald", 199, Rarity.RARE, mage.cards.m.MartonStromgald.class));
- cards.add(new SetCardInfo("Melee", 200, Rarity.UNCOMMON, mage.cards.m.Melee.class));
- cards.add(new SetCardInfo("Melting", 201, Rarity.UNCOMMON, mage.cards.m.Melting.class));
- cards.add(new SetCardInfo("Merieke Ri Berit", 297, Rarity.RARE, mage.cards.m.MeriekeRiBerit.class));
- cards.add(new SetCardInfo("Mesmeric Trance", 83, Rarity.RARE, mage.cards.m.MesmericTrance.class));
- cards.add(new SetCardInfo("Meteor Shower", 202, Rarity.COMMON, mage.cards.m.MeteorShower.class));
- cards.add(new SetCardInfo("Mind Ravel", 147, Rarity.COMMON, mage.cards.m.MindRavel.class));
- cards.add(new SetCardInfo("Mind Warp", 148, Rarity.UNCOMMON, mage.cards.m.MindWarp.class));
- cards.add(new SetCardInfo("Mind Whip", 149, Rarity.RARE, mage.cards.m.MindWhip.class));
- cards.add(new SetCardInfo("Minion of Leshrac", 150, Rarity.RARE, mage.cards.m.MinionOfLeshrac.class));
- cards.add(new SetCardInfo("Minion of Tevesh Szat", 151, Rarity.RARE, mage.cards.m.MinionOfTeveshSzat.class));
- cards.add(new SetCardInfo("Mistfolk", 84, Rarity.COMMON, mage.cards.m.Mistfolk.class));
- cards.add(new SetCardInfo("Mole Worms", 152, Rarity.UNCOMMON, mage.cards.m.MoleWorms.class));
- cards.add(new SetCardInfo("Monsoon", 298, Rarity.RARE, mage.cards.m.Monsoon.class));
- cards.add(new SetCardInfo("Moor Fiend", 153, Rarity.COMMON, mage.cards.m.MoorFiend.class));
- cards.add(new SetCardInfo("Mountain Goat", 203, Rarity.COMMON, mage.cards.m.MountainGoat.class));
- cards.add(new SetCardInfo("Mountain Titan", 299, Rarity.RARE, mage.cards.m.MountainTitan.class));
- cards.add(new SetCardInfo("Mountain", 376, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Mountain", 377, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Mountain", 378, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Mudslide", 204, Rarity.RARE, mage.cards.m.Mudslide.class));
- cards.add(new SetCardInfo("Musician", 85, Rarity.RARE, mage.cards.m.Musician.class));
- cards.add(new SetCardInfo("Mystic Might", 86, Rarity.RARE, mage.cards.m.MysticMight.class));
- cards.add(new SetCardInfo("Mystic Remora", 87, Rarity.COMMON, mage.cards.m.MysticRemora.class));
- cards.add(new SetCardInfo("Nacre Talisman", 329, Rarity.UNCOMMON, mage.cards.n.NacreTalisman.class));
- cards.add(new SetCardInfo("Naked Singularity", 330, Rarity.RARE, mage.cards.n.NakedSingularity.class));
- cards.add(new SetCardInfo("Nature's Lore", 255, Rarity.UNCOMMON, mage.cards.n.NaturesLore.class));
- cards.add(new SetCardInfo("Necropotence", 154, Rarity.RARE, mage.cards.n.Necropotence.class));
- cards.add(new SetCardInfo("Norritt", 155, Rarity.COMMON, mage.cards.n.Norritt.class));
- cards.add(new SetCardInfo("Oath of Lim-Dul", 156, Rarity.RARE, mage.cards.o.OathOfLimDul.class));
- cards.add(new SetCardInfo("Onyx Talisman", 331, Rarity.UNCOMMON, mage.cards.o.OnyxTalisman.class));
- cards.add(new SetCardInfo("Orcish Cannoneers", 205, Rarity.UNCOMMON, mage.cards.o.OrcishCannoneers.class));
- cards.add(new SetCardInfo("Orcish Healer", 208, Rarity.UNCOMMON, mage.cards.o.OrcishHealer.class));
- cards.add(new SetCardInfo("Orcish Librarian", 209, Rarity.RARE, mage.cards.o.OrcishLibrarian.class));
- cards.add(new SetCardInfo("Orcish Lumberjack", 210, Rarity.COMMON, mage.cards.o.OrcishLumberjack.class));
- cards.add(new SetCardInfo("Orcish Squatters", 211, Rarity.RARE, mage.cards.o.OrcishSquatters.class));
- cards.add(new SetCardInfo("Order of the Sacred Torch", 45, Rarity.RARE, mage.cards.o.OrderOfTheSacredTorch.class));
- cards.add(new SetCardInfo("Order of the White Shield", 46, Rarity.UNCOMMON, mage.cards.o.OrderOfTheWhiteShield.class));
- cards.add(new SetCardInfo("Pale Bears", 256, Rarity.RARE, mage.cards.p.PaleBears.class));
- cards.add(new SetCardInfo("Panic", 212, Rarity.COMMON, mage.cards.p.Panic.class));
- cards.add(new SetCardInfo("Pentagram of the Ages", 332, Rarity.RARE, mage.cards.p.PentagramOfTheAges.class));
- cards.add(new SetCardInfo("Pestilence Rats", 157, Rarity.COMMON, mage.cards.p.PestilenceRats.class));
- cards.add(new SetCardInfo("Phantasmal Mount", 88, Rarity.UNCOMMON, mage.cards.p.PhantasmalMount.class));
- cards.add(new SetCardInfo("Pit Trap", 333, Rarity.UNCOMMON, mage.cards.p.PitTrap.class));
- cards.add(new SetCardInfo("Plains", 364, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Plains", 365, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Plains", 366, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Polar Kraken", 89, Rarity.RARE, mage.cards.p.PolarKraken.class));
- cards.add(new SetCardInfo("Portent", 90, Rarity.COMMON, mage.cards.p.Portent.class));
- cards.add(new SetCardInfo("Power Sink", 91, Rarity.COMMON, mage.cards.p.PowerSink.class));
- cards.add(new SetCardInfo("Pox", 158, Rarity.RARE, mage.cards.p.Pox.class));
- cards.add(new SetCardInfo("Prismatic Ward", 47, Rarity.COMMON, mage.cards.p.PrismaticWard.class));
- cards.add(new SetCardInfo("Pygmy Allosaurus", 257, Rarity.RARE, mage.cards.p.PygmyAllosaurus.class));
- cards.add(new SetCardInfo("Pyknite", 258, Rarity.COMMON, mage.cards.p.Pyknite.class));
- cards.add(new SetCardInfo("Pyroblast", 213, Rarity.COMMON, mage.cards.p.Pyroblast.class));
- cards.add(new SetCardInfo("Pyroclasm", 214, Rarity.UNCOMMON, mage.cards.p.Pyroclasm.class));
- cards.add(new SetCardInfo("Rally", 48, Rarity.COMMON, mage.cards.r.Rally.class));
- cards.add(new SetCardInfo("Ray of Command", 92, Rarity.COMMON, mage.cards.r.RayOfCommand.class));
- cards.add(new SetCardInfo("Ray of Erasure", 93, Rarity.COMMON, mage.cards.r.RayOfErasure.class));
- cards.add(new SetCardInfo("Reality Twist", 94, Rarity.RARE, mage.cards.r.RealityTwist.class));
- cards.add(new SetCardInfo("Reclamation", 300, Rarity.RARE, mage.cards.r.Reclamation.class));
- cards.add(new SetCardInfo("Red Scarab", 49, Rarity.UNCOMMON, mage.cards.r.RedScarab.class));
- cards.add(new SetCardInfo("Regeneration", 259, Rarity.COMMON, mage.cards.r.Regeneration.class));
- cards.add(new SetCardInfo("Rime Dryad", 260, Rarity.COMMON, mage.cards.r.RimeDryad.class));
- cards.add(new SetCardInfo("Ritual of Subdual", 261, Rarity.RARE, mage.cards.r.RitualOfSubdual.class));
- cards.add(new SetCardInfo("River Delta", 359, Rarity.RARE, mage.cards.r.RiverDelta.class));
- cards.add(new SetCardInfo("Runed Arch", 334, Rarity.RARE, mage.cards.r.RunedArch.class));
- cards.add(new SetCardInfo("Sabretooth Tiger", 215, Rarity.COMMON, mage.cards.s.SabretoothTiger.class));
- cards.add(new SetCardInfo("Scaled Wurm", 262, Rarity.COMMON, mage.cards.s.ScaledWurm.class));
- cards.add(new SetCardInfo("Sea Spirit", 95, Rarity.UNCOMMON, mage.cards.s.SeaSpirit.class));
- cards.add(new SetCardInfo("Seizures", 159, Rarity.COMMON, mage.cards.s.Seizures.class));
- cards.add(new SetCardInfo("Seraph", 51, Rarity.RARE, mage.cards.s.Seraph.class));
- cards.add(new SetCardInfo("Shambling Strider", 263, Rarity.COMMON, mage.cards.s.ShamblingStrider.class));
- cards.add(new SetCardInfo("Shatter", 216, Rarity.COMMON, mage.cards.s.Shatter.class));
- cards.add(new SetCardInfo("Shield Bearer", 52, Rarity.COMMON, mage.cards.s.ShieldBearer.class));
- cards.add(new SetCardInfo("Shield of the Ages", 335, Rarity.UNCOMMON, mage.cards.s.ShieldOfTheAges.class));
- cards.add(new SetCardInfo("Shyft", 96, Rarity.RARE, mage.cards.s.Shyft.class));
- cards.add(new SetCardInfo("Sibilant Spirit", 97, Rarity.RARE, mage.cards.s.SibilantSpirit.class));
- cards.add(new SetCardInfo("Silver Erne", 98, Rarity.UNCOMMON, mage.cards.s.SilverErne.class));
- cards.add(new SetCardInfo("Skeleton Ship", 301, Rarity.RARE, mage.cards.s.SkeletonShip.class));
- cards.add(new SetCardInfo("Skull Catapult", 336, Rarity.UNCOMMON, mage.cards.s.SkullCatapult.class));
- cards.add(new SetCardInfo("Snow Devil", 100, Rarity.COMMON, mage.cards.s.SnowDevil.class));
- cards.add(new SetCardInfo("Snow Fortress", 337, Rarity.RARE, mage.cards.s.SnowFortress.class));
- cards.add(new SetCardInfo("Snow Hound", 53, Rarity.UNCOMMON, mage.cards.s.SnowHound.class));
- cards.add(new SetCardInfo("Snow-Covered Forest", 383, Rarity.LAND, mage.cards.s.SnowCoveredForest.class));
- cards.add(new SetCardInfo("Snow-Covered Island", 371, Rarity.LAND, mage.cards.s.SnowCoveredIsland.class));
- cards.add(new SetCardInfo("Snow-Covered Mountain", 379, Rarity.LAND, mage.cards.s.SnowCoveredMountain.class));
- cards.add(new SetCardInfo("Snow-Covered Plains", 367, Rarity.LAND, mage.cards.s.SnowCoveredPlains.class));
- cards.add(new SetCardInfo("Snow-Covered Swamp", 372, Rarity.LAND, mage.cards.s.SnowCoveredSwamp.class));
- cards.add(new SetCardInfo("Soldevi Golem", 338, Rarity.RARE, mage.cards.s.SoldeviGolem.class));
- cards.add(new SetCardInfo("Soldevi Machinist", 102, Rarity.UNCOMMON, mage.cards.s.SoldeviMachinist.class));
- cards.add(new SetCardInfo("Soldevi Simulacrum", 339, Rarity.UNCOMMON, mage.cards.s.SoldeviSimulacrum.class));
- cards.add(new SetCardInfo("Songs of the Damned", 160, Rarity.COMMON, mage.cards.s.SongsOfTheDamned.class));
- cards.add(new SetCardInfo("Soul Barrier", 103, Rarity.UNCOMMON, mage.cards.s.SoulBarrier.class));
- cards.add(new SetCardInfo("Soul Burn", 161, Rarity.COMMON, mage.cards.s.SoulBurn.class));
- cards.add(new SetCardInfo("Soul Kiss", 162, Rarity.COMMON, mage.cards.s.SoulKiss.class));
- cards.add(new SetCardInfo("Spoils of Evil", 163, Rarity.RARE, mage.cards.s.SpoilsOfEvil.class));
- cards.add(new SetCardInfo("Staff of the Ages", 340, Rarity.RARE, mage.cards.s.StaffOfTheAges.class));
- cards.add(new SetCardInfo("Stampede", 265, Rarity.RARE, mage.cards.s.Stampede.class));
- cards.add(new SetCardInfo("Stench of Evil", 165, Rarity.UNCOMMON, mage.cards.s.StenchOfEvil.class));
- cards.add(new SetCardInfo("Stone Rain", 217, Rarity.COMMON, mage.cards.s.StoneRain.class));
- cards.add(new SetCardInfo("Stone Spirit", 218, Rarity.UNCOMMON, mage.cards.s.StoneSpirit.class));
- cards.add(new SetCardInfo("Stonehands", 219, Rarity.COMMON, mage.cards.s.Stonehands.class));
- cards.add(new SetCardInfo("Storm Spirit", 303, Rarity.RARE, mage.cards.s.StormSpirit.class));
- cards.add(new SetCardInfo("Stormbind", 304, Rarity.RARE, mage.cards.s.Stormbind.class));
- cards.add(new SetCardInfo("Stromgald Cabal", 166, Rarity.RARE, mage.cards.s.StromgaldCabal.class));
- cards.add(new SetCardInfo("Stunted Growth", 266, Rarity.RARE, mage.cards.s.StuntedGrowth.class));
- cards.add(new SetCardInfo("Sulfurous Springs", 360, Rarity.RARE, mage.cards.s.SulfurousSprings.class));
- cards.add(new SetCardInfo("Sunstone", 341, Rarity.UNCOMMON, mage.cards.s.Sunstone.class));
- cards.add(new SetCardInfo("Swamp", 373, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Swamp", 374, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Swamp", 375, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
- cards.add(new SetCardInfo("Swords to Plowshares", 54, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class));
- cards.add(new SetCardInfo("Tarpan", 267, Rarity.COMMON, mage.cards.t.Tarpan.class));
- cards.add(new SetCardInfo("Thermokarst", 268, Rarity.UNCOMMON, mage.cards.t.Thermokarst.class));
- cards.add(new SetCardInfo("Thoughtleech", 269, Rarity.UNCOMMON, mage.cards.t.Thoughtleech.class));
- cards.add(new SetCardInfo("Thunder Wall", 104, Rarity.UNCOMMON, mage.cards.t.ThunderWall.class));
- cards.add(new SetCardInfo("Timberline Ridge", 361, Rarity.RARE, mage.cards.t.TimberlineRidge.class));
- cards.add(new SetCardInfo("Time Bomb", 342, Rarity.RARE, mage.cards.t.TimeBomb.class));
- cards.add(new SetCardInfo("Tinder Wall", 270, Rarity.COMMON, mage.cards.t.TinderWall.class));
- cards.add(new SetCardInfo("Tor Giant", 220, Rarity.COMMON, mage.cards.t.TorGiant.class));
- cards.add(new SetCardInfo("Total War", 221, Rarity.RARE, mage.cards.t.TotalWar.class));
- cards.add(new SetCardInfo("Touch of Death", 167, Rarity.COMMON, mage.cards.t.TouchOfDeath.class));
- cards.add(new SetCardInfo("Trailblazer", 272, Rarity.RARE, mage.cards.t.Trailblazer.class));
- cards.add(new SetCardInfo("Underground River", 362, Rarity.RARE, mage.cards.u.UndergroundRiver.class));
- cards.add(new SetCardInfo("Updraft", 105, Rarity.UNCOMMON, mage.cards.u.Updraft.class));
- cards.add(new SetCardInfo("Urza's Bauble", 343, Rarity.UNCOMMON, mage.cards.u.UrzasBauble.class));
- cards.add(new SetCardInfo("Veldt", 363, Rarity.RARE, mage.cards.v.Veldt.class));
- cards.add(new SetCardInfo("Venomous Breath", 273, Rarity.UNCOMMON, mage.cards.v.VenomousBreath.class));
- cards.add(new SetCardInfo("Vertigo", 222, Rarity.UNCOMMON, mage.cards.v.Vertigo.class));
- cards.add(new SetCardInfo("Vexing Arcanix", 344, Rarity.RARE, mage.cards.v.VexingArcanix.class));
- cards.add(new SetCardInfo("Vibrating Sphere", 345, Rarity.RARE, mage.cards.v.VibratingSphere.class));
- cards.add(new SetCardInfo("Walking Wall", 346, Rarity.UNCOMMON, mage.cards.w.WalkingWall.class));
- cards.add(new SetCardInfo("Wall of Lava", 223, Rarity.UNCOMMON, mage.cards.w.WallOfLava.class));
- cards.add(new SetCardInfo("Wall of Pine Needles", 274, Rarity.UNCOMMON, mage.cards.w.WallOfPineNeedles.class));
- cards.add(new SetCardInfo("Wall of Shields", 347, Rarity.UNCOMMON, mage.cards.w.WallOfShields.class));
- cards.add(new SetCardInfo("War Chariot", 348, Rarity.UNCOMMON, mage.cards.w.WarChariot.class));
- cards.add(new SetCardInfo("Warning", 55, Rarity.COMMON, mage.cards.w.Warning.class));
- cards.add(new SetCardInfo("Whalebone Glider", 349, Rarity.UNCOMMON, mage.cards.w.WhaleboneGlider.class));
- cards.add(new SetCardInfo("White Scarab", 56, Rarity.UNCOMMON, mage.cards.w.WhiteScarab.class));
- cards.add(new SetCardInfo("Whiteout", 275, Rarity.UNCOMMON, mage.cards.w.Whiteout.class));
- cards.add(new SetCardInfo("Wiitigo", 276, Rarity.RARE, mage.cards.w.Wiitigo.class));
- cards.add(new SetCardInfo("Wild Growth", 277, Rarity.COMMON, mage.cards.w.WildGrowth.class));
- cards.add(new SetCardInfo("Wind Spirit", 106, Rarity.UNCOMMON, mage.cards.w.WindSpirit.class));
- cards.add(new SetCardInfo("Wings of Aesthir", 305, Rarity.UNCOMMON, mage.cards.w.WingsOfAesthir.class));
- cards.add(new SetCardInfo("Withering Wisps", 168, Rarity.UNCOMMON, mage.cards.w.WitheringWisps.class));
- cards.add(new SetCardInfo("Woolly Mammoths", 278, Rarity.COMMON, mage.cards.w.WoollyMammoths.class));
- cards.add(new SetCardInfo("Woolly Spider", 279, Rarity.COMMON, mage.cards.w.WoollySpider.class));
- cards.add(new SetCardInfo("Word of Blasting", 224, Rarity.UNCOMMON, mage.cards.w.WordOfBlasting.class));
- cards.add(new SetCardInfo("Word of Undoing", 108, Rarity.COMMON, mage.cards.w.WordOfUndoing.class));
- cards.add(new SetCardInfo("Wrath of Marit Lage", 109, Rarity.RARE, mage.cards.w.WrathOfMaritLage.class));
- cards.add(new SetCardInfo("Yavimaya Gnats", 280, Rarity.UNCOMMON, mage.cards.y.YavimayaGnats.class));
- cards.add(new SetCardInfo("Zur's Weirding", 110, Rarity.RARE, mage.cards.z.ZursWeirding.class));
- cards.add(new SetCardInfo("Zuran Enchanter", 111, Rarity.COMMON, mage.cards.z.ZuranEnchanter.class));
- cards.add(new SetCardInfo("Zuran Orb", 350, Rarity.UNCOMMON, mage.cards.z.ZuranOrb.class));
- cards.add(new SetCardInfo("Zuran Spellcaster", 112, Rarity.COMMON, mage.cards.z.ZuranSpellcaster.class));
- }
-}
+package mage.sets;
+
+import mage.cards.ExpansionSet;
+import mage.constants.Rarity;
+import mage.constants.SetType;
+
+/**
+ * @author North
+ */
+public final class IceAge extends ExpansionSet {
+
+ private static final IceAge instance = new IceAge();
+
+ public static IceAge getInstance() {
+ return instance;
+ }
+
+ private IceAge() {
+ super("Ice Age", "ICE", ExpansionSet.buildDate(1995, 5, 1), SetType.EXPANSION);
+ this.blockName = "Ice Age";
+ this.hasBoosters = true;
+ this.numBoosterLands = 0;
+ this.numBoosterCommon = 11;
+ this.numBoosterUncommon = 3;
+ this.numBoosterRare = 1;
+ this.ratioBoosterMythic = 0;
+
+ cards.add(new SetCardInfo("Abyssal Specter", 113, Rarity.UNCOMMON, mage.cards.a.AbyssalSpecter.class));
+ cards.add(new SetCardInfo("Adarkar Sentinel", 306, Rarity.UNCOMMON, mage.cards.a.AdarkarSentinel.class));
+ cards.add(new SetCardInfo("Adarkar Wastes", 351, Rarity.RARE, mage.cards.a.AdarkarWastes.class));
+ cards.add(new SetCardInfo("Aegis of the Meek", 307, Rarity.RARE, mage.cards.a.AegisOfTheMeek.class));
+ cards.add(new SetCardInfo("Aggression", 169, Rarity.UNCOMMON, mage.cards.a.Aggression.class));
+ cards.add(new SetCardInfo("Altar of Bone", 281, Rarity.RARE, mage.cards.a.AltarOfBone.class));
+ cards.add(new SetCardInfo("Anarchy", 170, Rarity.UNCOMMON, mage.cards.a.Anarchy.class));
+ cards.add(new SetCardInfo("Arenson's Aura", 3, Rarity.COMMON, mage.cards.a.ArensonsAura.class));
+ cards.add(new SetCardInfo("Armor of Faith", 4, Rarity.COMMON, mage.cards.a.ArmorOfFaith.class));
+ cards.add(new SetCardInfo("Arnjlot's Ascent", 57, Rarity.COMMON, mage.cards.a.ArnjlotsAscent.class));
+ cards.add(new SetCardInfo("Ashen Ghoul", 114, Rarity.UNCOMMON, mage.cards.a.AshenGhoul.class));
+ cards.add(new SetCardInfo("Aurochs", 225, Rarity.COMMON, mage.cards.a.Aurochs.class));
+ cards.add(new SetCardInfo("Avalanche", 171, Rarity.UNCOMMON, mage.cards.a.Avalanche.class));
+ cards.add(new SetCardInfo("Balduvian Barbarians", 172, Rarity.COMMON, mage.cards.b.BalduvianBarbarians.class));
+ cards.add(new SetCardInfo("Balduvian Bears", 226, Rarity.COMMON, mage.cards.b.BalduvianBears.class));
+ cards.add(new SetCardInfo("Balduvian Conjurer", 58, Rarity.UNCOMMON, mage.cards.b.BalduvianConjurer.class));
+ cards.add(new SetCardInfo("Balduvian Hydra", 173, Rarity.RARE, mage.cards.b.BalduvianHydra.class));
+ cards.add(new SetCardInfo("Barbed Sextant", 312, Rarity.COMMON, mage.cards.b.BarbedSextant.class));
+ cards.add(new SetCardInfo("Baton of Morale", 313, Rarity.UNCOMMON, mage.cards.b.BatonOfMorale.class));
+ cards.add(new SetCardInfo("Battle Cry", 5, Rarity.UNCOMMON, mage.cards.b.BattleCry.class));
+ cards.add(new SetCardInfo("Battle Frenzy", 175, Rarity.COMMON, mage.cards.b.BattleFrenzy.class));
+ cards.add(new SetCardInfo("Binding Grasp", 60, Rarity.UNCOMMON, mage.cards.b.BindingGrasp.class));
+ cards.add(new SetCardInfo("Black Scarab", 6, Rarity.UNCOMMON, mage.cards.b.BlackScarab.class));
+ cards.add(new SetCardInfo("Blessed Wine", 7, Rarity.COMMON, mage.cards.b.BlessedWine.class));
+ cards.add(new SetCardInfo("Blinking Spirit", 8, Rarity.RARE, mage.cards.b.BlinkingSpirit.class));
+ cards.add(new SetCardInfo("Blizzard", 227, Rarity.RARE, mage.cards.b.Blizzard.class));
+ cards.add(new SetCardInfo("Blue Scarab", 9, Rarity.UNCOMMON, mage.cards.b.BlueScarab.class));
+ cards.add(new SetCardInfo("Brainstorm", 61, Rarity.COMMON, mage.cards.b.Brainstorm.class));
+ cards.add(new SetCardInfo("Brand of Ill Omen", 177, Rarity.RARE, mage.cards.b.BrandOfIllOmen.class));
+ cards.add(new SetCardInfo("Breath of Dreams", 62, Rarity.UNCOMMON, mage.cards.b.BreathOfDreams.class));
+ cards.add(new SetCardInfo("Brine Shaman", 115, Rarity.COMMON, mage.cards.b.BrineShaman.class));
+ cards.add(new SetCardInfo("Brown Ouphe", 228, Rarity.COMMON, mage.cards.b.BrownOuphe.class));
+ cards.add(new SetCardInfo("Brushland", 352, Rarity.RARE, mage.cards.b.Brushland.class));
+ cards.add(new SetCardInfo("Burnt Offering", 116, Rarity.COMMON, mage.cards.b.BurntOffering.class));
+ cards.add(new SetCardInfo("Call to Arms", 10, Rarity.RARE, mage.cards.c.CallToArms.class));
+ cards.add(new SetCardInfo("Caribou Range", 11, Rarity.RARE, mage.cards.c.CaribouRange.class));
+ cards.add(new SetCardInfo("Celestial Sword", 314, Rarity.RARE, mage.cards.c.CelestialSword.class));
+ cards.add(new SetCardInfo("Centaur Archer", 282, Rarity.UNCOMMON, mage.cards.c.CentaurArcher.class));
+ cards.add(new SetCardInfo("Chaos Lord", 178, Rarity.RARE, mage.cards.c.ChaosLord.class));
+ cards.add(new SetCardInfo("Chaos Moon", 179, Rarity.RARE, mage.cards.c.ChaosMoon.class));
+ cards.add(new SetCardInfo("Chub Toad", 229, Rarity.COMMON, mage.cards.c.ChubToad.class));
+ cards.add(new SetCardInfo("Circle of Protection: Black", 12, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlack.class));
+ cards.add(new SetCardInfo("Circle of Protection: Blue", 13, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlue.class));
+ cards.add(new SetCardInfo("Circle of Protection: Green", 14, Rarity.COMMON, mage.cards.c.CircleOfProtectionGreen.class));
+ cards.add(new SetCardInfo("Circle of Protection: Red", 15, Rarity.COMMON, mage.cards.c.CircleOfProtectionRed.class));
+ cards.add(new SetCardInfo("Circle of Protection: White", 16, Rarity.COMMON, mage.cards.c.CircleOfProtectionWhite.class));
+ cards.add(new SetCardInfo("Clairvoyance", 63, Rarity.COMMON, mage.cards.c.Clairvoyance.class));
+ cards.add(new SetCardInfo("Cloak of Confusion", 117, Rarity.COMMON, mage.cards.c.CloakOfConfusion.class));
+ cards.add(new SetCardInfo("Cold Snap", 17, Rarity.UNCOMMON, mage.cards.c.ColdSnap.class));
+ cards.add(new SetCardInfo("Conquer", 180, Rarity.UNCOMMON, mage.cards.c.Conquer.class));
+ cards.add(new SetCardInfo("Cooperation", 18, Rarity.COMMON, mage.cards.c.Cooperation.class));
+ cards.add(new SetCardInfo("Counterspell", 64, Rarity.COMMON, mage.cards.c.Counterspell.class));
+ cards.add(new SetCardInfo("Crown of the Ages", 315, Rarity.RARE, mage.cards.c.CrownOfTheAges.class));
+ cards.add(new SetCardInfo("Curse of Marit Lage", 181, Rarity.RARE, mage.cards.c.CurseOfMaritLage.class));
+ cards.add(new SetCardInfo("Dance of the Dead", 118, Rarity.UNCOMMON, mage.cards.d.DanceOfTheDead.class));
+ cards.add(new SetCardInfo("Dark Banishing", 119, Rarity.COMMON, mage.cards.d.DarkBanishing.class));
+ cards.add(new SetCardInfo("Dark Ritual", 120, Rarity.COMMON, mage.cards.d.DarkRitual.class));
+ cards.add(new SetCardInfo("Death Ward", 19, Rarity.COMMON, mage.cards.d.DeathWard.class));
+ cards.add(new SetCardInfo("Deflection", 65, Rarity.RARE, mage.cards.d.Deflection.class));
+ cards.add(new SetCardInfo("Demonic Consultation", 121, Rarity.UNCOMMON, mage.cards.d.DemonicConsultation.class));
+ cards.add(new SetCardInfo("Despotic Scepter", 316, Rarity.RARE, mage.cards.d.DespoticScepter.class));
+ cards.add(new SetCardInfo("Diabolic Vision", 284, Rarity.UNCOMMON, mage.cards.d.DiabolicVision.class));
+ cards.add(new SetCardInfo("Dire Wolves", 230, Rarity.COMMON, mage.cards.d.DireWolves.class));
+ cards.add(new SetCardInfo("Disenchant", 20, Rarity.COMMON, mage.cards.d.Disenchant.class));
+ cards.add(new SetCardInfo("Dread Wight", 122, Rarity.RARE, mage.cards.d.DreadWight.class));
+ cards.add(new SetCardInfo("Dreams of the Dead", 66, Rarity.UNCOMMON, mage.cards.d.DreamsOfTheDead.class));
+ cards.add(new SetCardInfo("Drift of the Dead", 123, Rarity.UNCOMMON, mage.cards.d.DriftOfTheDead.class));
+ cards.add(new SetCardInfo("Drought", 21, Rarity.UNCOMMON, mage.cards.d.Drought.class));
+ cards.add(new SetCardInfo("Dwarven Armory", 182, Rarity.RARE, mage.cards.d.DwarvenArmory.class));
+ cards.add(new SetCardInfo("Earthlink", 285, Rarity.RARE, mage.cards.e.Earthlink.class));
+ cards.add(new SetCardInfo("Earthlore", 231, Rarity.COMMON, mage.cards.e.Earthlore.class));
+ cards.add(new SetCardInfo("Elder Druid", 232, Rarity.RARE, mage.cards.e.ElderDruid.class));
+ cards.add(new SetCardInfo("Elemental Augury", 286, Rarity.RARE, mage.cards.e.ElementalAugury.class));
+ cards.add(new SetCardInfo("Elkin Bottle", 317, Rarity.RARE, mage.cards.e.ElkinBottle.class));
+ cards.add(new SetCardInfo("Enduring Renewal", 23, Rarity.RARE, mage.cards.e.EnduringRenewal.class));
+ cards.add(new SetCardInfo("Energy Storm", 24, Rarity.RARE, mage.cards.e.EnergyStorm.class));
+ cards.add(new SetCardInfo("Enervate", 67, Rarity.COMMON, mage.cards.e.Enervate.class));
+ cards.add(new SetCardInfo("Errant Minion", 68, Rarity.COMMON, mage.cards.e.ErrantMinion.class));
+ cards.add(new SetCardInfo("Errantry", 183, Rarity.COMMON, mage.cards.e.Errantry.class));
+ cards.add(new SetCardInfo("Essence Filter", 233, Rarity.COMMON, mage.cards.e.EssenceFilter.class));
+ cards.add(new SetCardInfo("Essence Flare", 69, Rarity.COMMON, mage.cards.e.EssenceFlare.class));
+ cards.add(new SetCardInfo("Fanatical Fever", 234, Rarity.UNCOMMON, mage.cards.f.FanaticalFever.class));
+ cards.add(new SetCardInfo("Fear", 124, Rarity.COMMON, mage.cards.f.Fear.class));
+ cards.add(new SetCardInfo("Fiery Justice", 288, Rarity.RARE, mage.cards.f.FieryJustice.class));
+ cards.add(new SetCardInfo("Fire Covenant", 289, Rarity.UNCOMMON, mage.cards.f.FireCovenant.class));
+ cards.add(new SetCardInfo("Flame Spirit", 184, Rarity.UNCOMMON, mage.cards.f.FlameSpirit.class));
+ cards.add(new SetCardInfo("Flare", 185, Rarity.COMMON, mage.cards.f.Flare.class));
+ cards.add(new SetCardInfo("Flooded Woodlands", 290, Rarity.RARE, mage.cards.f.FloodedWoodlands.class));
+ cards.add(new SetCardInfo("Flow of Maggots", 125, Rarity.RARE, mage.cards.f.FlowOfMaggots.class));
+ cards.add(new SetCardInfo("Folk of the Pines", 235, Rarity.COMMON, mage.cards.f.FolkOfThePines.class));
+ cards.add(new SetCardInfo("Forbidden Lore", 236, Rarity.RARE, mage.cards.f.ForbiddenLore.class));
+ cards.add(new SetCardInfo("Force Void", 70, Rarity.UNCOMMON, mage.cards.f.ForceVoid.class));
+ cards.add(new SetCardInfo("Forest", 380, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Forest", 381, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Forest", 382, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Forgotten Lore", 237, Rarity.UNCOMMON, mage.cards.f.ForgottenLore.class));
+ cards.add(new SetCardInfo("Formation", 25, Rarity.RARE, mage.cards.f.Formation.class));
+ cards.add(new SetCardInfo("Foul Familiar", 126, Rarity.COMMON, mage.cards.f.FoulFamiliar.class));
+ cards.add(new SetCardInfo("Foxfire", 238, Rarity.COMMON, mage.cards.f.Foxfire.class));
+ cards.add(new SetCardInfo("Freyalise Supplicant", 239, Rarity.UNCOMMON, mage.cards.f.FreyaliseSupplicant.class));
+ cards.add(new SetCardInfo("Freyalise's Charm", 240, Rarity.UNCOMMON, mage.cards.f.FreyalisesCharm.class));
+ cards.add(new SetCardInfo("Freyalise's Winds", 241, Rarity.RARE, mage.cards.f.FreyalisesWinds.class));
+ cards.add(new SetCardInfo("Fumarole", 291, Rarity.UNCOMMON, mage.cards.f.Fumarole.class));
+ cards.add(new SetCardInfo("Fylgja", 26, Rarity.COMMON, mage.cards.f.Fylgja.class));
+ cards.add(new SetCardInfo("Fyndhorn Bow", 318, Rarity.UNCOMMON, mage.cards.f.FyndhornBow.class));
+ cards.add(new SetCardInfo("Fyndhorn Brownie", 242, Rarity.COMMON, mage.cards.f.FyndhornBrownie.class));
+ cards.add(new SetCardInfo("Fyndhorn Elder", 243, Rarity.UNCOMMON, mage.cards.f.FyndhornElder.class));
+ cards.add(new SetCardInfo("Fyndhorn Elves", 244, Rarity.COMMON, mage.cards.f.FyndhornElves.class));
+ cards.add(new SetCardInfo("Fyndhorn Pollen", 245, Rarity.RARE, mage.cards.f.FyndhornPollen.class));
+ cards.add(new SetCardInfo("Game of Chaos", 186, Rarity.RARE, mage.cards.g.GameOfChaos.class));
+ cards.add(new SetCardInfo("Gangrenous Zombies", 127, Rarity.COMMON, mage.cards.g.GangrenousZombies.class));
+ cards.add(new SetCardInfo("Gaze of Pain", 128, Rarity.COMMON, mage.cards.g.GazeOfPain.class));
+ cards.add(new SetCardInfo("General Jarkeld", 27, Rarity.RARE, mage.cards.g.GeneralJarkeld.class));
+ cards.add(new SetCardInfo("Giant Growth", 246, Rarity.COMMON, mage.cards.g.GiantGrowth.class));
+ cards.add(new SetCardInfo("Giant Trap Door Spider", 293, Rarity.UNCOMMON, mage.cards.g.GiantTrapDoorSpider.class));
+ cards.add(new SetCardInfo("Glacial Chasm", 353, Rarity.UNCOMMON, mage.cards.g.GlacialChasm.class));
+ cards.add(new SetCardInfo("Glacial Crevasses", 187, Rarity.RARE, mage.cards.g.GlacialCrevasses.class));
+ cards.add(new SetCardInfo("Glacial Wall", 71, Rarity.UNCOMMON, mage.cards.g.GlacialWall.class));
+ cards.add(new SetCardInfo("Glaciers", 294, Rarity.RARE, mage.cards.g.Glaciers.class));
+ cards.add(new SetCardInfo("Goblin Lyre", 319, Rarity.RARE, mage.cards.g.GoblinLyre.class));
+ cards.add(new SetCardInfo("Goblin Mutant", 188, Rarity.UNCOMMON, mage.cards.g.GoblinMutant.class));
+ cards.add(new SetCardInfo("Goblin Snowman", 191, Rarity.UNCOMMON, mage.cards.g.GoblinSnowman.class));
+ cards.add(new SetCardInfo("Gorilla Pack", 247, Rarity.COMMON, mage.cards.g.GorillaPack.class));
+ cards.add(new SetCardInfo("Gravebind", 129, Rarity.RARE, mage.cards.g.Gravebind.class));
+ cards.add(new SetCardInfo("Green Scarab", 28, Rarity.UNCOMMON, mage.cards.g.GreenScarab.class));
+ cards.add(new SetCardInfo("Hallowed Ground", 29, Rarity.UNCOMMON, mage.cards.h.HallowedGround.class));
+ cards.add(new SetCardInfo("Halls of Mist", 354, Rarity.RARE, mage.cards.h.HallsOfMist.class));
+ cards.add(new SetCardInfo("Heal", 30, Rarity.COMMON, mage.cards.h.Heal.class));
+ cards.add(new SetCardInfo("Hecatomb", 130, Rarity.RARE, mage.cards.h.Hecatomb.class));
+ cards.add(new SetCardInfo("Hematite Talisman", 320, Rarity.UNCOMMON, mage.cards.h.HematiteTalisman.class));
+ cards.add(new SetCardInfo("Hoar Shade", 131, Rarity.COMMON, mage.cards.h.HoarShade.class));
+ cards.add(new SetCardInfo("Hot Springs", 248, Rarity.RARE, mage.cards.h.HotSprings.class));
+ cards.add(new SetCardInfo("Howl from Beyond", 132, Rarity.COMMON, mage.cards.h.HowlFromBeyond.class));
+ cards.add(new SetCardInfo("Hurricane", 249, Rarity.UNCOMMON, mage.cards.h.Hurricane.class));
+ cards.add(new SetCardInfo("Hyalopterous Lemure", 133, Rarity.UNCOMMON, mage.cards.h.HyalopterousLemure.class));
+ cards.add(new SetCardInfo("Hydroblast", 72, Rarity.COMMON, mage.cards.h.Hydroblast.class));
+ cards.add(new SetCardInfo("Hymn of Rebirth", 295, Rarity.UNCOMMON, mage.cards.h.HymnOfRebirth.class));
+ cards.add(new SetCardInfo("Ice Cauldron", 321, Rarity.RARE, mage.cards.i.IceCauldron.class));
+ cards.add(new SetCardInfo("Ice Floe", 355, Rarity.UNCOMMON, mage.cards.i.IceFloe.class));
+ cards.add(new SetCardInfo("Iceberg", 73, Rarity.UNCOMMON, mage.cards.i.Iceberg.class));
+ cards.add(new SetCardInfo("Icequake", 134, Rarity.UNCOMMON, mage.cards.i.Icequake.class));
+ cards.add(new SetCardInfo("Icy Manipulator", 322, Rarity.UNCOMMON, mage.cards.i.IcyManipulator.class));
+ cards.add(new SetCardInfo("Icy Prison", 74, Rarity.RARE, mage.cards.i.IcyPrison.class));
+ cards.add(new SetCardInfo("Illusionary Forces", 75, Rarity.COMMON, mage.cards.i.IllusionaryForces.class));
+ cards.add(new SetCardInfo("Illusionary Presence", 76, Rarity.RARE, mage.cards.i.IllusionaryPresence.class));
+ cards.add(new SetCardInfo("Illusionary Terrain", 77, Rarity.UNCOMMON, mage.cards.i.IllusionaryTerrain.class));
+ cards.add(new SetCardInfo("Illusionary Wall", 78, Rarity.COMMON, mage.cards.i.IllusionaryWall.class));
+ cards.add(new SetCardInfo("Illusions of Grandeur", 79, Rarity.RARE, mage.cards.i.IllusionsOfGrandeur.class));
+ cards.add(new SetCardInfo("Imposing Visage", 193, Rarity.COMMON, mage.cards.i.ImposingVisage.class));
+ cards.add(new SetCardInfo("Incinerate", 194, Rarity.COMMON, mage.cards.i.Incinerate.class));
+ cards.add(new SetCardInfo("Infernal Darkness", 135, Rarity.RARE, mage.cards.i.InfernalDarkness.class));
+ cards.add(new SetCardInfo("Infernal Denizen", 136, Rarity.RARE, mage.cards.i.InfernalDenizen.class));
+ cards.add(new SetCardInfo("Infinite Hourglass", 323, Rarity.RARE, mage.cards.i.InfiniteHourglass.class));
+ cards.add(new SetCardInfo("Infuse", 80, Rarity.COMMON, mage.cards.i.Infuse.class));
+ cards.add(new SetCardInfo("Island", 368, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Island", 369, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Island", 370, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Jester's Cap", 324, Rarity.RARE, mage.cards.j.JestersCap.class));
+ cards.add(new SetCardInfo("Jester's Mask", 325, Rarity.RARE, mage.cards.j.JestersMask.class));
+ cards.add(new SetCardInfo("Jeweled Amulet", 326, Rarity.UNCOMMON, mage.cards.j.JeweledAmulet.class));
+ cards.add(new SetCardInfo("Johtull Wurm", 250, Rarity.UNCOMMON, mage.cards.j.JohtullWurm.class));
+ cards.add(new SetCardInfo("Jokulhaups", 195, Rarity.RARE, mage.cards.j.Jokulhaups.class));
+ cards.add(new SetCardInfo("Juniper Order Druid", 251, Rarity.COMMON, mage.cards.j.JuniperOrderDruid.class));
+ cards.add(new SetCardInfo("Justice", 32, Rarity.UNCOMMON, mage.cards.j.Justice.class));
+ cards.add(new SetCardInfo("Karplusan Forest", 356, Rarity.RARE, mage.cards.k.KarplusanForest.class));
+ cards.add(new SetCardInfo("Karplusan Giant", 196, Rarity.UNCOMMON, mage.cards.k.KarplusanGiant.class));
+ cards.add(new SetCardInfo("Karplusan Yeti", 197, Rarity.RARE, mage.cards.k.KarplusanYeti.class));
+ cards.add(new SetCardInfo("Kelsinko Ranger", 33, Rarity.COMMON, mage.cards.k.KelsinkoRanger.class));
+ cards.add(new SetCardInfo("Kjeldoran Dead", 137, Rarity.COMMON, mage.cards.k.KjeldoranDead.class));
+ cards.add(new SetCardInfo("Kjeldoran Frostbeast", 296, Rarity.UNCOMMON, mage.cards.k.KjeldoranFrostbeast.class));
+ cards.add(new SetCardInfo("Kjeldoran Knight", 36, Rarity.RARE, mage.cards.k.KjeldoranKnight.class));
+ cards.add(new SetCardInfo("Kjeldoran Phalanx", 37, Rarity.RARE, mage.cards.k.KjeldoranPhalanx.class));
+ cards.add(new SetCardInfo("Kjeldoran Royal Guard", 38, Rarity.RARE, mage.cards.k.KjeldoranRoyalGuard.class));
+ cards.add(new SetCardInfo("Kjeldoran Skycaptain", 39, Rarity.UNCOMMON, mage.cards.k.KjeldoranSkycaptain.class));
+ cards.add(new SetCardInfo("Kjeldoran Skyknight", 40, Rarity.COMMON, mage.cards.k.KjeldoranSkyknight.class));
+ cards.add(new SetCardInfo("Kjeldoran Warrior", 41, Rarity.COMMON, mage.cards.k.KjeldoranWarrior.class));
+ cards.add(new SetCardInfo("Knight of Stromgald", 138, Rarity.UNCOMMON, mage.cards.k.KnightOfStromgald.class));
+ cards.add(new SetCardInfo("Krovikan Elementalist", 139, Rarity.UNCOMMON, mage.cards.k.KrovikanElementalist.class));
+ cards.add(new SetCardInfo("Krovikan Fetish", 140, Rarity.COMMON, mage.cards.k.KrovikanFetish.class));
+ cards.add(new SetCardInfo("Krovikan Sorcerer", 81, Rarity.COMMON, mage.cards.k.KrovikanSorcerer.class));
+ cards.add(new SetCardInfo("Krovikan Vampire", 141, Rarity.UNCOMMON, mage.cards.k.KrovikanVampire.class));
+ cards.add(new SetCardInfo("Land Cap", 357, Rarity.RARE, mage.cards.l.LandCap.class));
+ cards.add(new SetCardInfo("Lapis Lazuli Talisman", 327, Rarity.UNCOMMON, mage.cards.l.LapisLazuliTalisman.class));
+ cards.add(new SetCardInfo("Lava Tubes", 358, Rarity.RARE, mage.cards.l.LavaTubes.class));
+ cards.add(new SetCardInfo("Legions of Lim-Dul", 142, Rarity.COMMON, mage.cards.l.LegionsOfLimDul.class));
+ cards.add(new SetCardInfo("Leshrac's Rite", 143, Rarity.UNCOMMON, mage.cards.l.LeshracsRite.class));
+ cards.add(new SetCardInfo("Leshrac's Sigil", 144, Rarity.UNCOMMON, mage.cards.l.LeshracsSigil.class));
+ cards.add(new SetCardInfo("Lhurgoyf", 252, Rarity.RARE, mage.cards.l.Lhurgoyf.class));
+ cards.add(new SetCardInfo("Lightning Blow", 42, Rarity.RARE, mage.cards.l.LightningBlow.class));
+ cards.add(new SetCardInfo("Lim-Dul's Cohort", 145, Rarity.COMMON, mage.cards.l.LimDulsCohort.class));
+ cards.add(new SetCardInfo("Lim-Dul's Hex", 146, Rarity.UNCOMMON, mage.cards.l.LimDulsHex.class));
+ cards.add(new SetCardInfo("Lost Order of Jarkeld", 43, Rarity.RARE, mage.cards.l.LostOrderOfJarkeld.class));
+ cards.add(new SetCardInfo("Lure", 253, Rarity.UNCOMMON, mage.cards.l.Lure.class));
+ cards.add(new SetCardInfo("Magus of the Unseen", 82, Rarity.RARE, mage.cards.m.MagusOfTheUnseen.class));
+ cards.add(new SetCardInfo("Malachite Talisman", 328, Rarity.UNCOMMON, mage.cards.m.MalachiteTalisman.class));
+ cards.add(new SetCardInfo("Marton Stromgald", 199, Rarity.RARE, mage.cards.m.MartonStromgald.class));
+ cards.add(new SetCardInfo("Melee", 200, Rarity.UNCOMMON, mage.cards.m.Melee.class));
+ cards.add(new SetCardInfo("Melting", 201, Rarity.UNCOMMON, mage.cards.m.Melting.class));
+ cards.add(new SetCardInfo("Merieke Ri Berit", 297, Rarity.RARE, mage.cards.m.MeriekeRiBerit.class));
+ cards.add(new SetCardInfo("Mesmeric Trance", 83, Rarity.RARE, mage.cards.m.MesmericTrance.class));
+ cards.add(new SetCardInfo("Meteor Shower", 202, Rarity.COMMON, mage.cards.m.MeteorShower.class));
+ cards.add(new SetCardInfo("Mind Ravel", 147, Rarity.COMMON, mage.cards.m.MindRavel.class));
+ cards.add(new SetCardInfo("Mind Warp", 148, Rarity.UNCOMMON, mage.cards.m.MindWarp.class));
+ cards.add(new SetCardInfo("Mind Whip", 149, Rarity.RARE, mage.cards.m.MindWhip.class));
+ cards.add(new SetCardInfo("Minion of Leshrac", 150, Rarity.RARE, mage.cards.m.MinionOfLeshrac.class));
+ cards.add(new SetCardInfo("Minion of Tevesh Szat", 151, Rarity.RARE, mage.cards.m.MinionOfTeveshSzat.class));
+ cards.add(new SetCardInfo("Mistfolk", 84, Rarity.COMMON, mage.cards.m.Mistfolk.class));
+ cards.add(new SetCardInfo("Mole Worms", 152, Rarity.UNCOMMON, mage.cards.m.MoleWorms.class));
+ cards.add(new SetCardInfo("Monsoon", 298, Rarity.RARE, mage.cards.m.Monsoon.class));
+ cards.add(new SetCardInfo("Moor Fiend", 153, Rarity.COMMON, mage.cards.m.MoorFiend.class));
+ cards.add(new SetCardInfo("Mountain Goat", 203, Rarity.COMMON, mage.cards.m.MountainGoat.class));
+ cards.add(new SetCardInfo("Mountain Titan", 299, Rarity.RARE, mage.cards.m.MountainTitan.class));
+ cards.add(new SetCardInfo("Mountain", 376, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Mountain", 377, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Mountain", 378, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Mudslide", 204, Rarity.RARE, mage.cards.m.Mudslide.class));
+ cards.add(new SetCardInfo("Musician", 85, Rarity.RARE, mage.cards.m.Musician.class));
+ cards.add(new SetCardInfo("Mystic Might", 86, Rarity.RARE, mage.cards.m.MysticMight.class));
+ cards.add(new SetCardInfo("Mystic Remora", 87, Rarity.COMMON, mage.cards.m.MysticRemora.class));
+ cards.add(new SetCardInfo("Nacre Talisman", 329, Rarity.UNCOMMON, mage.cards.n.NacreTalisman.class));
+ cards.add(new SetCardInfo("Naked Singularity", 330, Rarity.RARE, mage.cards.n.NakedSingularity.class));
+ cards.add(new SetCardInfo("Nature's Lore", 255, Rarity.UNCOMMON, mage.cards.n.NaturesLore.class));
+ cards.add(new SetCardInfo("Necropotence", 154, Rarity.RARE, mage.cards.n.Necropotence.class));
+ cards.add(new SetCardInfo("Norritt", 155, Rarity.COMMON, mage.cards.n.Norritt.class));
+ cards.add(new SetCardInfo("Oath of Lim-Dul", 156, Rarity.RARE, mage.cards.o.OathOfLimDul.class));
+ cards.add(new SetCardInfo("Onyx Talisman", 331, Rarity.UNCOMMON, mage.cards.o.OnyxTalisman.class));
+ cards.add(new SetCardInfo("Orcish Cannoneers", 205, Rarity.UNCOMMON, mage.cards.o.OrcishCannoneers.class));
+ cards.add(new SetCardInfo("Orcish Healer", 208, Rarity.UNCOMMON, mage.cards.o.OrcishHealer.class));
+ cards.add(new SetCardInfo("Orcish Librarian", 209, Rarity.RARE, mage.cards.o.OrcishLibrarian.class));
+ cards.add(new SetCardInfo("Orcish Lumberjack", 210, Rarity.COMMON, mage.cards.o.OrcishLumberjack.class));
+ cards.add(new SetCardInfo("Orcish Squatters", 211, Rarity.RARE, mage.cards.o.OrcishSquatters.class));
+ cards.add(new SetCardInfo("Order of the Sacred Torch", 45, Rarity.RARE, mage.cards.o.OrderOfTheSacredTorch.class));
+ cards.add(new SetCardInfo("Order of the White Shield", 46, Rarity.UNCOMMON, mage.cards.o.OrderOfTheWhiteShield.class));
+ cards.add(new SetCardInfo("Pale Bears", 256, Rarity.RARE, mage.cards.p.PaleBears.class));
+ cards.add(new SetCardInfo("Panic", 212, Rarity.COMMON, mage.cards.p.Panic.class));
+ cards.add(new SetCardInfo("Pentagram of the Ages", 332, Rarity.RARE, mage.cards.p.PentagramOfTheAges.class));
+ cards.add(new SetCardInfo("Pestilence Rats", 157, Rarity.COMMON, mage.cards.p.PestilenceRats.class));
+ cards.add(new SetCardInfo("Phantasmal Mount", 88, Rarity.UNCOMMON, mage.cards.p.PhantasmalMount.class));
+ cards.add(new SetCardInfo("Pit Trap", 333, Rarity.UNCOMMON, mage.cards.p.PitTrap.class));
+ cards.add(new SetCardInfo("Plains", 364, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Plains", 365, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Plains", 366, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Polar Kraken", 89, Rarity.RARE, mage.cards.p.PolarKraken.class));
+ cards.add(new SetCardInfo("Portent", 90, Rarity.COMMON, mage.cards.p.Portent.class));
+ cards.add(new SetCardInfo("Power Sink", 91, Rarity.COMMON, mage.cards.p.PowerSink.class));
+ cards.add(new SetCardInfo("Pox", 158, Rarity.RARE, mage.cards.p.Pox.class));
+ cards.add(new SetCardInfo("Prismatic Ward", 47, Rarity.COMMON, mage.cards.p.PrismaticWard.class));
+ cards.add(new SetCardInfo("Pygmy Allosaurus", 257, Rarity.RARE, mage.cards.p.PygmyAllosaurus.class));
+ cards.add(new SetCardInfo("Pyknite", 258, Rarity.COMMON, mage.cards.p.Pyknite.class));
+ cards.add(new SetCardInfo("Pyroblast", 213, Rarity.COMMON, mage.cards.p.Pyroblast.class));
+ cards.add(new SetCardInfo("Pyroclasm", 214, Rarity.UNCOMMON, mage.cards.p.Pyroclasm.class));
+ cards.add(new SetCardInfo("Rally", 48, Rarity.COMMON, mage.cards.r.Rally.class));
+ cards.add(new SetCardInfo("Ray of Command", 92, Rarity.COMMON, mage.cards.r.RayOfCommand.class));
+ cards.add(new SetCardInfo("Ray of Erasure", 93, Rarity.COMMON, mage.cards.r.RayOfErasure.class));
+ cards.add(new SetCardInfo("Reality Twist", 94, Rarity.RARE, mage.cards.r.RealityTwist.class));
+ cards.add(new SetCardInfo("Reclamation", 300, Rarity.RARE, mage.cards.r.Reclamation.class));
+ cards.add(new SetCardInfo("Red Scarab", 49, Rarity.UNCOMMON, mage.cards.r.RedScarab.class));
+ cards.add(new SetCardInfo("Regeneration", 259, Rarity.COMMON, mage.cards.r.Regeneration.class));
+ cards.add(new SetCardInfo("Rime Dryad", 260, Rarity.COMMON, mage.cards.r.RimeDryad.class));
+ cards.add(new SetCardInfo("Ritual of Subdual", 261, Rarity.RARE, mage.cards.r.RitualOfSubdual.class));
+ cards.add(new SetCardInfo("River Delta", 359, Rarity.RARE, mage.cards.r.RiverDelta.class));
+ cards.add(new SetCardInfo("Runed Arch", 334, Rarity.RARE, mage.cards.r.RunedArch.class));
+ cards.add(new SetCardInfo("Sabretooth Tiger", 215, Rarity.COMMON, mage.cards.s.SabretoothTiger.class));
+ cards.add(new SetCardInfo("Scaled Wurm", 262, Rarity.COMMON, mage.cards.s.ScaledWurm.class));
+ cards.add(new SetCardInfo("Sea Spirit", 95, Rarity.UNCOMMON, mage.cards.s.SeaSpirit.class));
+ cards.add(new SetCardInfo("Seizures", 159, Rarity.COMMON, mage.cards.s.Seizures.class));
+ cards.add(new SetCardInfo("Seraph", 51, Rarity.RARE, mage.cards.s.Seraph.class));
+ cards.add(new SetCardInfo("Shambling Strider", 263, Rarity.COMMON, mage.cards.s.ShamblingStrider.class));
+ cards.add(new SetCardInfo("Shatter", 216, Rarity.COMMON, mage.cards.s.Shatter.class));
+ cards.add(new SetCardInfo("Shield Bearer", 52, Rarity.COMMON, mage.cards.s.ShieldBearer.class));
+ cards.add(new SetCardInfo("Shield of the Ages", 335, Rarity.UNCOMMON, mage.cards.s.ShieldOfTheAges.class));
+ cards.add(new SetCardInfo("Shyft", 96, Rarity.RARE, mage.cards.s.Shyft.class));
+ cards.add(new SetCardInfo("Sibilant Spirit", 97, Rarity.RARE, mage.cards.s.SibilantSpirit.class));
+ cards.add(new SetCardInfo("Silver Erne", 98, Rarity.UNCOMMON, mage.cards.s.SilverErne.class));
+ cards.add(new SetCardInfo("Skeleton Ship", 301, Rarity.RARE, mage.cards.s.SkeletonShip.class));
+ cards.add(new SetCardInfo("Skull Catapult", 336, Rarity.UNCOMMON, mage.cards.s.SkullCatapult.class));
+ cards.add(new SetCardInfo("Snow Devil", 100, Rarity.COMMON, mage.cards.s.SnowDevil.class));
+ cards.add(new SetCardInfo("Snow Fortress", 337, Rarity.RARE, mage.cards.s.SnowFortress.class));
+ cards.add(new SetCardInfo("Snow Hound", 53, Rarity.UNCOMMON, mage.cards.s.SnowHound.class));
+ cards.add(new SetCardInfo("Snow-Covered Forest", 383, Rarity.LAND, mage.cards.s.SnowCoveredForest.class));
+ cards.add(new SetCardInfo("Snow-Covered Island", 371, Rarity.LAND, mage.cards.s.SnowCoveredIsland.class));
+ cards.add(new SetCardInfo("Snow-Covered Mountain", 379, Rarity.LAND, mage.cards.s.SnowCoveredMountain.class));
+ cards.add(new SetCardInfo("Snow-Covered Plains", 367, Rarity.LAND, mage.cards.s.SnowCoveredPlains.class));
+ cards.add(new SetCardInfo("Snow-Covered Swamp", 372, Rarity.LAND, mage.cards.s.SnowCoveredSwamp.class));
+ cards.add(new SetCardInfo("Soldevi Golem", 338, Rarity.RARE, mage.cards.s.SoldeviGolem.class));
+ cards.add(new SetCardInfo("Soldevi Machinist", 102, Rarity.UNCOMMON, mage.cards.s.SoldeviMachinist.class));
+ cards.add(new SetCardInfo("Soldevi Simulacrum", 339, Rarity.UNCOMMON, mage.cards.s.SoldeviSimulacrum.class));
+ cards.add(new SetCardInfo("Songs of the Damned", 160, Rarity.COMMON, mage.cards.s.SongsOfTheDamned.class));
+ cards.add(new SetCardInfo("Soul Barrier", 103, Rarity.UNCOMMON, mage.cards.s.SoulBarrier.class));
+ cards.add(new SetCardInfo("Soul Burn", 161, Rarity.COMMON, mage.cards.s.SoulBurn.class));
+ cards.add(new SetCardInfo("Soul Kiss", 162, Rarity.COMMON, mage.cards.s.SoulKiss.class));
+ cards.add(new SetCardInfo("Spoils of Evil", 163, Rarity.RARE, mage.cards.s.SpoilsOfEvil.class));
+ cards.add(new SetCardInfo("Staff of the Ages", 340, Rarity.RARE, mage.cards.s.StaffOfTheAges.class));
+ cards.add(new SetCardInfo("Stampede", 265, Rarity.RARE, mage.cards.s.Stampede.class));
+ cards.add(new SetCardInfo("Stench of Evil", 165, Rarity.UNCOMMON, mage.cards.s.StenchOfEvil.class));
+ cards.add(new SetCardInfo("Stone Rain", 217, Rarity.COMMON, mage.cards.s.StoneRain.class));
+ cards.add(new SetCardInfo("Stone Spirit", 218, Rarity.UNCOMMON, mage.cards.s.StoneSpirit.class));
+ cards.add(new SetCardInfo("Stonehands", 219, Rarity.COMMON, mage.cards.s.Stonehands.class));
+ cards.add(new SetCardInfo("Storm Spirit", 303, Rarity.RARE, mage.cards.s.StormSpirit.class));
+ cards.add(new SetCardInfo("Stormbind", 304, Rarity.RARE, mage.cards.s.Stormbind.class));
+ cards.add(new SetCardInfo("Stromgald Cabal", 166, Rarity.RARE, mage.cards.s.StromgaldCabal.class));
+ cards.add(new SetCardInfo("Stunted Growth", 266, Rarity.RARE, mage.cards.s.StuntedGrowth.class));
+ cards.add(new SetCardInfo("Sulfurous Springs", 360, Rarity.RARE, mage.cards.s.SulfurousSprings.class));
+ cards.add(new SetCardInfo("Sunstone", 341, Rarity.UNCOMMON, mage.cards.s.Sunstone.class));
+ cards.add(new SetCardInfo("Swamp", 373, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Swamp", 374, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Swamp", 375, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
+ cards.add(new SetCardInfo("Swords to Plowshares", 54, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class));
+ cards.add(new SetCardInfo("Tarpan", 267, Rarity.COMMON, mage.cards.t.Tarpan.class));
+ cards.add(new SetCardInfo("Thermokarst", 268, Rarity.UNCOMMON, mage.cards.t.Thermokarst.class));
+ cards.add(new SetCardInfo("Thoughtleech", 269, Rarity.UNCOMMON, mage.cards.t.Thoughtleech.class));
+ cards.add(new SetCardInfo("Thunder Wall", 104, Rarity.UNCOMMON, mage.cards.t.ThunderWall.class));
+ cards.add(new SetCardInfo("Timberline Ridge", 361, Rarity.RARE, mage.cards.t.TimberlineRidge.class));
+ cards.add(new SetCardInfo("Time Bomb", 342, Rarity.RARE, mage.cards.t.TimeBomb.class));
+ cards.add(new SetCardInfo("Tinder Wall", 270, Rarity.COMMON, mage.cards.t.TinderWall.class));
+ cards.add(new SetCardInfo("Tor Giant", 220, Rarity.COMMON, mage.cards.t.TorGiant.class));
+ cards.add(new SetCardInfo("Total War", 221, Rarity.RARE, mage.cards.t.TotalWar.class));
+ cards.add(new SetCardInfo("Touch of Death", 167, Rarity.COMMON, mage.cards.t.TouchOfDeath.class));
+ cards.add(new SetCardInfo("Trailblazer", 272, Rarity.RARE, mage.cards.t.Trailblazer.class));
+ cards.add(new SetCardInfo("Underground River", 362, Rarity.RARE, mage.cards.u.UndergroundRiver.class));
+ cards.add(new SetCardInfo("Updraft", 105, Rarity.UNCOMMON, mage.cards.u.Updraft.class));
+ cards.add(new SetCardInfo("Urza's Bauble", 343, Rarity.UNCOMMON, mage.cards.u.UrzasBauble.class));
+ cards.add(new SetCardInfo("Veldt", 363, Rarity.RARE, mage.cards.v.Veldt.class));
+ cards.add(new SetCardInfo("Venomous Breath", 273, Rarity.UNCOMMON, mage.cards.v.VenomousBreath.class));
+ cards.add(new SetCardInfo("Vertigo", 222, Rarity.UNCOMMON, mage.cards.v.Vertigo.class));
+ cards.add(new SetCardInfo("Vexing Arcanix", 344, Rarity.RARE, mage.cards.v.VexingArcanix.class));
+ cards.add(new SetCardInfo("Vibrating Sphere", 345, Rarity.RARE, mage.cards.v.VibratingSphere.class));
+ cards.add(new SetCardInfo("Walking Wall", 346, Rarity.UNCOMMON, mage.cards.w.WalkingWall.class));
+ cards.add(new SetCardInfo("Wall of Lava", 223, Rarity.UNCOMMON, mage.cards.w.WallOfLava.class));
+ cards.add(new SetCardInfo("Wall of Pine Needles", 274, Rarity.UNCOMMON, mage.cards.w.WallOfPineNeedles.class));
+ cards.add(new SetCardInfo("Wall of Shields", 347, Rarity.UNCOMMON, mage.cards.w.WallOfShields.class));
+ cards.add(new SetCardInfo("War Chariot", 348, Rarity.UNCOMMON, mage.cards.w.WarChariot.class));
+ cards.add(new SetCardInfo("Warning", 55, Rarity.COMMON, mage.cards.w.Warning.class));
+ cards.add(new SetCardInfo("Whalebone Glider", 349, Rarity.UNCOMMON, mage.cards.w.WhaleboneGlider.class));
+ cards.add(new SetCardInfo("White Scarab", 56, Rarity.UNCOMMON, mage.cards.w.WhiteScarab.class));
+ cards.add(new SetCardInfo("Whiteout", 275, Rarity.UNCOMMON, mage.cards.w.Whiteout.class));
+ cards.add(new SetCardInfo("Wiitigo", 276, Rarity.RARE, mage.cards.w.Wiitigo.class));
+ cards.add(new SetCardInfo("Wild Growth", 277, Rarity.COMMON, mage.cards.w.WildGrowth.class));
+ cards.add(new SetCardInfo("Wind Spirit", 106, Rarity.UNCOMMON, mage.cards.w.WindSpirit.class));
+ cards.add(new SetCardInfo("Wings of Aesthir", 305, Rarity.UNCOMMON, mage.cards.w.WingsOfAesthir.class));
+ cards.add(new SetCardInfo("Withering Wisps", 168, Rarity.UNCOMMON, mage.cards.w.WitheringWisps.class));
+ cards.add(new SetCardInfo("Woolly Mammoths", 278, Rarity.COMMON, mage.cards.w.WoollyMammoths.class));
+ cards.add(new SetCardInfo("Woolly Spider", 279, Rarity.COMMON, mage.cards.w.WoollySpider.class));
+ cards.add(new SetCardInfo("Word of Blasting", 224, Rarity.UNCOMMON, mage.cards.w.WordOfBlasting.class));
+ cards.add(new SetCardInfo("Word of Undoing", 108, Rarity.COMMON, mage.cards.w.WordOfUndoing.class));
+ cards.add(new SetCardInfo("Wrath of Marit Lage", 109, Rarity.RARE, mage.cards.w.WrathOfMaritLage.class));
+ cards.add(new SetCardInfo("Yavimaya Gnats", 280, Rarity.UNCOMMON, mage.cards.y.YavimayaGnats.class));
+ cards.add(new SetCardInfo("Zur's Weirding", 110, Rarity.RARE, mage.cards.z.ZursWeirding.class));
+ cards.add(new SetCardInfo("Zuran Enchanter", 111, Rarity.COMMON, mage.cards.z.ZuranEnchanter.class));
+ cards.add(new SetCardInfo("Zuran Orb", 350, Rarity.UNCOMMON, mage.cards.z.ZuranOrb.class));
+ cards.add(new SetCardInfo("Zuran Spellcaster", 112, Rarity.COMMON, mage.cards.z.ZuranSpellcaster.class));
+ }
+}
diff --git a/Mage.Sets/src/mage/sets/Weatherlight.java b/Mage.Sets/src/mage/sets/Weatherlight.java
index 23770049ec3..b8be7cb40e9 100644
--- a/Mage.Sets/src/mage/sets/Weatherlight.java
+++ b/Mage.Sets/src/mage/sets/Weatherlight.java
@@ -55,6 +55,7 @@ public final class Weatherlight extends ExpansionSet {
cards.add(new SetCardInfo("Bogardan Firefiend", 91, Rarity.COMMON, mage.cards.b.BogardanFirefiend.class));
cards.add(new SetCardInfo("Boiling Blood", 92, Rarity.COMMON, mage.cards.b.BoilingBlood.class));
cards.add(new SetCardInfo("Bone Dancer", 62, Rarity.RARE, mage.cards.b.BoneDancer.class));
+ cards.add(new SetCardInfo("Bosium Strip", 147, Rarity.RARE, mage.cards.b.BosiumStrip.class));
cards.add(new SetCardInfo("Briar Shield", 121, Rarity.COMMON, mage.cards.b.BriarShield.class));
cards.add(new SetCardInfo("Bubble Matrix", 146, Rarity.RARE, mage.cards.b.BubbleMatrix.class));
cards.add(new SetCardInfo("Buried Alive", 63, Rarity.UNCOMMON, mage.cards.b.BuriedAlive.class));
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/curses/CursesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/curses/CursesTest.java
index fd43fd20614..4d208738027 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/curses/CursesTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/curses/CursesTest.java
@@ -426,7 +426,7 @@ public class CursesTest extends CardTestPlayerBase {
}
/*
- * Reported bug issue #3326 (NOTE test is failing due to bug in code)
+ * Reported bug issue #3326
* When {Witchbane Orb} triggers when entering the field and there IS a curse attached to you, an error message (I sadly skipped) appears and your turn is reset.
This happened to me in a 4-player Commander game with {Curse of the Shallow Graves} on the field.
*/
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/FeatherTheRedeemedTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/FeatherTheRedeemedTest.java
new file mode 100644
index 00000000000..bc353d8bd08
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/FeatherTheRedeemedTest.java
@@ -0,0 +1,121 @@
+package org.mage.test.cards.abilities.other;
+
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneAllEffect;
+import mage.constants.Duration;
+import mage.constants.PhaseStep;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.filter.StaticFilters;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author JayDi85
+ */
+public class FeatherTheRedeemedTest extends CardTestPlayerBase {
+
+ // Feather, the Redeemed {R}{W}{W}
+ /*
+ Whenever you cast an instant or sorcery spell that targets a creature you control, exile that card
+ instead of putting it into your graveyard as it resolves. If you do, return it to your hand at the beginning of the next end step.
+ */
+
+ @Test
+ public void test_ExileSpellWithReturnAtTheEnd() {
+ // cast bolt, put to exile, return to hand
+ addCard(Zone.BATTLEFIELD, playerA, "Feather, the Redeemed");
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 2);
+
+ // cast and put to exile
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
+ checkPermanentCount("turn 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grizzly Bears", 1);
+ checkExileCount("turn 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", 1);
+ checkHandCardCount("turn 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+
+ // return to hand at the next end step
+ checkExileCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+ checkHandCardCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
+
+ setStrictChooseMode(true);
+ setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+ assertAllCommandsUsed();
+ }
+
+ @Test
+ public void test_ExileSpellAndRecastWithReturnAtTheEnd() {
+ // cast bolt, put to exile, cast from exile, put to exile, return to hand
+ addCustomCardWithAbility("cast from exile", playerA, new SimpleStaticAbility(
+ new PlayFromNotOwnHandZoneAllEffect(StaticFilters.FILTER_CARD, Zone.EXILED, false, TargetController.ANY, Duration.WhileOnBattlefield)
+ ));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Feather, the Redeemed");
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 3);
+
+ // cast and put to exile
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ checkPermanentCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 3 - 1);
+ checkExileCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
+ checkHandCardCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+
+ // cast from exile and put to exile again
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ checkPermanentCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 3 - 2);
+ checkExileCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
+ checkHandCardCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+
+ // return to hand at the next end step
+ setChoice(playerA, "At the beginning of the next end step"); // two triggeres from two cast (card's code adds two same effects on each trigger)
+ checkExileCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+ checkHandCardCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
+
+ setStrictChooseMode(true);
+ setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+ assertAllCommandsUsed();
+ }
+
+ @Test
+ public void test_ExileSpellAndRecastWithoutReturn() {
+ // cast bolt, put to exile, cast from exile with different target, put to graveyard, not return
+ addCustomCardWithAbility("cast from exile", playerA, new SimpleStaticAbility(
+ new PlayFromNotOwnHandZoneAllEffect(StaticFilters.FILTER_CARD, Zone.EXILED, false, TargetController.ANY, Duration.WhileOnBattlefield)
+ ));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Feather, the Redeemed");
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 3);
+
+ // cast and put to exile
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ checkPermanentCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 3 - 1);
+ checkExileCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 1);
+ checkHandCardCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+
+ // cast from exile to target player (without trigger) and put to graveyard
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ checkPermanentCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 3 - 1); // no changes
+ checkLife("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerB, 20 - 3);
+ checkExileCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+ checkHandCardCount("turn 1 recast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+
+ // not return to hand at the next end step
+ checkExileCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+ checkHandCardCount("turn 1 after", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", 0);
+
+ setStrictChooseMode(true);
+ setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+ assertAllCommandsUsed();
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/DidNotHaveHexproofTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/DidNotHaveHexproofTest.java
new file mode 100644
index 00000000000..369faa3aecb
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/DidNotHaveHexproofTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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 org.mage.test.cards.asthough;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ *
+ * @author drmDev
+ */
+public class DidNotHaveHexproofTest extends CardTestPlayerBase {
+
+ /*
+ Witchbane Orb (4)
+ When Witchbane Orb enters the battlefield, destroy all Curses attached to you.
+ You have hexproof. (You can't be the target of spells or abilities your opponents control, including Aura spells.)
+ */
+ public static final String wOrb = "Witchbane Orb";
+
+ /*
+ Detection Tower (Land)
+ {T}: Add Colorless.
+ 1, {T}: Until end of turn, your opponents and creatures your opponents control with hexproof can be the targets of spells and abilities you control
+ as though they didn't have hexproof.
+ */
+ public static final String dTower = "Detection Tower";
+
+ @Test
+ public void detectionTowerAllowsTargettingPlayerWithWitchbaneOrb() {
+
+ addCard(Zone.BATTLEFIELD, playerA, dTower);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
+ addCard(Zone.HAND, playerA, "Shock"); // {R} 2 dmg to any target
+ addCard(Zone.BATTLEFIELD, playerB, wOrb);
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}");
+ castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Shock", playerB);
+
+ setStopAt(1, PhaseStep.END_COMBAT);
+ execute();
+
+ assertTappedCount("Mountain", true, 2);
+ assertTapped(dTower, true);
+ assertGraveyardCount(playerA, "Shock", 1);
+ assertLife(playerB, 18);
+ assertAllCommandsUsed();
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java
new file mode 100644
index 00000000000..02d57293aa6
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java
@@ -0,0 +1,66 @@
+package org.mage.test.cards.continuous;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestCommander4Players;
+
+/**
+ * @author JayDi85
+ */
+public class CommandersCastTest extends CardTestCommander4Players {
+
+ // Player order: A -> D -> C -> B
+
+ @Test
+ public void test_CastToBattlefieldOneTime() {
+ addCard(Zone.COMMAND, playerA, "Balduvian Bears", 1); // {1}{G}, 2/2, commander
+ addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
+
+ showCommand("commanders", 1, PhaseStep.PRECOMBAT_MAIN, playerA);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears");
+
+ setStopAt(1, PhaseStep.END_TURN);
+ setStrictChooseMode(true);
+ execute();
+ assertAllCommandsUsed();
+
+ assertCommandZoneCount(playerA, "Balduvian Bears", 0);
+ assertPermanentCount(playerA, "Balduvian Bears", 1);
+ }
+
+ @Test
+ public void test_CastToBattlefieldTwoTimes() {
+ // Player order: A -> D -> C -> B
+ addCard(Zone.COMMAND, playerA, "Balduvian Bears", 1); // {1}{G}, 2/2, commander
+ addCard(Zone.BATTLEFIELD, playerA, "Forest", 6); // 2 + 4
+ //
+ addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
+ addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
+
+ // cast 1
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears");
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ checkPermanentCount("after cast 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1);
+
+ // destroy commander
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Balduvian Bears");
+ setChoice(playerA, "Yes"); // put to command zone again
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ checkPermanentCount("after destroy", 1, PhaseStep.PRECOMBAT_MAIN, playerB, playerA, "Balduvian Bears", 0);
+
+ // cast 2
+ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears");
+ waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
+ checkPermanentCount("after cast 2", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears", 1);
+
+ setStopAt(1, PhaseStep.END_TURN);
+ setStrictChooseMode(true);
+ execute();
+ assertAllCommandsUsed();
+
+ assertCommandZoneCount(playerA, "Balduvian Bears", 0);
+ assertPermanentCount(playerA, "Balduvian Bears", 1);
+ assertGraveyardCount(playerB, "Lightning Bolt", 1);
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ConditionalCostModificationTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ConditionalCostModificationTest.java
new file mode 100644
index 00000000000..8dbe972ea37
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ConditionalCostModificationTest.java
@@ -0,0 +1,139 @@
+package org.mage.test.cards.continuous;
+
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.MyTurnCondition;
+import mage.abilities.condition.common.NotMyTurnCondition;
+import mage.abilities.decorator.ConditionalCostModificationEffect;
+import mage.abilities.effects.common.cost.AbilitiesCostReductionControllerEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.keyword.EquipAbility;
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author JayDi85
+ */
+public class ConditionalCostModificationTest extends CardTestPlayerBase {
+
+ // Dagger of the Worthy {2}
+ // Equipped creature gets +2/+0 and has afflict 1.
+ // Equip {2}
+
+ @Test
+ public void test_NoModification() {
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Dagger of the Worthy", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Balduvian Bears");
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertTappedCount("Mountain", true, 2);
+ assertTappedCount("Mountain", false, 0);
+ }
+
+ @Test
+ public void test_ModificationNormal() {
+ addCustomCardWithAbility("mod", playerA, new SimpleStaticAbility(new AbilitiesCostReductionControllerEffect(EquipAbility.class, "equip")));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Dagger of the Worthy", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Balduvian Bears");
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertTappedCount("Mountain", true, 1);
+ assertTappedCount("Mountain", false, 1);
+ }
+
+ @Test
+ public void test_ModificationConditionalActive() {
+ addCustomCardWithAbility("mod", playerA, new SimpleStaticAbility(
+ new ConditionalCostModificationEffect(
+ new AbilitiesCostReductionControllerEffect(EquipAbility.class, "equip"),
+ MyTurnCondition.instance,
+ ""
+ )
+ ));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Dagger of the Worthy", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Balduvian Bears");
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertTappedCount("Mountain", true, 1);
+ assertTappedCount("Mountain", false, 1);
+ }
+
+ @Test
+ public void test_ModificationConditionalNotActive() {
+ addCustomCardWithAbility("mod", playerA, new SimpleStaticAbility(
+ new ConditionalCostModificationEffect(
+ new AbilitiesCostReductionControllerEffect(EquipAbility.class, "equip"),
+ NotMyTurnCondition.instance,
+ ""
+ )
+ ));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Dagger of the Worthy", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Balduvian Bears");
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertTappedCount("Mountain", true, 2);
+ assertTappedCount("Mountain", false, 0);
+ }
+
+ @Test
+ public void test_ModificationConditionalNotActiveWithOtherEffect() {
+ addCustomCardWithAbility("mod", playerA, new SimpleStaticAbility(
+ new ConditionalCostModificationEffect(
+ new AbilitiesCostReductionControllerEffect(EquipAbility.class, "equip"),
+ NotMyTurnCondition.instance,
+ new SpellsCostIncreasementAllEffect(1),
+ ""
+ )
+ ));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Dagger of the Worthy", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Balduvian Bears"); // no mod, 2 cost
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); // +1 for spell, 2 cost
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertTappedCount("Mountain", true, 4);
+ assertTappedCount("Mountain", false, 0);
+ assertLife(playerB, 20 - 3);
+ }
+
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ConditionalPreventionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ConditionalPreventionTest.java
new file mode 100644
index 00000000000..42c8b0bb6f7
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/ConditionalPreventionTest.java
@@ -0,0 +1,137 @@
+package org.mage.test.cards.continuous;
+
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.MyTurnCondition;
+import mage.abilities.condition.common.NotMyTurnCondition;
+import mage.abilities.decorator.ConditionalPreventionEffect;
+import mage.abilities.effects.common.PreventAllDamageToAllEffect;
+import mage.abilities.effects.common.PreventAllDamageToPlayersEffect;
+import mage.constants.Duration;
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import mage.filter.StaticFilters;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author JayDi85
+ */
+public class ConditionalPreventionTest extends CardTestPlayerBase {
+
+ // conditional effects go to layered, but there are prevention effects list too
+
+ @Test
+ public void test_NotPreventDamage() {
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears");
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertPermanentCount(playerA, "Balduvian Bears", 0);
+ assertHandCount(playerA, "Lightning Bolt", 0);
+ }
+
+ @Test
+ public void test_PreventDamageNormal() {
+ addCustomCardWithAbility("prevent", playerA, new SimpleStaticAbility(new PreventAllDamageToAllEffect(Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT)));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears");
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertPermanentCount(playerA, "Balduvian Bears", 1);
+ assertHandCount(playerA, "Lightning Bolt", 0);
+ }
+
+ @Test
+ public void test_PreventDamageConditionalActive() {
+ addCustomCardWithAbility("prevent", playerA, new SimpleStaticAbility(
+ new ConditionalPreventionEffect(
+ new PreventAllDamageToAllEffect(Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT),
+ MyTurnCondition.instance,
+ ""
+ )
+ ));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears");
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertPermanentCount(playerA, "Balduvian Bears", 1);
+ assertHandCount(playerA, "Lightning Bolt", 0);
+ }
+
+ @Test
+ public void test_PreventDamageConditionalNotActive() {
+ addCustomCardWithAbility("prevent", playerA, new SimpleStaticAbility(
+ new ConditionalPreventionEffect(
+ new PreventAllDamageToAllEffect(Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT),
+ NotMyTurnCondition.instance,
+ ""
+ )
+ ));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears");
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertPermanentCount(playerA, "Balduvian Bears", 0);
+ assertHandCount(playerA, "Lightning Bolt", 0);
+ }
+
+ @Test
+ public void test_PreventDamageConditionalNotActiveWithOtherEffect() {
+ addCustomCardWithAbility("prevent", playerA, new SimpleStaticAbility(
+ new ConditionalPreventionEffect(
+ new PreventAllDamageToAllEffect(Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT),
+ new PreventAllDamageToPlayersEffect(Duration.WhileOnBattlefield, false),
+ NotMyTurnCondition.instance,
+ ""
+ )
+ ));
+
+ addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Balduvian Bears"); // will prevent
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerA); // will not prevent
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertPermanentCount(playerA, "Balduvian Bears", 0); // not prevented, dies
+ assertLife(playerA, 20); // prevented, no damage
+ assertHandCount(playerA, "Lightning Bolt", 0);
+ }
+
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GideonBlackbladeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GideonBlackbladeTest.java
new file mode 100644
index 00000000000..9f1baf27a7f
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GideonBlackbladeTest.java
@@ -0,0 +1,39 @@
+package org.mage.test.cards.continuous;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import mage.counters.CounterType;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author JayDi85
+ */
+public class GideonBlackbladeTest extends CardTestPlayerBase {
+
+ // Gideon Blackblade L4
+ // As long as it's your turn, Gideon Blackblade is a 4/4 Human Soldier creature with indestructible that's still a planeswalker.
+ // Prevent all damage that would be dealt to Gideon Blackblade during your turn.
+
+ @Test
+ public void test_PreventDamageToGideonOnYourTurn() {
+ addCard(Zone.BATTLEFIELD, playerA, "Gideon Blackblade");
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
+
+ checkPT("turn 1 before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gideon Blackblade", 4, 4);
+ castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Lightning Bolt", "Gideon Blackblade");
+ checkPT("turn 1 after", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Gideon Blackblade", 4, 4);
+ checkPermanentCounters("turn 1 after", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Gideon Blackblade", CounterType.LOYALTY, 4);
+
+ checkPT("turn 2 before", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Gideon Blackblade", 0, 0);
+ castSpell(2, PhaseStep.BEGIN_COMBAT, playerA, "Lightning Bolt", "Gideon Blackblade");
+ checkPT("turn 2 after", 2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Gideon Blackblade", 0, 0);
+ checkPermanentCounters("turn 2 after", 2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Gideon Blackblade", CounterType.LOYALTY, 4 - 3);
+
+ setStrictChooseMode(true);
+ setStopAt(2, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MartyrsOfKorlisTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MartyrsOfKorlisTest.java
new file mode 100644
index 00000000000..6cb3214d4fb
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MartyrsOfKorlisTest.java
@@ -0,0 +1,42 @@
+package org.mage.test.cards.continuous;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author JayDi85
+ */
+public class MartyrsOfKorlisTest extends CardTestPlayerBase {
+
+ // Martyrs of Korlis 1/6
+ // As long as Martyrs of Korlis is untapped, all damage that would be dealt to you by artifacts is dealt to Martyrs of Korlis instead.
+
+ @Test
+ public void test_PreventDamageToGideonOnYourTurn() {
+ addCard(Zone.BATTLEFIELD, playerB, "Martyrs of Korlis");
+ addCard(Zone.BATTLEFIELD, playerA, "Alloy Myr"); // 2/2
+
+ // with redirect
+ checkDamage("turn 1 before", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Martyrs of Korlis", 0);
+ checkLife("turn 1 before", 1, PhaseStep.PRECOMBAT_MAIN, playerB, 20);
+ attack(1, playerA, "Alloy Myr", playerB);
+ checkDamage("turn 1 after", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Martyrs of Korlis", 2);
+ checkLife("turn 1 after", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, 20);
+
+ attack(2, playerB, "Martyrs of Korlis", playerA);
+
+ // without redirect
+ checkDamage("turn 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerB, "Martyrs of Korlis", 0);
+ checkLife("turn 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerB, 20);
+ attack(3, playerA, "Alloy Myr", playerB);
+ checkDamage("turn 3 after", 3, PhaseStep.POSTCOMBAT_MAIN, playerB, "Martyrs of Korlis", 0);
+ checkLife("turn 3 after", 3, PhaseStep.POSTCOMBAT_MAIN, playerB, 20 - 2);
+
+ setStrictChooseMode(true);
+ setStopAt(3, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java
index 1d428a30a08..173bb38a70d 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java
@@ -205,7 +205,7 @@ public class DoublingSeasonTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Doubling Season");
- activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA,"+1: Draw a card, then discard a card at random.");
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Draw a card, then discard a card at random.");
setStopAt(1, PhaseStep.END_TURN);
execute();
@@ -216,4 +216,38 @@ public class DoublingSeasonTest extends CardTestPlayerBase {
//Should not be doubled
assertCounterCount("Tibalt, the Fiend-Blooded", CounterType.LOYALTY, 3);
}
+
+ /**
+ * +1 cost is not affected by double, but replace event like Pir, Imaginative Rascal will be affected
+ * https://github.com/magefree/mage/issues/5802
+ */
+ @Test
+ public void testPlaneswalkerWithoutReplacementEffect() {
+ //addCard(Zone.BATTLEFIELD, playerA, "Pir, Imaginative Rascal");
+ addCard(Zone.BATTLEFIELD, playerA, "Chandra, Fire Artisan");
+ addCard(Zone.BATTLEFIELD, playerA, "Doubling Season");
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1");
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertCounterCount(playerA, "Chandra, Fire Artisan", CounterType.LOYALTY, 4 + 1);
+ }
+
+ @Test
+ public void testPlaneswalkerWithReplacementEffect() {
+ addCard(Zone.BATTLEFIELD, playerA, "Chandra, Fire Artisan");
+ addCard(Zone.BATTLEFIELD, playerA, "Doubling Season"); // x2 counters
+ addCard(Zone.BATTLEFIELD, playerA, "Pir, Imaginative Rascal"); // +1 counter
+
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1");
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertCounterCount(playerA, "Chandra, Fire Artisan", CounterType.LOYALTY, 4 + (1 + 1) * 2);
+ }
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/requirement/BlockRequirementTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/requirement/BlockRequirementTest.java
index 85bb3f87a38..d7a8819c87d 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/requirement/BlockRequirementTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/requirement/BlockRequirementTest.java
@@ -225,4 +225,77 @@ public class BlockRequirementTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Dimensional Infiltrator", 1);
assertGraveyardCount(playerB, "Llanowar Elves", 1);
}
+
+ /*
+ Reported bug: Challenger Troll on field not enforcing block restrictions
+ */
+ @Test
+ public void testChallengerTrollTryBlockWithMany() {
+ /*
+ Challenger Troll {4}{G} - 6/5
+ Creature — Troll
+ Each creature you control with power 4 or greater can’t be blocked by more than one creature.
+ */
+ String cTroll = "Challenger Troll";
+
+ String bSable = "Bronze Sable"; // {2} 2/1
+ String hGiant = "Hill Giant"; // {3}{R} 3/3
+
+ addCard(Zone.BATTLEFIELD, playerA, cTroll);
+ addCard(Zone.BATTLEFIELD, playerB, bSable);
+ addCard(Zone.BATTLEFIELD, playerB, hGiant);
+
+ attack(1, playerA, cTroll);
+
+ // only 1 should be able to block it since Troll >=4 power block restriction
+ block(1, playerB, bSable, cTroll);
+ block(1, playerB, hGiant, cTroll);
+
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+
+ try {
+ execute();
+ fail("Expected exception not thrown");
+ } catch (UnsupportedOperationException e) {
+ assertEquals("Challenger Troll is blocked by 2 creature(s). It can only be blocked by 1 or less.", e.getMessage());
+ }
+ }
+
+ /*
+ Reported bug: Challenger Troll on field not enforcing block restrictions
+ */
+ @Test
+ public void testChallengerTrollAndOtherFourPowerCreaturesBlocks() {
+ /*
+ Challenger Troll {4}{G} - 6/5
+ Creature — Troll
+ Each creature you control with power 4 or greater can’t be blocked by more than one creature.
+ */
+ String cTroll = "Challenger Troll";
+ String bHulk = "Bloom Hulk"; // {3}{G} 4/4 ETB: proliferate
+
+ String bSable = "Bronze Sable"; // {2} 2/1
+ String hGiant = "Hill Giant"; // {3}{R} 3/3
+
+ addCard(Zone.BATTLEFIELD, playerA, cTroll);
+ addCard(Zone.BATTLEFIELD, playerA, bHulk);
+ addCard(Zone.BATTLEFIELD, playerB, bSable);
+ addCard(Zone.BATTLEFIELD, playerB, hGiant);
+
+ attack(1, playerA, cTroll);
+ attack(1, playerA, bHulk);
+
+ // only 1 should be able to block Bloom Hulk since >=4 power and Troll on field
+ block(1, playerB, bSable, bHulk);
+ block(1, playerB, hGiant, bHulk);
+
+ setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
+
+ try {
+ execute();
+ fail("Expected exception not thrown");
+ } catch (UnsupportedOperationException e) {
+ assertEquals("Bloom Hulk is blocked by 2 creature(s). It can only be blocked by 1 or less.", e.getMessage());
+ }
+ }
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/war/KioraTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/war/KioraTest.java
new file mode 100644
index 00000000000..18ba5479c25
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/war/KioraTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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 org.mage.test.cards.single.war;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import mage.counters.CounterType;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author escplan9
+ */
+public class KioraTest extends CardTestPlayerBase {
+
+ /*
+ {2} {U/G}
+ 7 loyalty
+ Whenever a creature with power 4 or greater enters the battlefield, draw a card.
+ [-1]: Untap target permanent.
+ */
+ public final String kiora = "Kiora, Behemoth Beckoner";
+
+
+ @Test
+ public void kioraUntapLand() {
+
+ addCard(Zone.BATTLEFIELD, playerA, kiora);
+ addCard(Zone.BATTLEFIELD, playerA, "Bronze Sable"); // {2} 2/1
+ addCard(Zone.BATTLEFIELD, playerA, "Forest");
+ addCard(Zone.HAND, playerA, "Giant Growth");
+
+ // cast a spell to tap the only land
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Giant Growth", "Bronze Sable");
+
+ // untap that only land
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-1: Untap target permanent", "Forest");
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertGraveyardCount(playerA, "Giant Growth", 1);
+ assertHandCount(playerA, 0);
+ assertPowerToughness(playerA, "Bronze Sable", 5, 4); // giant growthed 2/1 + 3/3 = 5/4
+ assertCounterCount(playerA, kiora, CounterType.LOYALTY, 6);
+ assertTapped("Forest", false); // Kiora's untap
+ }
+}
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/mulligan/MulliganTestBase.java b/Mage.Tests/src/test/java/org/mage/test/mulligan/MulliganTestBase.java
index 711d9792b7b..7f6dd82569e 100644
--- a/Mage.Tests/src/test/java/org/mage/test/mulligan/MulliganTestBase.java
+++ b/Mage.Tests/src/test/java/org/mage/test/mulligan/MulliganTestBase.java
@@ -1,41 +1,21 @@
-
package org.mage.test.mulligan;
-import mage.MageItem;
-import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.Modes;
-import mage.abilities.TriggeredAbility;
-import mage.abilities.costs.VariableCost;
-import mage.abilities.costs.mana.ManaCost;
-import mage.cards.Card;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
import mage.cards.basiclands.Forest;
import mage.cards.decks.Deck;
-import mage.choices.Choice;
-import mage.constants.Outcome;
import mage.constants.RangeOfInfluence;
import mage.game.Game;
import mage.game.GameOptions;
import mage.game.TwoPlayerDuel;
-import mage.game.combat.CombatGroup;
-import mage.game.draft.Draft;
-import mage.game.match.Match;
import mage.game.mulligan.Mulligan;
import mage.game.mulligan.MulliganType;
-import mage.game.permanent.Permanent;
-import mage.game.tournament.Tournament;
-import mage.players.Player;
-import mage.players.PlayerImpl;
-import mage.target.Target;
-import mage.target.TargetAmount;
-import mage.target.TargetCard;
-import mage.target.TargetPlayer;
+import mage.players.StubPlayer;
import org.apache.log4j.Logger;
-import java.io.Serializable;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
import java.util.stream.Stream;
import static com.google.common.base.Preconditions.checkArgument;
@@ -43,7 +23,6 @@ import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.getOnlyElement;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableSet;
-import static java.util.stream.Collectors.toList;
import static mage.constants.MultiplayerAttackOption.LEFT;
import static mage.constants.RangeOfInfluence.ONE;
import static mage.constants.Rarity.LAND;
@@ -167,7 +146,8 @@ public class MulliganTestBase {
return deck;
}
- interface Step {}
+ interface Step {
+ }
interface MulliganStep extends Step {
boolean mulligan();
@@ -242,192 +222,4 @@ public class MulliganTestBase {
}
- static class StubPlayer extends PlayerImpl implements Player {
-
- public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
- if (target instanceof TargetPlayer) {
- for (Player player : game.getPlayers().values()) {
- if (player.getId().equals(getId()) && target.canTarget(getId(), game)) {
- target.add(player.getId(), game);
- return true;
- }
- }
- }
- return false;
- }
-
- public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) {
- cards.getCards(game).stream().map(MageItem::getId).forEach(cardId -> target.add(cardId, game));
- return true;
- }
-
- @Override
- public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) {
- if ("cards to PUT on the BOTTOM of your library (Discard for Mulligan)".equals(target.getFilter().getMessage())) {
- chooseDiscardBottom(game, target.getMinNumberOfTargets(), cards.getCards(game)
- .stream().map(MageItem::getId).collect(toList())).forEach(cardId -> target.add(cardId, game));
- } else {
- UUID cardId = getOnlyElement(cards.getCards(game)).getId();
- if (chooseScry(game, cardId)) {
- target.add(cardId, game);
- return true;
- }
- }
- return false;
- }
-
- public List chooseDiscardBottom(Game game, int count, List cardIds) {
- return cardIds.subList(0, count);
- }
-
- public boolean chooseScry(Game game, UUID cardId) {
- return false;
- }
-
- @Override
- public void shuffleLibrary(Ability source, Game game) {
-
- }
-
- public StubPlayer(String name, RangeOfInfluence range) {
- super(name, range);
- }
-
- @Override
- public void abort() {
-
- }
-
- @Override
- public void skip() {
-
- }
-
- @Override
- public Player copy() {
- return null;
- }
-
- @Override
- public boolean priority(Game game) {
- return false;
- }
-
- @Override
- public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map options) {
- return false;
- }
-
- @Override
- public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
- return false;
- }
-
- @Override
- public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
- return false;
- }
-
- @Override
- public boolean chooseMulligan(Game game) {
- return false;
- }
-
- @Override
- public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) {
- return false;
- }
-
- @Override
- public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) {
- return false;
- }
-
- @Override
- public boolean choose(Outcome outcome, Choice choice, Game game) {
- return false;
- }
-
- @Override
- public boolean choosePile(Outcome outcome, String message, List extends Card> pile1, List extends Card> pile2, Game game) {
- return false;
- }
-
- @Override
- public boolean playMana(Ability ability, ManaCost unpaid, String promptText, Game game) {
- return false;
- }
-
- @Override
- public int announceXMana(int min, int max, String message, Game game, Ability ability) {
- return 0;
- }
-
- @Override
- public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost) {
- return 0;
- }
-
- @Override
- public int chooseReplacementEffect(Map abilityMap, Game game) {
- return 0;
- }
-
- @Override
- public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) {
- return null;
- }
-
- @Override
- public Mode chooseMode(Modes modes, Ability source, Game game) {
- return null;
- }
-
- @Override
- public void selectAttackers(Game game, UUID attackingPlayerId) {
-
- }
-
- @Override
- public void selectBlockers(Game game, UUID defendingPlayerId) {
-
- }
-
- @Override
- public UUID chooseAttackerOrder(List attacker, Game game) {
- return null;
- }
-
- @Override
- public UUID chooseBlockerOrder(List blockers, CombatGroup combatGroup, List blockerOrder, Game game) {
- return null;
- }
-
- @Override
- public void assignDamage(int damage, List targets, String singleTargetName, UUID sourceId, Game game) {
-
- }
-
- @Override
- public int getAmount(int min, int max, String message, Game game) {
- return 0;
- }
-
- @Override
- public void sideboard(Match match, Deck deck) {
-
- }
-
- @Override
- public void construct(Tournament tournament, Deck deck) {
-
- }
-
- @Override
- public void pickCard(List cards, Deck deck, Draft draft) {
-
- }
-
- }
-
}
\ No newline at end of file
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 85fd011dc02..e0e3b0006b3 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
@@ -15,6 +15,7 @@ import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.abilities.mana.ManaOptions;
import mage.cards.Card;
import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.cards.decks.Deck;
import mage.choices.Choice;
import mage.constants.*;
@@ -619,6 +620,13 @@ public class TestPlayer implements Player {
wasProccessed = true;
}
+ // check damage: card name, damage
+ if (params[0].equals(CHECK_COMMAND_DAMAGE) && params.length == 3) {
+ assertDamage(action, game, computerPlayer, params[1], Integer.parseInt(params[2]));
+ actions.remove(action);
+ wasProccessed = true;
+ }
+
// check life: life
if (params[0].equals(CHECK_COMMAND_LIFE) && params.length == 2) {
assertLife(action, game, computerPlayer, Integer.parseInt(params[1]));
@@ -739,6 +747,16 @@ public class TestPlayer implements Player {
wasProccessed = true;
}
+ // show command
+ if (params[0].equals(SHOW_COMMAND_COMMAND) && params.length == 1) {
+ printStart(action.getActionName());
+ CardsImpl cards = new CardsImpl(computerPlayer.getCommandersIds());
+ printCards(cards.getCards(game));
+ printEnd();
+ actions.remove(action);
+ wasProccessed = true;
+ }
+
// show battlefield
if (params[0].equals(SHOW_COMMAND_BATTLEFIELD) && params.length == 1) {
printStart(action.getActionName());
@@ -930,6 +948,12 @@ public class TestPlayer implements Player {
Toughness, perm.getToughness().getValue());
}
+ private void assertDamage(PlayerAction action, Game game, Player player, String permanentName, int damage) {
+ Permanent perm = findPermanentWithAssert(action, game, player, permanentName);
+
+ Assert.assertEquals(action.getActionName() + " - permanent " + permanentName + " have wrong damage: " + perm.getDamage() + " <> " + damage, damage, perm.getDamage());
+ }
+
private void assertLife(PlayerAction action, Game game, Player player, int Life) {
Assert.assertEquals(action.getActionName() + " - " + player.getName() + " have wrong life: " + player.getLife() + " <> " + Life,
Life, player.getLife());
@@ -1393,11 +1417,13 @@ public class TestPlayer implements Player {
}
if (!choices.isEmpty()) {
for (String choice : choices) {
- for (int index = 0; index < rEffects.size(); index++) {
- if (choice.equals(rEffects.get(Integer.toString(index)))) {
+ int index = 0;
+ for (Map.Entry entry : rEffects.entrySet()) {
+ if (entry.getValue().startsWith(choice)) {
choices.remove(choice);
return index;
}
+ index++;
}
}
// TODO: enable fail checks and fix tests
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander4Players.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander4Players.java
new file mode 100644
index 00000000000..a122945927a
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander4Players.java
@@ -0,0 +1,28 @@
+package org.mage.test.serverside.base;
+
+import mage.constants.MultiplayerAttackOption;
+import mage.constants.RangeOfInfluence;
+import mage.game.CommanderFreeForAll;
+import mage.game.Game;
+import mage.game.GameException;
+import mage.game.mulligan.VancouverMulligan;
+import org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl;
+
+import java.io.FileNotFoundException;
+
+/**
+ * @author JayDi85
+ */
+public abstract class CardTestCommander4Players extends CardTestPlayerAPIImpl {
+
+ @Override
+ protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException {
+ Game game = new CommanderFreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, new VancouverMulligan(0), 20);
+ // Player order: A -> D -> C -> B
+ playerA = createPlayer(game, playerA, "PlayerA");
+ playerB = createPlayer(game, playerB, "PlayerB");
+ playerC = createPlayer(game, playerC, "PlayerC");
+ playerD = createPlayer(game, playerD, "PlayerD");
+ return game;
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java
index 5d64d3d2460..45eda5e7fe5 100644
--- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java
@@ -52,6 +52,7 @@ public abstract class MageTestPlayerBase {
protected Map> battlefieldCards = new HashMap<>();
protected Map> graveyardCards = new HashMap<>();
protected Map> libraryCards = new HashMap<>();
+ protected Map> commandCards = new HashMap<>();
protected Map> commands = new HashMap<>();
@@ -211,6 +212,9 @@ public abstract class MageTestPlayerBase {
} else if ("library".equalsIgnoreCase(zone)) {
gameZone = Zone.LIBRARY;
cards = getLibraryCards(getPlayer(nickname));
+ } else if ("command".equalsIgnoreCase(zone)) {
+ gameZone = Zone.COMMAND;
+ cards = getCommandCards(getPlayer(nickname));
} else if ("player".equalsIgnoreCase(zone)) {
String command = m.group(3);
if ("life".equals(command)) {
@@ -280,27 +284,36 @@ public abstract class MageTestPlayerBase {
if (graveyardCards.containsKey(player)) {
return graveyardCards.get(player);
}
- List grave = new ArrayList<>();
- graveyardCards.put(player, grave);
- return grave;
+ List res = new ArrayList<>();
+ graveyardCards.put(player, res);
+ return res;
}
protected List getLibraryCards(TestPlayer player) {
if (libraryCards.containsKey(player)) {
return libraryCards.get(player);
}
- List library = new ArrayList<>();
- libraryCards.put(player, library);
- return library;
+ List res = new ArrayList<>();
+ libraryCards.put(player, res);
+ return res;
+ }
+
+ protected List getCommandCards(TestPlayer player) {
+ if (commandCards.containsKey(player)) {
+ return commandCards.get(player);
+ }
+ List res = new ArrayList<>();
+ commandCards.put(player, res);
+ return res;
}
protected List getBattlefieldCards(TestPlayer player) {
if (battlefieldCards.containsKey(player)) {
return battlefieldCards.get(player);
}
- List battlefield = new ArrayList<>();
- battlefieldCards.put(player, battlefield);
- return battlefield;
+ List res = new ArrayList<>();
+ battlefieldCards.put(player, res);
+ return res;
}
protected Map getCommands(TestPlayer player) {
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
index b7ccdb1bfc6..8b66bcc20ad 100644
--- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
@@ -52,6 +52,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
// TODO: add target player param to commands
public static final String CHECK_COMMAND_PT = "PT";
+ public static final String CHECK_COMMAND_DAMAGE = "DAMAGE";
public static final String CHECK_COMMAND_LIFE = "LIFE";
public static final String CHECK_COMMAND_ABILITY = "ABILITY";
public static final String CHECK_COMMAND_PERMANENT_COUNT = "PERMANENT_COUNT";
@@ -69,6 +70,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
// TODO: add target player param to commands
public static final String SHOW_COMMAND_LIBRARY = "LIBRARY";
public static final String SHOW_COMMAND_HAND = "HAND";
+ public static final String SHOW_COMMAND_COMMAND = "COMMAND";
public static final String SHOW_COMMAND_BATTLEFIELD = "BATTLEFIELD";
public static final String SHOW_COMMAND_GRAVEYEARD = "GRAVEYARD";
public static final String SHOW_COMMAND_EXILE = "EXILE";
@@ -239,7 +241,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
TestPlayer testPlayer = (TestPlayer) player;
currentGame.cheat(player.getId(), getCommands(testPlayer));
currentGame.cheat(player.getId(), activePlayer.getId(), getLibraryCards(testPlayer), getHandCards(testPlayer),
- getBattlefieldCards(testPlayer), getGraveCards(testPlayer));
+ getBattlefieldCards(testPlayer), getGraveCards(testPlayer), getCommandCards(testPlayer));
}
long t1 = System.nanoTime();
@@ -297,6 +299,11 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
check(checkName, turnNum, step, player, CHECK_COMMAND_PT, permanentName, power.toString(), toughness.toString());
}
+ public void checkDamage(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer damage) {
+ //Assert.assertNotEquals("", permanentName);
+ check(checkName, turnNum, step, player, CHECK_COMMAND_DAMAGE, permanentName, damage.toString());
+ }
+
public void checkLife(String checkName, int turnNum, PhaseStep step, TestPlayer player, Integer life) {
check(checkName, turnNum, step, player, CHECK_COMMAND_LIFE, life.toString());
}
@@ -383,6 +390,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
show(showName, turnNum, step, player, SHOW_COMMAND_HAND);
}
+ public void showCommand(String showName, int turnNum, PhaseStep step, TestPlayer player) {
+ show(showName, turnNum, step, player, SHOW_COMMAND_COMMAND);
+ }
+
public void showBattlefield(String showName, int turnNum, PhaseStep step, TestPlayer player) {
show(showName, turnNum, step, player, SHOW_COMMAND_BATTLEFIELD);
}
@@ -530,6 +541,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
return getGraveCards(player);
case LIBRARY:
return getLibraryCards(player);
+ case COMMAND:
+ return getCommandCards(player);
default:
break;
}
@@ -1251,7 +1264,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
if (!player.getActions().isEmpty()) {
System.out.println("Remaining actions for " + player.getName() + " (" + player.getActions().size() + "):");
player.getActions().stream().forEach(a -> {
- System.out.println("* turn " + a.getTurnNum() + " - " + a.getStep() + ": " + a.getActionName());
+ System.out.println("* turn " + a.getTurnNum() + " - " + a.getStep() + ": " + (a.getActionName().isEmpty() ? a.getAction() : a.getActionName()));
});
Assert.fail("Player " + player.getName() + " must have 0 actions but found " + player.getActions().size());
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/ExportJsonGameplayDataTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/ExportJsonGameplayDataTest.java
index 67ef4b64317..624c07c13f9 100644
--- a/Mage.Tests/src/test/java/org/mage/test/utils/ExportJsonGameplayDataTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/utils/ExportJsonGameplayDataTest.java
@@ -37,8 +37,16 @@ public class ExportJsonGameplayDataTest {
Collection sets = Sets.getInstance().values();
for (ExpansionSet set : sets) {
for (ExpansionSet.SetCardInfo setInfo : set.getSetCardInfo()) {
- cards.add(CardImpl.createCard(setInfo.getCardClass(), new CardSetInfo(setInfo.getName(), set.getCode(),
- setInfo.getCardNumber(), setInfo.getRarity(), setInfo.getGraphicInfo())));
+ // catch cards creation errors and report (e.g. on wrong card code)
+ try {
+ Card card = CardImpl.createCard(setInfo.getCardClass(), new CardSetInfo(setInfo.getName(), set.getCode(),
+ setInfo.getCardNumber(), setInfo.getRarity(), setInfo.getGraphicInfo()));
+ if (card != null) {
+ cards.add(card);
+ }
+ } catch (Throwable e) {
+ logger.error("Can't create card " + setInfo.getName() + ": " + e.getMessage(), e);
+ }
}
JsonObject res = new JsonObject();
diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java
index 36ce86fb2d5..b3fcd37e40d 100644
--- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java
+++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java
@@ -15,6 +15,7 @@ import mage.game.draft.RateCard;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.TokenImpl;
import mage.watchers.Watcher;
+import org.apache.log4j.Logger;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
@@ -41,6 +42,8 @@ import java.util.stream.Collectors;
*/
public class VerifyCardDataTest {
+ private static final Logger logger = Logger.getLogger(VerifyCardDataTest.class);
+
// right now this is very noisy, and not useful enough to make any assertions on
private static final boolean CHECK_SOURCE_TOKENS = false;
@@ -411,7 +414,7 @@ public class VerifyCardDataTest {
}
@Test
- @Ignore // TODO: enable it on copy() methods removing
+ //@Ignore // TODO: enable it on copy() methods removing
public void checkWatcherCopyMethods() {
Collection errorsList = new ArrayList<>();
@@ -421,6 +424,13 @@ public class VerifyCardDataTest {
Set> watcherClassesList = reflections.getSubTypesOf(Watcher.class);
for (Class extends Watcher> watcherClass : watcherClassesList) {
+
+ // only watcher class can be extended (e.g. final)
+ if (!watcherClass.getSuperclass().equals(Watcher.class)) {
+ errorsList.add("error, only Watcher class can be extended: " + watcherClass.getName());
+ }
+
+ // no copy methods
try {
Method m = watcherClass.getMethod("copy");
if (!m.getGenericReturnType().getTypeName().equals("T")) {
@@ -429,6 +439,34 @@ public class VerifyCardDataTest {
} catch (NoSuchMethodException e) {
errorsList.add("error, can't find copy() method in watcher class: " + watcherClass.getName());
}
+
+ // no constructor for copy
+ try {
+ Constructor extends Watcher> constructor = watcherClass.getDeclaredConstructor(watcherClass);
+ errorsList.add("error, copy constructor is not allowed in watcher class: " + watcherClass.getName());
+ } catch (NoSuchMethodException e) {
+ // all fine, no needs in copy constructors
+ }
+
+ // errors on create
+ try {
+ Constructor extends Watcher> constructor = watcherClass.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ Watcher w1 = constructor.newInstance();
+
+ // errors on copy
+ try {
+ Watcher w2 = w1.copy();
+ if (w2 == null) {
+ errorsList.add("error, can't copy watcher with unknown error, look at error logs above: " + watcherClass.getName());
+ }
+ } catch (Exception e) {
+ errorsList.add("error, can't copy watcher: " + watcherClass.getName() + " (" + e.getMessage() + ")");
+ }
+ } catch (Exception e) {
+ errorsList.add("error, can't create watcher: " + watcherClass.getName() + " (" + e.getMessage() + ")");
+ }
+
}
printMessages(warningsList);
@@ -971,4 +1009,28 @@ public class VerifyCardDataTest {
}
}
}
+
+ @Test
+ public void testCardsCreatingAndConstructorErrors() {
+ int errorsCount = 0;
+ Collection sets = Sets.getInstance().values();
+ for (ExpansionSet set : sets) {
+ for (ExpansionSet.SetCardInfo setInfo : set.getSetCardInfo()) {
+ // catch cards creation errors and report (e.g. on wrong card code or construction checks fail)
+ try {
+ Card card = CardImpl.createCard(setInfo.getCardClass(), new CardSetInfo(setInfo.getName(), set.getCode(),
+ setInfo.getCardNumber(), setInfo.getRarity(), setInfo.getGraphicInfo()));
+ if (card == null) {
+ errorsCount++;
+ }
+ } catch (Throwable e) {
+ logger.error("Can't create card " + setInfo.getName() + ": " + e.getMessage(), e);
+ }
+ }
+ }
+
+ if (errorsCount > 0) {
+ Assert.fail("Founded " + errorsCount + " broken cards, look at logs for stack error");
+ }
+ }
}
diff --git a/Mage/src/main/java/mage/MageObjectReference.java b/Mage/src/main/java/mage/MageObjectReference.java
index 44f63bebc66..a4f2a81302f 100644
--- a/Mage/src/main/java/mage/MageObjectReference.java
+++ b/Mage/src/main/java/mage/MageObjectReference.java
@@ -53,6 +53,10 @@ public class MageObjectReference implements Comparable, Ser
public MageObjectReference(UUID sourceId, Game game) {
this.sourceId = sourceId;
+ if (sourceId == null) {
+ throw new IllegalArgumentException("MageObjectReference contains nullable sourceId");
+ }
+
MageObject mageObject = game.getObject(sourceId);
if (mageObject != null) {
this.zoneChangeCounter = mageObject.getZoneChangeCounter(game);
diff --git a/Mage/src/main/java/mage/abilities/common/CastCommanderAbility.java b/Mage/src/main/java/mage/abilities/common/CastCommanderAbility.java
index be7896e11b0..c31137dfe88 100644
--- a/Mage/src/main/java/mage/abilities/common/CastCommanderAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/CastCommanderAbility.java
@@ -1,7 +1,7 @@
-
package mage.abilities.common;
import mage.abilities.SpellAbility;
+import mage.abilities.costs.CostsImpl;
import mage.cards.Card;
import mage.constants.SpellAbilityType;
import mage.constants.TimingRule;
@@ -9,15 +9,21 @@ import mage.constants.Zone;
import mage.game.Game;
/**
- *
* @author Plopman
*/
public class CastCommanderAbility extends SpellAbility {
public CastCommanderAbility(Card card) {
super(card.getManaCost(), card.getName(), Zone.COMMAND, SpellAbilityType.BASE);
- this.costs = card.getSpellAbility().getCosts().copy();
- this.timing = TimingRule.SORCERY;
+ if (card.getSpellAbility() != null) {
+ this.getCosts().addAll(card.getSpellAbility().getCosts().copy());
+ this.getEffects().addAll(card.getSpellAbility().getEffects().copy());
+ this.getTargets().addAll(card.getSpellAbility().getTargets().copy());
+ this.timing = card.getSpellAbility().getTiming();
+ } else {
+ this.costs = new CostsImpl<>();
+ this.timing = TimingRule.SORCERY;
+ }
this.usesStack = true;
this.controllerId = card.getOwnerId();
this.sourceId = card.getId();
diff --git a/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java
index acf69c2ba12..e05f4cf3bba 100644
--- a/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/DealsCombatDamageToAPlayerTriggeredAbility.java
@@ -1,4 +1,3 @@
-
package mage.abilities.common;
import mage.abilities.TriggeredAbilityImpl;
@@ -45,6 +44,7 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility
this.text = ability.text;
this.setTargetPointer = ability.setTargetPointer;
this.onlyOpponents = ability.onlyOpponents;
+ this.orPlaneswalker = ability.orPlaneswalker;
}
public DealsCombatDamageToAPlayerTriggeredAbility setOrPlaneswalker(boolean orPlaneswalker) {
diff --git a/Mage/src/main/java/mage/abilities/costs/common/RemoveCounterCost.java b/Mage/src/main/java/mage/abilities/costs/common/RemoveCounterCost.java
index 90c7b07cd92..ab1196345f3 100644
--- a/Mage/src/main/java/mage/abilities/costs/common/RemoveCounterCost.java
+++ b/Mage/src/main/java/mage/abilities/costs/common/RemoveCounterCost.java
@@ -1,9 +1,5 @@
-
package mage.abilities.costs.common;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
@@ -18,8 +14,11 @@ import mage.players.Player;
import mage.target.TargetPermanent;
import mage.util.CardUtil;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author LevelX
*/
public class RemoveCounterCost extends CostImpl {
@@ -102,10 +101,6 @@ public class RemoveCounterCost extends CostImpl {
new StringBuilder("Remove how many counters from ").append(permanent.getIdName()).toString(), game);
}
permanent.removeCounters(counterName, numberOfCountersSelected, game);
- if (permanent.getCounters(game).getCount(counterName) == 0) {
- // this removes only the item with number = 0 from the collection
- permanent.getCounters(game).removeCounter(counterName);
- }
countersRemoved += numberOfCountersSelected;
if (!game.isSimulation()) {
game.informPlayers(new StringBuilder(controller.getLogName())
diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalContinuousEffect.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalContinuousEffect.java
index 1ce5392da33..df8c2f51e57 100644
--- a/Mage/src/main/java/mage/abilities/decorator/ConditionalContinuousEffect.java
+++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalContinuousEffect.java
@@ -1,9 +1,5 @@
package mage.abilities.decorator;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.condition.Condition;
@@ -11,11 +7,14 @@ import mage.abilities.condition.FixedCondition;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
-import mage.constants.DependencyType;
-import mage.constants.Duration;
-import mage.constants.Layer;
-import mage.constants.SubLayer;
+import mage.constants.*;
import mage.game.Game;
+import org.junit.Assert;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
/**
* Adds condition to {@link ContinuousEffect}. Acts as decorator.
@@ -48,6 +47,18 @@ public class ConditionalContinuousEffect extends ContinuousEffectImpl {
this.otherwiseEffect = otherwiseEffect;
this.baseCondition = condition;
this.staticText = text;
+
+ // checks for compatibility
+ EffectType needType = EffectType.CONTINUOUS;
+ if (effect != null && !effect.getEffectType().equals(needType)) {
+ Assert.fail("ConditionalContinuousEffect supports only " + needType.toString() + " but found " + effect.getEffectType().toString());
+ }
+ if (otherwiseEffect != null && !otherwiseEffect.getEffectType().equals(needType)) {
+ Assert.fail("ConditionalContinuousEffect supports only " + needType.toString() + " but found " + effect.getEffectType().toString());
+ }
+ if (effect != null && otherwiseEffect != null && !effect.getEffectType().equals(otherwiseEffect.getEffectType())) {
+ Assert.fail("ConditionalContinuousEffect must be same but found " + effect.getEffectType().toString() + " and " + otherwiseEffect.getEffectType().toString());
+ }
}
public ConditionalContinuousEffect(final ConditionalContinuousEffect effect) {
@@ -68,6 +79,7 @@ public class ConditionalContinuousEffect extends ContinuousEffectImpl {
@Override
public void init(Ability source, Game game) {
+ super.init(source, game);
if (baseCondition instanceof LockedInCondition) {
condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
} else {
diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalCostModificationEffect.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalCostModificationEffect.java
new file mode 100644
index 00000000000..cecf01c6245
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalCostModificationEffect.java
@@ -0,0 +1,86 @@
+package mage.abilities.decorator;
+
+import mage.abilities.Ability;
+import mage.abilities.condition.Condition;
+import mage.abilities.effects.CostModificationEffect;
+import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.constants.Duration;
+import mage.game.Game;
+
+/**
+ * @author JayDi85
+ */
+public class ConditionalCostModificationEffect extends CostModificationEffectImpl {
+
+ protected CostModificationEffect effect;
+ protected CostModificationEffect otherwiseEffect;
+ protected Condition condition;
+ protected boolean conditionState;
+
+ public ConditionalCostModificationEffect(CostModificationEffect effect, Condition condition, String text) {
+ this(effect, condition, null, text);
+ }
+
+ public ConditionalCostModificationEffect(CostModificationEffect effect, Condition condition, CostModificationEffect otherwiseEffect,
+ String text) {
+ super(effect.getDuration(), effect.getOutcome(), effect.getModificationType());
+ this.effect = effect;
+ this.condition = condition;
+ this.otherwiseEffect = otherwiseEffect;
+ if (text != null) {
+ this.setText(text);
+ }
+ }
+
+ public ConditionalCostModificationEffect(final ConditionalCostModificationEffect effect) {
+ super(effect);
+ this.effect = (CostModificationEffect) effect.effect.copy();
+ if (effect.otherwiseEffect != null) {
+ this.otherwiseEffect = (CostModificationEffect) effect.otherwiseEffect.copy();
+ }
+ this.condition = effect.condition;
+ this.conditionState = effect.conditionState;
+ }
+
+ @Override
+ public boolean isDiscarded() {
+ return effect.isDiscarded() || (otherwiseEffect != null && otherwiseEffect.isDiscarded());
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source, Ability abilityToModify) {
+ conditionState = condition.apply(game, source);
+ if (conditionState) {
+ effect.setTargetPointer(this.targetPointer);
+ return effect.apply(game, source, abilityToModify);
+ } else if (otherwiseEffect != null) {
+ otherwiseEffect.setTargetPointer(this.targetPointer);
+ return otherwiseEffect.apply(game, source, abilityToModify);
+ }
+ if (!conditionState && effect.getDuration() == Duration.OneUse) {
+ used = true;
+ }
+ if (!conditionState && effect.getDuration() == Duration.Custom) {
+ this.discard();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean applies(Ability abilityToModify, Ability source, Game game) {
+ conditionState = condition.apply(game, source);
+ if (conditionState) {
+ effect.setTargetPointer(this.targetPointer);
+ return effect.applies(abilityToModify, source, game);
+ } else if (otherwiseEffect != null) {
+ otherwiseEffect.setTargetPointer(this.targetPointer);
+ return otherwiseEffect.applies(abilityToModify, source, game);
+ }
+ return false;
+ }
+
+ @Override
+ public ConditionalCostModificationEffect copy() {
+ return new ConditionalCostModificationEffect(this);
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalPreventionEffect.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalPreventionEffect.java
new file mode 100644
index 00000000000..ec256f06dc0
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalPreventionEffect.java
@@ -0,0 +1,140 @@
+package mage.abilities.decorator;
+
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.FixedCondition;
+import mage.abilities.condition.LockedInCondition;
+import mage.abilities.effects.PreventionEffect;
+import mage.abilities.effects.PreventionEffectImpl;
+import mage.constants.Duration;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+
+/**
+ * @author JayDi85
+ */
+public class ConditionalPreventionEffect extends PreventionEffectImpl {
+
+ protected PreventionEffect effect;
+ protected PreventionEffect otherwiseEffect;
+ protected Condition baseCondition;
+ protected Condition condition;
+ protected boolean conditionState;
+ protected boolean initDone = false;
+
+ public ConditionalPreventionEffect(PreventionEffect effect, Condition condition, String text) {
+ this(effect, null, condition, text);
+ }
+
+ /**
+ * Only use this if both effects have the same layers
+ *
+ * @param effect
+ * @param otherwiseEffect
+ * @param condition
+ * @param text
+ */
+ public ConditionalPreventionEffect(PreventionEffect effect, PreventionEffect otherwiseEffect, Condition condition, String text) {
+ super(effect.getDuration());
+ this.effect = effect;
+ this.otherwiseEffect = otherwiseEffect;
+ this.baseCondition = condition;
+ this.staticText = text;
+ }
+
+ public ConditionalPreventionEffect(final ConditionalPreventionEffect effect) {
+ super(effect);
+ this.effect = (PreventionEffect) effect.effect.copy();
+ if (effect.otherwiseEffect != null) {
+ this.otherwiseEffect = (PreventionEffect) effect.otherwiseEffect.copy();
+ }
+ this.condition = effect.condition; // TODO: checks conditional copy -- it's can be usefull for memory leaks fix?
+ this.conditionState = effect.conditionState;
+ this.baseCondition = effect.baseCondition;
+ this.initDone = effect.initDone;
+ }
+
+ @Override
+ public boolean isDiscarded() {
+ return this.discarded || effect.isDiscarded() || (otherwiseEffect != null && otherwiseEffect.isDiscarded());
+ }
+
+ @Override
+ public void init(Ability source, Game game) {
+ super.init(source, game);
+ if (baseCondition instanceof LockedInCondition) {
+ condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
+ } else {
+ condition = baseCondition;
+ }
+ effect.setTargetPointer(this.targetPointer);
+ effect.init(source, game);
+ if (otherwiseEffect != null) {
+ otherwiseEffect.setTargetPointer(this.targetPointer);
+ otherwiseEffect.init(source, game);
+ }
+ initDone = true;
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ if (conditionState) {
+ effect.setTargetPointer(this.targetPointer);
+ return effect.replaceEvent(event, source, game);
+ } else if (otherwiseEffect != null) {
+ otherwiseEffect.setTargetPointer(this.targetPointer);
+ return otherwiseEffect.replaceEvent(event, source, game);
+ }
+
+ if (!conditionState && effect.getDuration() == Duration.OneUse) {
+ used = true;
+ }
+ if (!conditionState && effect.getDuration() == Duration.Custom) {
+ this.discard();
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return false;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return effect.checksEventType(event, game)
+ || (otherwiseEffect != null && otherwiseEffect.checksEventType(event, game));
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (!initDone) { // if simpleStaticAbility, init won't be called
+ init(source, game);
+ }
+ conditionState = condition.apply(game, source);
+ if (conditionState) {
+ effect.setTargetPointer(this.targetPointer);
+ return effect.applies(event, source, game);
+ } else if (otherwiseEffect != null) {
+ otherwiseEffect.setTargetPointer(this.targetPointer);
+ return otherwiseEffect.applies(event, source, game);
+ }
+ return false;
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ if ((staticText == null || staticText.isEmpty()) && this.effect != null) { // usefull for conditional night/day card abilities
+ return effect.getText(mode);
+ }
+ return staticText;
+ }
+
+ @Override
+ public ConditionalPreventionEffect copy() {
+ return new ConditionalPreventionEffect(this);
+ }
+
+}
diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalRequirementEffect.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalRequirementEffect.java
index 5ebe3b61720..148be62172d 100644
--- a/Mage/src/main/java/mage/abilities/decorator/ConditionalRequirementEffect.java
+++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalRequirementEffect.java
@@ -1,7 +1,5 @@
-
package mage.abilities.decorator;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.abilities.condition.FixedCondition;
@@ -12,12 +10,13 @@ import mage.constants.EffectType;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
-public class ConditionalRequirementEffect extends RequirementEffect {
+public class ConditionalRequirementEffect extends RequirementEffect {
protected RequirementEffect effect;
protected RequirementEffect otherwiseEffect;
@@ -27,7 +26,14 @@ public class ConditionalRequirementEffect extends RequirementEffect {
protected boolean initDone = false;
public ConditionalRequirementEffect(RequirementEffect effect, Condition condition) {
- this(Duration.WhileOnBattlefield, effect, condition, null, false);
+ this(effect, condition, null);
+ }
+
+ public ConditionalRequirementEffect(RequirementEffect effect, Condition condition, String text) {
+ this(effect.getDuration(), effect, condition, null, false);
+ if (text != null) {
+ setText(text);
+ }
}
public ConditionalRequirementEffect(Duration duration, RequirementEffect effect, Condition condition, RequirementEffect otherwiseEffect, boolean lockedInCondition) {
@@ -75,7 +81,7 @@ public class ConditionalRequirementEffect extends RequirementEffect {
conditionState = condition.apply(game, source);
if (conditionState) {
effect.setTargetPointer(this.targetPointer);
- return effect.applies(permanent, source,game);
+ return effect.applies(permanent, source, game);
} else if (otherwiseEffect != null) {
otherwiseEffect.setTargetPointer(this.targetPointer);
return otherwiseEffect.applies(permanent, source, game);
@@ -138,7 +144,7 @@ public class ConditionalRequirementEffect extends RequirementEffect {
}
return null;
}
-
+
@Override
public ConditionalRequirementEffect copy() {
return new ConditionalRequirementEffect(this);
diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalRestrictionEffect.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalRestrictionEffect.java
index 5f1e6318d58..f9dec0248a3 100644
--- a/Mage/src/main/java/mage/abilities/decorator/ConditionalRestrictionEffect.java
+++ b/Mage/src/main/java/mage/abilities/decorator/ConditionalRestrictionEffect.java
@@ -22,14 +22,25 @@ public class ConditionalRestrictionEffect extends RestrictionEffect {
protected boolean initDone = false;
public ConditionalRestrictionEffect(RestrictionEffect effect, Condition condition) {
- this(Duration.WhileOnBattlefield, effect, condition, null);
+ this(effect, condition, null);
+ }
+
+ public ConditionalRestrictionEffect(RestrictionEffect effect, Condition condition, String text) {
+ this(effect.getDuration(), effect, condition, null, text);
}
public ConditionalRestrictionEffect(Duration duration, RestrictionEffect effect, Condition condition, RestrictionEffect otherwiseEffect) {
+ this(duration, effect, condition, otherwiseEffect, null);
+ }
+
+ public ConditionalRestrictionEffect(Duration duration, RestrictionEffect effect, Condition condition, RestrictionEffect otherwiseEffect, String text) {
super(duration);
this.effect = effect;
this.baseCondition = condition;
this.otherwiseEffect = otherwiseEffect;
+ if (text != null) {
+ this.setText(text);
+ }
}
public ConditionalRestrictionEffect(final ConditionalRestrictionEffect effect) {
diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/PermanentsYouControlCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/PermanentsYouControlCount.java
new file mode 100644
index 00000000000..8eef2b5ca7a
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/PermanentsYouControlCount.java
@@ -0,0 +1,35 @@
+package mage.abilities.dynamicvalue.common;
+
+import mage.abilities.Ability;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.effects.Effect;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+
+/**
+ * @author JayDi85
+ */
+public enum PermanentsYouControlCount implements DynamicValue {
+
+ instance;
+
+ @Override
+ public int calculate(Game game, Ability sourceAbility, Effect effect) {
+ return game.getBattlefield().count(StaticFilters.FILTER_CONTROLLED_PERMANENT, sourceAbility.getSourceId(), sourceAbility.getControllerId(), game);
+ }
+
+ @Override
+ public PermanentsYouControlCount copy() {
+ return instance;
+ }
+
+ @Override
+ public String toString() {
+ return "X";
+ }
+
+ @Override
+ public String getMessage() {
+ return "permanents you control";
+ }
+}
diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java
index 2970bbe3531..7cc9ed6c867 100644
--- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java
+++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java
@@ -311,14 +311,6 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
}
}
return dependentToEffects;
- /*
- return allEffectsInLayer.stream()
- .filter(effect -> effect.getDependencyTypes().contains(dependendToTypes))
- .map(Effect::getId)
- .collect(Collectors.toSet());
-
- }
- return new HashSet<>();*/
}
@Override
diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java
index e6bb1a53da2..6cb9d0e7703 100644
--- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java
+++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java
@@ -369,6 +369,7 @@ public class ContinuousEffects implements Serializable {
replaceEffects.put(effect, applicableAbilities);
}
}
+
for (Iterator iterator = preventionEffects.iterator(); iterator.hasNext(); ) {
PreventionEffect effect = iterator.next();
if (!effect.checksEventType(event, game)) {
@@ -394,6 +395,7 @@ public class ContinuousEffects implements Serializable {
replaceEffects.put(effect, applicableAbilities);
}
}
+
return replaceEffects;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToAttachedEffect.java
index 520f3a8a6f5..d696229bc96 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToAttachedEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToAttachedEffect.java
@@ -1,4 +1,3 @@
-
package mage.abilities.effects.common;
import mage.abilities.Ability;
@@ -70,8 +69,8 @@ public class PreventDamageToAttachedEffect extends PreventionEffectImpl {
}
sb.append("damage to ");
sb.append(attachmentType.verb());
- sb.append("creature, prevent ").append(amountToPrevent);;
- sb.append("of that damage");
+ sb.append(" creature, prevent ").append(amountToPrevent);;
+ sb.append(" of that damage");
}
return sb.toString();
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java
index 54d96c75d15..07892612d65 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureAllEffect.java
@@ -1,19 +1,13 @@
-
package mage.abilities.effects.common.continuous;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.ContinuousEffectImpl;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Layer;
-import mage.constants.Outcome;
-import mage.constants.SubLayer;
+import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import java.util.HashSet;
@@ -21,7 +15,6 @@ import java.util.Set;
/**
* @author LevelX2
- *
*/
public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
@@ -29,13 +22,19 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
protected String theyAreStillType;
private final FilterPermanent filter;
private boolean loseColor = true;
+ protected boolean loseName = false;
public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor) {
+ this(token, theyAreStillType, filter, duration, loseColor, false);
+ }
+
+ public BecomesCreatureAllEffect(Token token, String theyAreStillType, FilterPermanent filter, Duration duration, boolean loseColor, boolean loseName) {
super(duration, Outcome.BecomeCreature);
this.token = token;
this.theyAreStillType = theyAreStillType;
this.filter = filter;
this.loseColor = loseColor;
+ this.loseName = loseName;
}
public BecomesCreatureAllEffect(final BecomesCreatureAllEffect effect) {
@@ -44,6 +43,7 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
this.theyAreStillType = effect.theyAreStillType;
this.filter = effect.filter.copy();
this.loseColor = effect.loseColor;
+ this.loseName = effect.loseName;
}
@Override
@@ -65,30 +65,47 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Set affectedPermanents = new HashSet<>();
if (this.affectedObjectsSet) {
- for(MageObjectReference ref : affectedObjectList) {
+ for (MageObjectReference ref : affectedObjectList) {
affectedPermanents.add(ref.getPermanent(game));
}
} else {
affectedPermanents = new HashSet<>(game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game));
}
- for(Permanent permanent : affectedPermanents) {
+ for (Permanent permanent : affectedPermanents) {
if (permanent != null) {
switch (layer) {
+ case TextChangingEffects_3:
+ if (sublayer == SubLayer.NA) {
+ if (loseName) {
+ permanent.setName(token.getName());
+ }
+ }
+ break;
+
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
- if (!token.getCardType().isEmpty()) {
- for (CardType t : token.getCardType()) {
- if (!permanent.getCardType().contains(t)) {
- permanent.addCardType(t);
+ if (theyAreStillType != null) {
+ permanent.getSubtype(game).retainAll(SubType.getLandTypes());
+ permanent.getSubtype(game).addAll(token.getSubtype(game));
+ } else {
+ for (SubType t : token.getSubtype(game)) {
+ if (!permanent.hasSubtype(t, game)) {
+ permanent.getSubtype(game).add(t);
}
}
}
- if (theyAreStillType == null) {
- permanent.getSubtype(game).clear();
+
+ for (SuperType t : token.getSuperType()) {
+ if (!permanent.getSuperType().contains(t)) {
+ permanent.addSuperType(t);
+ }
}
- if (!token.getSubtype(game).isEmpty()) {
- permanent.getSubtype(game).addAll(token.getSubtype(game));
+
+ for (CardType t : token.getCardType()) {
+ if (!permanent.getCardType().contains(t)) {
+ permanent.addCardType(t);
+ }
}
}
break;
@@ -141,7 +158,11 @@ public class BecomesCreatureAllEffect extends ContinuousEffectImpl {
@Override
public boolean hasLayer(Layer layer) {
- return layer == Layer.PTChangingEffects_7 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4;
+ return layer == Layer.PTChangingEffects_7
+ || layer == Layer.AbilityAddingRemovingEffects_6
+ || layer == Layer.ColorChangingEffects_5
+ || layer == Layer.TypeChangingEffects_4
+ || layer == Layer.TextChangingEffects_3;
}
@Override
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java
index 97d55d1aa0b..ae2f629c6c0 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesCreatureTargetEffect.java
@@ -69,30 +69,34 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl {
}
}
break;
+
case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) {
if (loseAllAbilities) {
permanent.getSubtype(game).retainAll(SubType.getLandTypes());
permanent.getSubtype(game).addAll(token.getSubtype(game));
} else {
- if (!token.getSubtype(game).isEmpty()) {
- for (SubType subtype : token.getSubtype(game)) {
- if (!permanent.hasSubtype(subtype, game)) {
- permanent.getSubtype(game).add(subtype);
- }
+ for (SubType t : token.getSubtype(game)) {
+ if (!permanent.hasSubtype(t, game)) {
+ permanent.getSubtype(game).add(t);
}
-
}
}
- if (!token.getCardType().isEmpty()) {
- for (CardType t : token.getCardType()) {
- if (!permanent.getCardType().contains(t)) {
- permanent.addCardType(t);
- }
+
+ for (SuperType t : token.getSuperType()) {
+ if (!permanent.getSuperType().contains(t)) {
+ permanent.addSuperType(t);
+ }
+ }
+
+ for (CardType t : token.getCardType()) {
+ if (!permanent.getCardType().contains(t)) {
+ permanent.addCardType(t);
}
}
}
break;
+
case ColorChangingEffects_5:
if (sublayer == SubLayer.NA) {
if (loseAllAbilities) {
@@ -107,6 +111,7 @@ public class BecomesCreatureTargetEffect extends ContinuousEffectImpl {
}
}
break;
+
case AbilityAddingRemovingEffects_6:
if (loseAllAbilities) {
permanent.removeAllAbilities(source.getSourceId(), game);
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapAllDuringEachOtherPlayersUntapStepEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapAllDuringEachOtherPlayersUntapStepEffect.java
index 0b8c11b397c..bc2b0c89358 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapAllDuringEachOtherPlayersUntapStepEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/UntapAllDuringEachOtherPlayersUntapStepEffect.java
@@ -33,13 +33,13 @@ public class UntapAllDuringEachOtherPlayersUntapStepEffect extends ContinuousEff
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
- Boolean applied = (Boolean) game.getState().getValue(source.getSourceId() + "applied");
- if (applied == null) {
- applied = Boolean.FALSE;
- }
- if (!applied && layer == Layer.RulesEffects) {
- if (!source.isControlledBy(game.getActivePlayerId()) && game.getStep().getType() == PhaseStep.UNTAP) {
- game.getState().setValue(source.getSourceId() + "applied", true);
+ if (layer == Layer.RulesEffects && game.getStep().getType() == PhaseStep.UNTAP && !source.isControlledBy(game.getActivePlayerId())) {
+ Integer appliedTurn = (Integer) game.getState().getValue(source.getSourceId() + "appliedTurn");
+ if (appliedTurn == null) {
+ appliedTurn = 0;
+ }
+ if (appliedTurn < game.getTurnNum()) {
+ game.getState().setValue(source.getSourceId() + "appliedTurn", game.getTurnNum());
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
boolean untap = true;
for (RestrictionEffect effect : game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).keySet()) {
@@ -50,10 +50,6 @@ public class UntapAllDuringEachOtherPlayersUntapStepEffect extends ContinuousEff
}
}
}
- } else if (applied && layer == Layer.RulesEffects) {
- if (game.getStep().getType() == PhaseStep.END_TURN) {
- game.getState().setValue(source.getSourceId() + "applied", false);
- }
}
return true;
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/ProliferateEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/ProliferateEffect.java
index 005e6c0712d..e82e3c94def 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/counter/ProliferateEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/counter/ProliferateEffect.java
@@ -4,11 +4,12 @@ import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.counters.Counter;
+import mage.filter.common.FilterPermanentOrPlayerWithCounter;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
-import mage.target.common.TargetPermanentOrPlayerWithCounter;
+import mage.target.common.TargetPermanentOrPlayer;
import java.io.Serializable;
import java.util.HashMap;
@@ -47,7 +48,7 @@ public class ProliferateEffect extends OneShotEffect {
if (controller == null) {
return false;
}
- Target target = new TargetPermanentOrPlayerWithCounter(0, Integer.MAX_VALUE, true);
+ Target target = new TargetPermanentOrPlayer(0, Integer.MAX_VALUE, new FilterPermanentOrPlayerWithCounter(), true);
Map options = new HashMap<>();
options.put("UI.right.btn.text", "Done");
controller.choose(Outcome.Benefit, target, source.getSourceId(), game, options);
diff --git a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java
index ad8a25bbdea..e658515c4c8 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/discard/DiscardCardYouChooseTargetEffect.java
@@ -106,7 +106,7 @@ public class DiscardCardYouChooseTargetEffect extends OneShotEffect {
Cards revealedCards = new CardsImpl();
numberToReveal = Math.min(player.getHand().size(), numberToReveal);
if (player.getHand().size() > numberToReveal) {
- TargetCardInHand chosenCards = new TargetCardInHand(numberToReveal, numberToReveal, new FilterCard("card in " + player.getLogName() + "'s hand"));
+ TargetCardInHand chosenCards = new TargetCardInHand(numberToReveal, numberToReveal, new FilterCard("card in " + player.getName() + "'s hand"));
chosenCards.setNotTarget(true);
if (chosenCards.canChoose(player.getId(), game) && player.chooseTarget(Outcome.Discard, player.getHand(), chosenCards, source, game)) {
if (!chosenCards.getTargets().isEmpty()) {
diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/AdaptEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/AdaptEffect.java
index ed29b59aea6..43a81809f3c 100644
--- a/Mage/src/main/java/mage/abilities/effects/keyword/AdaptEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/keyword/AdaptEffect.java
@@ -1,8 +1,10 @@
package mage.abilities.effects.keyword;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
+import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -19,10 +21,10 @@ public class AdaptEffect extends OneShotEffect {
public AdaptEffect(int adaptNumber) {
super(Outcome.BoostCreature);
this.adaptNumber = adaptNumber;
- staticText = "Adapt " + adaptNumber +
- " (If this creature has no +1/+1 counters on it, put " +
- CardUtil.numberToText(adaptNumber) + " +1/+1 counter" +
- (adaptNumber > 1 ? "s" : "") + " on it.)";
+ staticText = "Adapt " + adaptNumber
+ + " (If this creature has no +1/+1 counters on it, put "
+ + CardUtil.numberToText(adaptNumber) + " +1/+1 counter"
+ + (adaptNumber > 1 ? "s" : "") + " on it.)";
}
private AdaptEffect(final AdaptEffect effect) {
@@ -37,7 +39,15 @@ public class AdaptEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Permanent permanent = game.getPermanent(source.getSourceId());
+ // Verify source object did not change zone and is on the battlefield
+ MageObject sourceObject = source.getSourceObjectIfItStillExists(game);
+ if (sourceObject == null) {
+ if (game.getState().getZone(source.getSourceId()).equals(Zone.BATTLEFIELD)
+ && source.getSourceObjectZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(source.getSourceId())) {
+ sourceObject = game.getPermanent(source.getSourceId());
+ }
+ }
+ Permanent permanent = ((Permanent) sourceObject);
if (permanent == null) {
return false;
}
@@ -48,7 +58,8 @@ public class AdaptEffect extends OneShotEffect {
if (game.replaceEvent(event)) {
return false;
}
- if (permanent.getCounters(game).getCount(CounterType.P1P1) == 0 || event.getFlag()) {
+ if (permanent.getCounters(game).getCount(CounterType.P1P1) == 0
+ || event.getFlag()) {
permanent.addCounters(CounterType.P1P1.createInstance(event.getAmount()), source, game);
}
return true;
diff --git a/Mage/src/main/java/mage/abilities/hint/common/PermanentsYouControlHint.java b/Mage/src/main/java/mage/abilities/hint/common/PermanentsYouControlHint.java
new file mode 100644
index 00000000000..cf47e835cd6
--- /dev/null
+++ b/Mage/src/main/java/mage/abilities/hint/common/PermanentsYouControlHint.java
@@ -0,0 +1,26 @@
+package mage.abilities.hint.common;
+
+import mage.abilities.Ability;
+import mage.abilities.dynamicvalue.common.PermanentsYouControlCount;
+import mage.abilities.hint.Hint;
+import mage.abilities.hint.ValueHint;
+import mage.game.Game;
+
+/**
+ * @author JayDi85
+ */
+public enum PermanentsYouControlHint implements Hint {
+
+ instance;
+ private static final Hint hint = new ValueHint("Permanents you control", PermanentsYouControlCount.instance);
+
+ @Override
+ public String getText(Game game, Ability ability) {
+ return hint.getText(game, ability);
+ }
+
+ @Override
+ public Hint copy() {
+ return instance;
+ }
+}
diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java
index 1bb7efb4e42..317bec4adda 100644
--- a/Mage/src/main/java/mage/cards/CardImpl.java
+++ b/Mage/src/main/java/mage/cards/CardImpl.java
@@ -690,27 +690,33 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
sourceId = source.getSourceId();
}
}
- GameEvent countersEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, sourceId, getControllerOrOwner(), counter.getName(), counter.getCount());
- countersEvent.setAppliedEffects(appliedEffects);
- countersEvent.setFlag(isEffect);
- if (!game.replaceEvent(countersEvent)) {
- int amount = countersEvent.getAmount();
+ GameEvent addingAllEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, sourceId, getControllerOrOwner(), counter.getName(), counter.getCount());
+ addingAllEvent.setAppliedEffects(appliedEffects);
+ addingAllEvent.setFlag(isEffect);
+ if (!game.replaceEvent(addingAllEvent)) {
+ int amount = addingAllEvent.getAmount();
+ boolean isEffectFlag = addingAllEvent.getFlag();
int finalAmount = amount;
for (int i = 0; i < amount; i++) {
Counter eventCounter = counter.copy();
eventCounter.remove(eventCounter.getCount() - 1);
- GameEvent event = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTER, objectId, sourceId, getControllerOrOwner(), counter.getName(), 1);
- event.setAppliedEffects(appliedEffects);
- if (!game.replaceEvent(event)) {
+ GameEvent addingOneEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTER, objectId, sourceId, getControllerOrOwner(), counter.getName(), 1);
+ addingOneEvent.setAppliedEffects(appliedEffects);
+ addingOneEvent.setFlag(isEffectFlag);
+ if (!game.replaceEvent(addingOneEvent)) {
getCounters(game).addCounter(eventCounter);
- game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER_ADDED, objectId, sourceId, getControllerOrOwner(), counter.getName(), 1));
+ GameEvent addedOneEvent = GameEvent.getEvent(GameEvent.EventType.COUNTER_ADDED, objectId, sourceId, getControllerOrOwner(), counter.getName(), 1);
+ addedOneEvent.setFlag(addingOneEvent.getFlag());
+ game.fireEvent(addedOneEvent);
} else {
finalAmount--;
returnCode = false;
}
}
if (finalAmount > 0) {
- game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERS_ADDED, objectId, sourceId, getControllerOrOwner(), counter.getName(), amount));
+ GameEvent addedAllEvent = GameEvent.getEvent(GameEvent.EventType.COUNTERS_ADDED, objectId, sourceId, getControllerOrOwner(), counter.getName(), amount);
+ addedAllEvent.setFlag(isEffectFlag);
+ game.fireEvent(addedAllEvent);
}
} else {
returnCode = false;
diff --git a/Mage/src/main/java/mage/cards/decks/exporter/MtgArenaDeckExporter.java b/Mage/src/main/java/mage/cards/decks/exporter/MtgArenaDeckExporter.java
index 220637ecff6..68073ae2ccc 100644
--- a/Mage/src/main/java/mage/cards/decks/exporter/MtgArenaDeckExporter.java
+++ b/Mage/src/main/java/mage/cards/decks/exporter/MtgArenaDeckExporter.java
@@ -1,5 +1,6 @@
package mage.cards.decks.exporter;
+import com.google.common.collect.ImmutableMap;
import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists;
import mage.cards.decks.DeckFileFilter;
@@ -13,9 +14,11 @@ import java.util.*;
*/
public class MtgArenaDeckExporter extends DeckExporter {
- private final String ext = "mtga";
- private final String description = "MTG Arena's deck format (*.mtga)";
- private final FileFilter fileFilter = new DeckFileFilter(ext, description);
+ private static final String ext = "mtga";
+ private static final String description = "MTG Arena's deck format (*.mtga)";
+ private static final FileFilter fileFilter = new DeckFileFilter(ext, description);
+
+ private static final Map SET_CODE_REPLACEMENTS = ImmutableMap.of("DOM", "DAR");
@Override
public void writeDeck(PrintWriter out, DeckCardLists deck) {
@@ -33,7 +36,9 @@ public class MtgArenaDeckExporter extends DeckExporter {
private List prepareCardsList(List sourceCards, Map amount, String prefix) {
List res = new ArrayList<>();
for (DeckCardInfo card : sourceCards) {
- String name = card.getCardName() + " (" + card.getSetCode().toUpperCase(Locale.ENGLISH) + ") " + card.getCardNum();
+ String setCode = card.getSetCode().toUpperCase(Locale.ENGLISH);
+ setCode = SET_CODE_REPLACEMENTS.getOrDefault(setCode, setCode);
+ String name = card.getCardName() + " (" + setCode + ") " + card.getCardNum();
String code = prefix + name;
int curAmount = amount.getOrDefault(code, 0);
if (curAmount == 0) {
diff --git a/Mage/src/main/java/mage/cards/decks/exporter/MtgArenaDeckExporterTest.java b/Mage/src/main/java/mage/cards/decks/exporter/MtgArenaDeckExporterTest.java
index 773a0d19a38..af7666a45d9 100644
--- a/Mage/src/main/java/mage/cards/decks/exporter/MtgArenaDeckExporterTest.java
+++ b/Mage/src/main/java/mage/cards/decks/exporter/MtgArenaDeckExporterTest.java
@@ -22,6 +22,7 @@ public class MtgArenaDeckExporterTest {
deck.getCards().add(new DeckCardInfo("Plains", "2", "RNA", 3));
deck.getCards().add(new DeckCardInfo("Plains", "2", "RNA", 5)); // must combine
deck.getCards().add(new DeckCardInfo("Mountain", "3", "RNA", 1));
+ deck.getCards().add(new DeckCardInfo("Goblin Chainwhirler", "129", "DOM", 4));
deck.getSideboard().add(new DeckCardInfo("Island", "1", "RNA", 2));
deck.getSideboard().add(new DeckCardInfo("Island", "1", "RNA", 5)); // must combine
deck.getSideboard().add(new DeckCardInfo("Mountain", "2", "RNA", 3));
@@ -30,6 +31,7 @@ public class MtgArenaDeckExporterTest {
assertEquals("2 Forest (RNA) 1" + System.lineSeparator() +
"8 Plains (RNA) 2" + System.lineSeparator() +
"1 Mountain (RNA) 3" + System.lineSeparator() +
+ "4 Goblin Chainwhirler (DAR) 129" + System.lineSeparator() +
System.lineSeparator() +
"7 Island (RNA) 1" + System.lineSeparator() +
"3 Mountain (RNA) 2" + System.lineSeparator(),
diff --git a/Mage/src/main/java/mage/filter/common/FilterPermanentOrPlayerWithCounter.java b/Mage/src/main/java/mage/filter/common/FilterPermanentOrPlayerWithCounter.java
index 6f5dfa5dba4..16c0eb36233 100644
--- a/Mage/src/main/java/mage/filter/common/FilterPermanentOrPlayerWithCounter.java
+++ b/Mage/src/main/java/mage/filter/common/FilterPermanentOrPlayerWithCounter.java
@@ -1,13 +1,11 @@
-
-
package mage.filter.common;
+import mage.MageItem;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
-import mage.MageItem;
/**
* @author nantuko
@@ -28,24 +26,24 @@ public class FilterPermanentOrPlayerWithCounter extends FilterPermanentOrPlayer
@Override
public boolean match(MageItem o, Game game) {
- if (o instanceof Player) {
- if (((Player)o).getCounters().isEmpty()) {
- return false;
- }
- } else if (o instanceof Permanent) {
- if (((Permanent)o).getCounters(game).isEmpty()) {
- return false;
+ if (super.match(o, game)) {
+ if (o instanceof Player) {
+ return !((Player) o).getCounters().isEmpty();
+ } else if (o instanceof Permanent) {
+ return !((Permanent) o).getCounters(game).isEmpty();
}
}
- return super.match(o, game);
+ return false;
}
@Override
public boolean match(MageItem o, UUID sourceId, UUID playerId, Game game) {
- if (o instanceof Player) {
- return playerFilter.match((Player) o, sourceId, playerId, game);
- } else if (o instanceof Permanent) {
- return permanentFilter.match((Permanent) o, sourceId, playerId, game);
+ if (super.match(o, sourceId, playerId, game)) {
+ if (o instanceof Player) {
+ return !((Player) o).getCounters().isEmpty();
+ } else if (o instanceof Permanent) {
+ return !((Permanent) o).getCounters(game).isEmpty();
+ }
}
return false;
}
diff --git a/Mage/src/main/java/mage/game/Game.java b/Mage/src/main/java/mage/game/Game.java
index 7ee0bfdcc03..30638c63a1c 100644
--- a/Mage/src/main/java/mage/game/Game.java
+++ b/Mage/src/main/java/mage/game/Game.java
@@ -432,7 +432,7 @@ public interface Game extends MageItem, Serializable {
// game cheats (for tests only)
void cheat(UUID ownerId, Map commands);
- void cheat(UUID ownerId, UUID activePlayerId, List library, List hand, List battlefield, List graveyard);
+ void cheat(UUID ownerId, UUID activePlayerId, List library, List hand, List battlefield, List graveyard, List command);
// controlling the behaviour of replacement effects while permanents entering the battlefield
void setScopeRelevant(boolean scopeRelevant);
diff --git a/Mage/src/main/java/mage/game/GameCommanderImpl.java b/Mage/src/main/java/mage/game/GameCommanderImpl.java
index 96de6b83069..47a6ee79a44 100644
--- a/Mage/src/main/java/mage/game/GameCommanderImpl.java
+++ b/Mage/src/main/java/mage/game/GameCommanderImpl.java
@@ -40,7 +40,6 @@ public abstract class GameCommanderImpl extends GameImpl {
@Override
protected void init(UUID choosingPlayerId) {
- Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
//Move commander to command zone
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
Player player = getPlayer(playerId);
@@ -49,7 +48,7 @@ public abstract class GameCommanderImpl extends GameImpl {
for (UUID commanderId : player.getCommandersIds()) {
Card commander = this.getCard(commanderId);
if (commander != null) {
- initCommander(commander, ability, player);
+ initCommander(commander, player);
}
}
} else {
@@ -57,20 +56,20 @@ public abstract class GameCommanderImpl extends GameImpl {
Card commander = this.getCard(player.getSideboard().iterator().next());
if (commander != null) {
player.addCommanderId(commander.getId());
- initCommander(commander, ability, player);
+ initCommander(commander, player);
}
}
}
}
}
- this.getState().addAbility(ability, null);
super.init(choosingPlayerId);
if (startingPlayerSkipsDraw) {
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
}
}
- private void initCommander(Card commander, Ability ability, Player player) {
+ public void initCommander(Card commander, Player player) {
+ Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
commander.moveToZone(Zone.COMMAND, null, this, true);
commander.getAbilities().setControllerId(player.getId());
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoHand, alsoLibrary));
@@ -79,6 +78,7 @@ public abstract class GameCommanderImpl extends GameImpl {
CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), checkCommanderDamage);
getState().addWatcher(watcher);
watcher.addCardInfoToCommander(this);
+ this.getState().addAbility(ability, null);
}
//20130711
diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java
index 7c6fb4370fc..94772becacb 100644
--- a/Mage/src/main/java/mage/game/GameImpl.java
+++ b/Mage/src/main/java/mage/game/GameImpl.java
@@ -2851,26 +2851,39 @@ public abstract class GameImpl implements Game, Serializable {
}
@Override
- public void cheat(UUID ownerId, UUID activePlayerId, List library, List hand, List battlefield, List graveyard) {
+ public void cheat(UUID ownerId, UUID activePlayerId, List library, List hand, List battlefield, List graveyard, List command) {
Player player = getPlayer(ownerId);
if (player != null) {
loadCards(ownerId, library);
loadCards(ownerId, hand);
loadCards(ownerId, battlefield);
loadCards(ownerId, graveyard);
+ loadCards(ownerId, command);
for (Card card : library) {
player.getLibrary().putOnTop(card, this);
}
+
for (Card card : hand) {
card.setZone(Zone.HAND, this);
player.getHand().add(card);
}
+
for (Card card : graveyard) {
card.setZone(Zone.GRAVEYARD, this);
player.getGraveyard().add(card);
}
+ // as commander (only commander games, look at init code in GameCommanderImpl)
+ if (this instanceof GameCommanderImpl) {
+ for (Card card : command) {
+ player.addCommanderId(card.getId());
+ // no needs in initCommander call -- it's uses on game startup (init)
+ }
+ } else if (!command.isEmpty()) {
+ throw new IllegalArgumentException("Command zone supports in commander test games");
+ }
+
// warning, permanents go to battlefield without resolve, continuus effects must be init
for (PermanentCard permanentCard : battlefield) {
permanentCard.setZone(Zone.BATTLEFIELD, this);
diff --git a/Mage/src/main/java/mage/game/GameTinyLeadersImpl.java b/Mage/src/main/java/mage/game/GameTinyLeadersImpl.java
index 78c7fdb0ec7..48e1efa89ff 100644
--- a/Mage/src/main/java/mage/game/GameTinyLeadersImpl.java
+++ b/Mage/src/main/java/mage/game/GameTinyLeadersImpl.java
@@ -1,9 +1,5 @@
-
package mage.game;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
@@ -21,8 +17,11 @@ import mage.game.turn.TurnMod;
import mage.players.Player;
import mage.watchers.common.CommanderInfoWatcher;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author JRHerlehy
*/
public abstract class GameTinyLeadersImpl extends GameImpl {
@@ -43,7 +42,6 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
@Override
protected void init(UUID choosingPlayerId) {
- Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
//Move tiny leader to command zone
for (UUID playerId : state.getPlayerList(startingPlayerId)) {
Player player = getPlayer(playerId);
@@ -55,6 +53,7 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
this.loadCards(cards, playerId);
player.addCommanderId(commander.getId());
commander.moveToZone(Zone.COMMAND, null, this, true);
+ Ability ability = new SimpleStaticAbility(Zone.COMMAND, new InfoEffect("Commander effects"));
ability.addEffect(new CommanderReplacementEffect(commander.getId(), alsoHand, alsoLibrary));
ability.addEffect(new CommanderCostModification(commander.getId()));
// Commander rule #4 was removed Jan. 18, 2016
@@ -63,13 +62,13 @@ public abstract class GameTinyLeadersImpl extends GameImpl {
CommanderInfoWatcher watcher = new CommanderInfoWatcher(commander.getId(), false);
getState().addWatcher(watcher);
watcher.addCardInfoToCommander(this);
+ this.getState().addAbility(ability, null);
} else {
throw new UnknownError("Commander card could not be created. Name: [" + player.getMatchPlayer().getDeck().getName() + ']');
}
}
}
- this.getState().addAbility(ability, null);
super.init(choosingPlayerId);
if (startingPlayerSkipsDraw) {
state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW));
diff --git a/Mage/src/main/java/mage/game/events/GameEvent.java b/Mage/src/main/java/mage/game/events/GameEvent.java
index 2d20ce98a0e..6d1705abe18 100644
--- a/Mage/src/main/java/mage/game/events/GameEvent.java
+++ b/Mage/src/main/java/mage/game/events/GameEvent.java
@@ -18,6 +18,9 @@ public class GameEvent implements Serializable {
protected UUID sourceId;
protected UUID playerId;
protected int amount;
+ // flags:
+ // for counters: event is result of effect (+1 from planeswalkers is cost, not effect)
+ // for combat damage: event is preventable damage
protected boolean flag;
protected String data;
protected Zone zone;
@@ -433,6 +436,17 @@ public class GameEvent implements Serializable {
this.amount = amount;
}
+ public void setAmountForCounters(int amount, boolean isEffect) {
+ this.amount = amount;
+
+ // cost event must be "transformed" to effect event, as example:
+ // planeswalker's +1 cost will be affected by Pir, Imaginative Rascal (1 + 1) and applied as effect by Doubling Season (2 * 2)
+ // https://github.com/magefree/mage/issues/5802
+ if (isEffect) {
+ setFlag(true);
+ }
+ }
+
public boolean getFlag() {
return flag;
}
diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java
index a76df41f434..725e077df00 100644
--- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java
+++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java
@@ -909,7 +909,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
if (countersToRemove > getCounters(game).getCount(CounterType.LOYALTY)) {
countersToRemove = getCounters(game).getCount(CounterType.LOYALTY);
}
- getCounters(game).removeCounter(CounterType.LOYALTY, countersToRemove);
+ removeCounters(CounterType.LOYALTY.getName(), countersToRemove, game);
game.fireEvent(new DamagedPlaneswalkerEvent(objectId, sourceId, controllerId, actualDamage, combat));
return actualDamage;
}
diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java
index 6e5c31dc3bb..6dc09c8f9dd 100644
--- a/Mage/src/main/java/mage/players/Player.java
+++ b/Mage/src/main/java/mage/players/Player.java
@@ -569,6 +569,7 @@ public interface Player extends MageItem, Copyable {
// set the value for non mana X costs
int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost);
+ // TODO: rework choose replacement effects to use array, not map (it'a random order now)
int chooseReplacementEffect(Map abilityMap, Game game);
TriggeredAbility chooseTriggeredAbility(List abilities, Game game);
diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java
index ee6ac479b7a..9df46c83eae 100644
--- a/Mage/src/main/java/mage/players/PlayerImpl.java
+++ b/Mage/src/main/java/mage/players/PlayerImpl.java
@@ -182,7 +182,6 @@ public abstract class PlayerImpl implements Player, Serializable {
protected final Map silentPhaseSteps = ImmutableMap.builder().
put(PhaseStep.DECLARE_ATTACKERS, Step.StepPart.PRE).build();
-
public PlayerImpl(String name, RangeOfInfluence range) {
this(UUID.randomUUID());
this.name = name;
@@ -611,7 +610,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
if (abilities.containsKey(HexproofAbility.getInstance().getId())) {
if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game)
- && null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, null, this.getId(), game)) {
+ && null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, null, sourceControllerId, game)) {
return false;
}
}
@@ -2011,24 +2010,30 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public boolean addCounters(Counter counter, Game game) {
boolean returnCode = true;
- GameEvent countersEvent = GameEvent.getEvent(EventType.ADD_COUNTERS, playerId, null, playerId, counter.getName(), counter.getCount());
- if (!game.replaceEvent(countersEvent)) {
- int amount = countersEvent.getAmount();
+ GameEvent addingAllEvent = GameEvent.getEvent(EventType.ADD_COUNTERS, playerId, null, playerId, counter.getName(), counter.getCount());
+ if (!game.replaceEvent(addingAllEvent)) {
+ int amount = addingAllEvent.getAmount();
int finalAmount = amount;
+ boolean isEffectFlag = addingAllEvent.getFlag();
for (int i = 0; i < amount; i++) {
Counter eventCounter = counter.copy();
eventCounter.remove(eventCounter.getCount() - 1);
- GameEvent event = GameEvent.getEvent(EventType.ADD_COUNTER, playerId, null, playerId, counter.getName(), 1);
- if (!game.replaceEvent(event)) {
+ GameEvent addingOneEvent = GameEvent.getEvent(EventType.ADD_COUNTER, playerId, null, playerId, counter.getName(), 1);
+ addingOneEvent.setFlag(isEffectFlag);
+ if (!game.replaceEvent(addingOneEvent)) {
getCounters().addCounter(eventCounter);
- game.fireEvent(GameEvent.getEvent(EventType.COUNTER_ADDED, playerId, null, playerId, counter.getName(), 1));
+ GameEvent addedOneEvent = GameEvent.getEvent(EventType.COUNTER_ADDED, playerId, null, playerId, counter.getName(), 1);
+ addedOneEvent.setFlag(addingOneEvent.getFlag());
+ game.fireEvent(addedOneEvent);
} else {
finalAmount--;
returnCode = false;
}
}
if (finalAmount > 0) {
- game.fireEvent(GameEvent.getEvent(EventType.COUNTERS_ADDED, playerId, null, playerId, counter.getName(), amount));
+ GameEvent addedAllEvent = GameEvent.getEvent(EventType.COUNTERS_ADDED, playerId, null, playerId, counter.getName(), amount);
+ addedAllEvent.setFlag(addingAllEvent.getFlag());
+ game.fireEvent(addedAllEvent);
}
} else {
returnCode = false;
diff --git a/Mage/src/main/java/mage/players/StubPlayer.java b/Mage/src/main/java/mage/players/StubPlayer.java
new file mode 100644
index 00000000000..04665fbbc2e
--- /dev/null
+++ b/Mage/src/main/java/mage/players/StubPlayer.java
@@ -0,0 +1,221 @@
+package mage.players;
+
+import mage.MageItem;
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.Modes;
+import mage.abilities.TriggeredAbility;
+import mage.abilities.costs.VariableCost;
+import mage.abilities.costs.mana.ManaCost;
+import mage.cards.Card;
+import mage.cards.Cards;
+import mage.cards.decks.Deck;
+import mage.choices.Choice;
+import mage.constants.Outcome;
+import mage.constants.RangeOfInfluence;
+import mage.game.Game;
+import mage.game.combat.CombatGroup;
+import mage.game.draft.Draft;
+import mage.game.match.Match;
+import mage.game.permanent.Permanent;
+import mage.game.tournament.Tournament;
+import mage.target.Target;
+import mage.target.TargetAmount;
+import mage.target.TargetCard;
+import mage.target.TargetPlayer;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static java.util.stream.Collectors.toList;
+
+public class StubPlayer extends PlayerImpl implements Player {
+
+ public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
+ if (target instanceof TargetPlayer) {
+ for (Player player : game.getPlayers().values()) {
+ if (player.getId().equals(getId()) && target.canTarget(getId(), game)) {
+ target.add(player.getId(), game);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean choose(Outcome outcome, Cards cards, TargetCard target, Game game) {
+ cards.getCards(game).stream().map(MageItem::getId).forEach(cardId -> target.add(cardId, game));
+ return true;
+ }
+
+ @Override
+ public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) {
+ if ("cards to PUT on the BOTTOM of your library (Discard for Mulligan)".equals(target.getFilter().getMessage())) {
+ chooseDiscardBottom(game, target.getMinNumberOfTargets(), cards.getCards(game)
+ .stream().map(MageItem::getId).collect(toList())).forEach(cardId -> target.add(cardId, game));
+ } else {
+ UUID cardId = getOnlyElement(cards.getCards(game)).getId();
+ if (chooseScry(game, cardId)) {
+ target.add(cardId, game);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public List chooseDiscardBottom(Game game, int count, List cardIds) {
+ return cardIds.subList(0, count);
+ }
+
+ public boolean chooseScry(Game game, UUID cardId) {
+ return false;
+ }
+
+ @Override
+ public void shuffleLibrary(Ability source, Game game) {
+
+ }
+
+ public StubPlayer(String name, RangeOfInfluence range) {
+ super(name, range);
+ }
+
+ @Override
+ public void abort() {
+
+ }
+
+ @Override
+ public void skip() {
+
+ }
+
+ @Override
+ public Player copy() {
+ return null;
+ }
+
+ @Override
+ public boolean priority(Game game) {
+ return false;
+ }
+
+ @Override
+ public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map options) {
+ return false;
+ }
+
+ @Override
+ public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
+ return false;
+ }
+
+ @Override
+ public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
+ return false;
+ }
+
+ @Override
+ public boolean chooseMulligan(Game game) {
+ return false;
+ }
+
+ @Override
+ public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) {
+ return false;
+ }
+
+ @Override
+ public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) {
+ return false;
+ }
+
+ @Override
+ public boolean choose(Outcome outcome, Choice choice, Game game) {
+ return false;
+ }
+
+ @Override
+ public boolean choosePile(Outcome outcome, String message, List extends Card> pile1, List extends Card> pile2, Game game) {
+ return false;
+ }
+
+ @Override
+ public boolean playMana(Ability ability, ManaCost unpaid, String promptText, Game game) {
+ return false;
+ }
+
+ @Override
+ public int announceXMana(int min, int max, String message, Game game, Ability ability) {
+ return 0;
+ }
+
+ @Override
+ public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost) {
+ return 0;
+ }
+
+ @Override
+ public int chooseReplacementEffect(Map abilityMap, Game game) {
+ return 0;
+ }
+
+ @Override
+ public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) {
+ return null;
+ }
+
+ @Override
+ public Mode chooseMode(Modes modes, Ability source, Game game) {
+ return null;
+ }
+
+ @Override
+ public void selectAttackers(Game game, UUID attackingPlayerId) {
+
+ }
+
+ @Override
+ public void selectBlockers(Game game, UUID defendingPlayerId) {
+
+ }
+
+ @Override
+ public UUID chooseAttackerOrder(List attacker, Game game) {
+ return null;
+ }
+
+ @Override
+ public UUID chooseBlockerOrder(List blockers, CombatGroup combatGroup, List blockerOrder, Game game) {
+ return null;
+ }
+
+ @Override
+ public void assignDamage(int damage, List targets, String singleTargetName, UUID sourceId, Game game) {
+
+ }
+
+ @Override
+ public int getAmount(int min, int max, String message, Game game) {
+ return 0;
+ }
+
+ @Override
+ public void sideboard(Match match, Deck deck) {
+
+ }
+
+ @Override
+ public void construct(Tournament tournament, Deck deck) {
+
+ }
+
+ @Override
+ public void pickCard(List cards, Deck deck, Draft draft) {
+
+ }
+
+}
\ No newline at end of file
diff --git a/Mage/src/main/java/mage/target/Targets.java b/Mage/src/main/java/mage/target/Targets.java
index 64c67c104a2..7b3af1ca0ca 100644
--- a/Mage/src/main/java/mage/target/Targets.java
+++ b/Mage/src/main/java/mage/target/Targets.java
@@ -66,7 +66,7 @@ public class Targets extends ArrayList {
if (!canChoose(source.getSourceId(), playerId, game)) {
return false;
}
- int state = game.bookmarkState();
+ //int state = game.bookmarkState();
while (!isChosen()) {
Target target = this.getUnchosen().get(0);
UUID targetController = playerId;
@@ -93,7 +93,7 @@ public class Targets extends ArrayList {
// Check if there are some rules for targets are violated, if so reset the targets and start again
if (this.getUnchosen().isEmpty()
&& game.replaceEvent(new GameEvent(GameEvent.EventType.TARGETS_VALID, source.getSourceId(), source.getSourceId(), source.getControllerId()), source)) {
- game.restoreState(state, "Targets");
+ //game.restoreState(state, "Targets");
clearChosen();
}
}
diff --git a/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java b/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java
index ac89c3f5375..20f4fa974e2 100644
--- a/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java
+++ b/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java
@@ -8,23 +8,22 @@ package mage.target.common;
import mage.filter.common.FilterOpponentOrPlaneswalker;
/**
- *
* @author LevelX2
*/
public class TargetOpponentOrPlaneswalker extends TargetPermanentOrPlayer {
public TargetOpponentOrPlaneswalker() {
- this(1, 1, new FilterOpponentOrPlaneswalker("opponent or planeswalker"), false);
- }
-
- public TargetOpponentOrPlaneswalker(int numTargets) {
- this(numTargets, numTargets, new FilterOpponentOrPlaneswalker(), false);
+ this(1);
}
public TargetOpponentOrPlaneswalker(FilterOpponentOrPlaneswalker filter) {
this(1, 1, filter, false);
}
+ public TargetOpponentOrPlaneswalker(int numTargets) {
+ this(numTargets, numTargets, new FilterOpponentOrPlaneswalker("opponent or planeswalker"), false);
+ }
+
public TargetOpponentOrPlaneswalker(int minNumTargets, int maxNumTargets, FilterOpponentOrPlaneswalker filter, boolean notTarget) {
super(minNumTargets, maxNumTargets, filter, notTarget);
}
diff --git a/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayer.java b/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayer.java
index 70dab46b02e..cee4973c4f8 100644
--- a/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayer.java
+++ b/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayer.java
@@ -1,28 +1,26 @@
package mage.target.common;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.constants.Zone;
import mage.filter.Filter;
import mage.filter.FilterPermanent;
-import mage.filter.StaticFilters;
import mage.filter.common.FilterPermanentOrPlayer;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetImpl;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author nantuko
*/
public class TargetPermanentOrPlayer extends TargetImpl {
protected FilterPermanentOrPlayer filter;
- protected FilterPermanent filterPermanent;
public TargetPermanentOrPlayer() {
this(1, 1);
@@ -46,14 +44,12 @@ public class TargetPermanentOrPlayer extends TargetImpl {
this.zone = Zone.ALL;
this.filter = filter;
this.targetName = filter.getMessage();
- this.filterPermanent = this.filter.getPermanentFilter();
this.notTarget = notTarget;
}
public TargetPermanentOrPlayer(final TargetPermanentOrPlayer target) {
super(target);
this.filter = target.filter.copy();
- this.filterPermanent = target.filterPermanent.copy();
}
@Override
@@ -61,10 +57,6 @@ public class TargetPermanentOrPlayer extends TargetImpl {
return filter;
}
- public void setFilter(FilterPermanentOrPlayer filter) {
- this.filter = filter;
- }
-
@Override
public boolean canTarget(UUID id, Game game) {
Permanent permanent = game.getPermanent(id);
@@ -118,7 +110,7 @@ public class TargetPermanentOrPlayer extends TargetImpl {
* {@link mage.players.Player} that can be chosen. Should only be used for
* Ability targets since this checks for protection, shroud etc.
*
- * @param sourceId - the target event source
+ * @param sourceId - the target event source
* @param sourceControllerId - controller of the target event source
* @param game
* @return - true if enough valid {@link mage.game.permanent.Permanent} or
@@ -130,14 +122,14 @@ public class TargetPermanentOrPlayer extends TargetImpl {
MageObject targetSource = game.getObject(sourceId);
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
- if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.getPlayerFilter().match(player, sourceId, sourceControllerId, game)) {
+ if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, sourceId, sourceControllerId, game)) {
count++;
if (count >= this.minNumberOfTargets) {
return true;
}
}
}
- for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT, sourceControllerId, game)) {
+ for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) {
count++;
if (count >= this.minNumberOfTargets) {
@@ -170,7 +162,7 @@ public class TargetPermanentOrPlayer extends TargetImpl {
}
}
}
- for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanent, sourceControllerId, game)) {
+ for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if (filter.match(permanent, null, sourceControllerId, game) && filter.match(permanent, game)) {
count++;
if (count >= this.minNumberOfTargets) {
@@ -187,11 +179,11 @@ public class TargetPermanentOrPlayer extends TargetImpl {
MageObject targetSource = game.getObject(sourceId);
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
- if (player != null && (notTarget || player.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.getPlayerFilter().match(player, sourceId, sourceControllerId, game)) {
+ if (player != null && (notTarget || player.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(player, sourceId, sourceControllerId, game)) {
possibleTargets.add(playerId);
}
}
- for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterPermanent(), sourceControllerId, game)) {
+ for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if ((notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(permanent, sourceId, sourceControllerId, game)) {
possibleTargets.add(permanent.getId());
}
@@ -204,11 +196,11 @@ public class TargetPermanentOrPlayer extends TargetImpl {
Set possibleTargets = new HashSet<>();
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
- if (player != null && filter.getPlayerFilter().match(player, game)) {
+ if (player != null && filter.match(player, game)) {
possibleTargets.add(playerId);
}
}
- for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, sourceControllerId, game)) {
+ for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if (filter.match(permanent, null, sourceControllerId, game)) {
possibleTargets.add(permanent.getId());
}
@@ -237,6 +229,6 @@ public class TargetPermanentOrPlayer extends TargetImpl {
}
public FilterPermanent getFilterPermanent() {
- return filterPermanent.copy();
+ return filter.getPermanentFilter().copy();
}
}
diff --git a/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayerWithCounter.java b/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayerWithCounter.java
deleted file mode 100644
index d6a515991df..00000000000
--- a/Mage/src/main/java/mage/target/common/TargetPermanentOrPlayerWithCounter.java
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-package mage.target.common;
-
-import mage.abilities.Ability;
-import mage.filter.common.FilterPermanentOrPlayerWithCounter;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
-import java.util.UUID;
-import mage.filter.FilterPermanent;
-import mage.filter.predicate.permanent.CounterPredicate;
-
-/**
- *
- * @author nantuko
- */
-public class TargetPermanentOrPlayerWithCounter extends TargetPermanentOrPlayer {
-
- protected final FilterPermanentOrPlayerWithCounter targetFilter;
-
- public TargetPermanentOrPlayerWithCounter() {
- this(1, 1);
- }
-
- public TargetPermanentOrPlayerWithCounter(int numTargets) {
- this(numTargets, numTargets);
- }
-
- public TargetPermanentOrPlayerWithCounter(int minNumTargets, int maxNumTargets) {
- this(minNumTargets, maxNumTargets, false);
- }
-
- public TargetPermanentOrPlayerWithCounter(int minNumTargets, int maxNumTargets, boolean notTarget) {
- super(minNumTargets, maxNumTargets, notTarget);
- this.targetFilter = new FilterPermanentOrPlayerWithCounter();
- this.filterPermanent = new FilterPermanent();
- this.filterPermanent.add(new CounterPredicate(null));
- this.targetName = targetFilter.getMessage();
- }
-
- public TargetPermanentOrPlayerWithCounter(final TargetPermanentOrPlayerWithCounter target) {
- super(target);
- this.targetFilter = target.targetFilter.copy();
- super.setFilter(this.targetFilter);
- }
-
- @Override
- public TargetPermanentOrPlayerWithCounter copy() {
- return new TargetPermanentOrPlayerWithCounter(this);
- }
-
- @Override
- public boolean canTarget(UUID id, Game game) {
- Permanent permanent = game.getPermanent(id);
- if (permanent != null) {
- if (permanent.getCounters(game).isEmpty()) {
- return false;
- }
- }
- Player player = game.getPlayer(id);
- if (player != null) {
- if (player.getCounters().isEmpty()) {
- return false;
- }
- }
- return super.canTarget(id, game);
- }
-
- @Override
- public boolean canTarget(UUID id, Ability source, Game game) {
- Permanent permanent = game.getPermanent(id);
- if (permanent != null) {
- if (permanent.getCounters(game).isEmpty()) {
- return false;
- }
- }
- Player player = game.getPlayer(id);
- if (player != null) {
- if (player.getCounters().isEmpty()) {
- return false;
- }
- }
- return super.canTarget(id, source, game);
- }
-
-}
diff --git a/Mage/src/main/java/mage/watchers/common/DragonOnTheBattlefieldWhileSpellWasCastWatcher.java b/Mage/src/main/java/mage/watchers/common/DragonOnTheBattlefieldWhileSpellWasCastWatcher.java
index 66a0b24ce0c..e138db27876 100644
--- a/Mage/src/main/java/mage/watchers/common/DragonOnTheBattlefieldWhileSpellWasCastWatcher.java
+++ b/Mage/src/main/java/mage/watchers/common/DragonOnTheBattlefieldWhileSpellWasCastWatcher.java
@@ -37,10 +37,12 @@ public class DragonOnTheBattlefieldWhileSpellWasCastWatcher extends Watcher {
// revealed a Dragon card or controlled a Dragon as you cast the spell
if (spell != null) {
boolean revealedOrOnBattlefield = false;
- for (Cost cost : spell.getSpellAbility().getCosts()) {
- if (cost instanceof RevealTargetFromHandCost) {
- revealedOrOnBattlefield = ((RevealTargetFromHandCost) cost).getNumberRevealedCards() > 0;
- break;
+ if (spell.getSpellAbility() != null) {
+ for (Cost cost : spell.getSpellAbility().getCosts()) {
+ if (cost instanceof RevealTargetFromHandCost) {
+ revealedOrOnBattlefield = ((RevealTargetFromHandCost) cost).getNumberRevealedCards() > 0;
+ break;
+ }
}
}
if (!revealedOrOnBattlefield) {