Merge pull request #4 from magefree/master

sync versions
This commit is contained in:
Oleg Agafonov 2017-11-18 21:38:05 +04:00 committed by GitHub
commit fcc7b63547
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
58 changed files with 3538 additions and 83 deletions

2
.gitignore vendored
View file

@ -4,7 +4,7 @@ syntax: glob
Mage.Client/*.dck
Mage.Client/db
Mage.Client/gamelogs
Mage.Client/mageclient.log
Mage.Client/*.log
Mage.Client/plugins/images
Mage.Client/plugins/plugin.data
Mage.Client/target

View file

@ -562,7 +562,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
}
@Override
public void setTextOffset(int yOffset) {
public void setCardCaptionTopOffset(int yOffsetPercent) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

View file

@ -53,7 +53,7 @@ public class CardArea extends JPanel implements MouseListener {
private boolean reloaded = false;
private final javax.swing.JLayeredPane cardArea;
private final javax.swing.JScrollPane scrollPane;
private int yTextOffset;
private int yCardCaptionOffsetPercent = 0; // card caption offset (use for moving card caption view center, below mana icons -- for more good UI)
private Dimension cardDimension;
private int verticalCardOffset;
@ -68,8 +68,6 @@ public class CardArea extends JPanel implements MouseListener {
setGUISize();
cardArea = new JLayeredPane();
scrollPane.setViewportView(cardArea);
yTextOffset = 10;
}
public void cleanUp() {
@ -103,10 +101,10 @@ public class CardArea extends JPanel implements MouseListener {
this.reloaded = true;
cardArea.removeAll();
if (showCards != null && showCards.size() < 10) {
yTextOffset = 10;
yCardCaptionOffsetPercent = 8; // TODO: need to test
loadCardsFew(showCards, bigCard, gameId);
} else {
yTextOffset = 0;
yCardCaptionOffsetPercent = 0;
loadCardsMany(showCards, bigCard, gameId);
}
cardArea.revalidate();
@ -118,8 +116,10 @@ public class CardArea extends JPanel implements MouseListener {
public void loadCardsNarrow(CardsView showCards, BigCard bigCard, UUID gameId) {
this.reloaded = true;
cardArea.removeAll();
yTextOffset = 0;
yCardCaptionOffsetPercent = 0; // TODO: need to test
loadCardsMany(showCards, bigCard, gameId);
cardArea.revalidate();
this.revalidate();
@ -152,7 +152,10 @@ public class CardArea extends JPanel implements MouseListener {
cardArea.moveToFront(cardPanel);
cardPanel.update(card);
cardPanel.setCardBounds(rectangle.x, rectangle.y, cardDimension.width, cardDimension.height);
cardPanel.setTextOffset(yTextOffset);
// new card have same settings as current view
cardPanel.setCardCaptionTopOffset(yCardCaptionOffsetPercent);
cardPanel.showCardTitle();
}

View file

@ -1726,7 +1726,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
// Create the card view
final MageCard cardPanel = Plugins.instance.getMageCard(card, lastBigCard, new Dimension(getCardWidth(), getCardHeight()), null, true, true);
cardPanel.update(card);
cardPanel.setTextOffset(0);
cardPanel.setCardCaptionTopOffset(0);
// Remove mouse wheel listeners so that scrolling works
// Scrolling works on all areas without cards or by using the scroll bar, that's enough

View file

@ -236,6 +236,7 @@ public class MageBook extends JComponent {
for (int i = 0; i < Math.min(conf.CARDS_PER_PAGE / 2, size); i++) {
Card card = cards.get(i).getMockCard();
addCard(new CardView(card), bigCard, null, rectangle);
rectangle = CardPosition.translatePosition(i, rectangle, conf);
}
@ -341,6 +342,8 @@ public class MageBook extends JComponent {
cardImg.update(card);
cardImg.setCardBounds(rectangle.x, rectangle.y, cardDimensions.frameWidth, cardDimensions.frameHeight);
cardImg.setCardCaptionTopOffset(8); // card caption below real card caption to see full name even with mana icons
boolean implemented = card.getRarity() != Rarity.NA;
GlowText label = new GlowText();

View file

@ -91,7 +91,8 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
private JPanel cardArea;
private int yTextOffset = 10;
// default offset, e.g. for battlefield
private int yCardCaptionOffsetPercent = 8; // card caption offset (use for moving card caption view center, below mana icons -- for more good UI)
// if this is set, it's opened if the user right clicks on the card panel
private JPopupMenu popupMenu;
@ -819,12 +820,12 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
}
@Override
public void setTextOffset(int yOffset) {
yTextOffset = yOffset;
public void setCardCaptionTopOffset(int yOffsetPercent) {
yCardCaptionOffsetPercent = yOffsetPercent;
}
public int getTextOffset() {
return yTextOffset;
public int getCardCaptionTopOffset() {
return yCardCaptionOffsetPercent;
}
@Override

View file

@ -34,7 +34,7 @@ import static org.mage.plugins.card.constants.Constants.THUMBNAIL_SIZE_FULL;
* Class for drawing the mage card object by using a form based JComponent
* approach
*
* @author arcane, nantuko, noxx, stravant
* @author arcane, nantuko, noxx, stravant, JayDi85
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class CardPanelComponentImpl extends CardPanel {
@ -47,9 +47,14 @@ public class CardPanelComponentImpl extends CardPanel {
private static final float ROUNDED_CORNER_SIZE = 0.1f;
private static final float BLACK_BORDER_SIZE = 0.03f;
private static final float SELECTION_BORDER_SIZE = 0.03f;
private static final int TEXT_GLOW_SIZE = 6;
private static final float TEXT_GLOW_INTENSITY = 3f;
// size to show icons and text (help to see full size card without text)
private static final int CARD_MIN_SIZE_FOR_ICONS = 60;
private static final int CARD_MAX_SIZE_FOR_ICONS = 200;
public final ScaledImagePanel imagePanel;
public ImagePanel overlayPanel;
@ -177,6 +182,34 @@ public class CardPanelComponentImpl extends CardPanel {
IMAGE_CACHE = ImageCaches.register(new MapMaker().softValues().makeComputingMap((Function<Key, BufferedImage>) key -> createImage(key)));
}
static private boolean canShowCardIcons(int cardFullWidth, boolean cardHasImage){
// cards without images show icons and text always
// TODO: apply "card names on card" setting to icon too?
// TODO: fix card min-max size to hide (compare to settings size, not direct 60 and 200)
return ((cardFullWidth > 60) && (cardFullWidth < 200)) || (!cardHasImage);
}
private static class CardSizes{
Rectangle rectFull;
Rectangle rectSelection;
Rectangle rectBorder;
Rectangle rectCard;
CardSizes(int offsetX, int offsetY, int fullWidth, int fullHeight){
int realBorderSizeX = Math.round(fullWidth * BLACK_BORDER_SIZE);
int realBorderSizeY = Math.round(fullWidth * BLACK_BORDER_SIZE);
int realSelectionSizeX = Math.round(fullWidth * SELECTION_BORDER_SIZE);
int realSelectionSizeY = Math.round(fullWidth * SELECTION_BORDER_SIZE);
// card full size = select border + black border + real card
rectFull = new Rectangle(offsetX, offsetY, fullWidth, fullHeight);
rectSelection = new Rectangle(rectFull.x, rectFull.y, rectFull.width, rectFull.height);
rectBorder = new Rectangle(rectSelection.x + realSelectionSizeX, rectSelection.y + realSelectionSizeY, rectSelection.width - 2 * realSelectionSizeX, rectSelection.height - 2 * realSelectionSizeY);
rectCard = new Rectangle(rectBorder.x + realBorderSizeX, rectBorder.y + realBorderSizeY, rectBorder.width - 2 * realBorderSizeX, rectBorder.height - 2 * realBorderSizeY);
}
}
public CardPanelComponentImpl(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) {
// Call to super
super(newGameCard, gameId, loadImage, callback, foil, dimension);
@ -368,32 +401,45 @@ public class CardPanelComponentImpl extends CardPanel {
Graphics2D g2d = image.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (!key.hasImage) {
g2d.setColor(new Color(30, 200, 200, 120));
} else {
g2d.setColor(new Color(0, 0, 0, 0));
}
// card full size = select border + black border + real card
CardSizes sizes = new CardSizes(cardXOffset, cardYOffset, cardWidth, cardHeight);
int cornerSize = Math.max(4, Math.round(cardWidth * ROUNDED_CORNER_SIZE));
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
// corners for selection and for border
int cornerSizeSelection = Math.max(4, Math.round(sizes.rectSelection.width * ROUNDED_CORNER_SIZE));
int cornerSizeBorder = Math.max(4, Math.round(sizes.rectBorder.width * ROUNDED_CORNER_SIZE));
// DRAW ORDER from big to small: select -> select info -> border -> card
// draw selection
if (key.isSelected) {
g2d.setColor(Color.green);
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
g2d.fillRoundRect(sizes.rectSelection.x + 1, sizes.rectSelection.y + 1, sizes.rectSelection.width - 2, sizes.rectSelection.height - 2, cornerSizeSelection, cornerSizeSelection);
} else if (key.isChoosable) {
g2d.setColor(new Color(250, 250, 0, 230));
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
g2d.fillRoundRect(sizes.rectSelection.x + 1, sizes.rectSelection.y + 1, sizes.rectSelection.width - 2, sizes.rectSelection.height - 2, cornerSizeSelection, cornerSizeSelection);
} else if (key.isPlayable) {
g2d.setColor(new Color(153, 102, 204, 200));
//g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
g2d.fillRoundRect(cardXOffset, cardYOffset, cardWidth, cardHeight, cornerSize, cornerSize);
g2d.fillRoundRect(sizes.rectSelection.x, sizes.rectSelection.y, sizes.rectSelection.width, sizes.rectSelection.height, cornerSizeSelection, cornerSizeSelection);
}
// draw empty card with border
if (!key.hasImage) {
// gray 1 px border
g2d.setColor(new Color(125, 125, 125, 255));
g2d.fillRoundRect(sizes.rectBorder.x, sizes.rectBorder.y, sizes.rectBorder.width, sizes.rectBorder.height, cornerSizeBorder, cornerSizeBorder);
// color plate
g2d.setColor(new Color(30, 200, 200, 200));
g2d.fillRoundRect(sizes.rectBorder.x + 1, sizes.rectBorder.y + 1, sizes.rectBorder.width - 2, sizes.rectBorder.height - 2, cornerSizeBorder, cornerSizeBorder);
}
// draw attack border (inner part of selection)
if (key.canAttack) {
g2d.setColor(new Color(0, 0, 255, 230));
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
g2d.fillRoundRect(sizes.rectBorder.x + 1, sizes.rectBorder.y + 1, sizes.rectBorder.width - 2, sizes.rectBorder.height - 2, cornerSizeBorder, cornerSizeBorder);
}
// draw real card by component (see imagePanel and other layout's items)
//TODO:uncomment
/*
if (gameCard.isAttacking()) {
@ -409,18 +455,54 @@ public class CardPanelComponentImpl extends CardPanel {
protected void paintChildren(Graphics g) {
super.paintChildren(g);
if (getShowCastingCost() && !isAnimationPanel() && getCardWidth() < 200 && getCardWidth() > 60) {
CardSizes realCard = new CardSizes(getCardXOffset(), getCardYOffset(), getCardWidth(), getCardHeight());
/*
// draw recs for debug
// full card
g.setColor(new Color(255, 0, 0));
g.drawRect(realCard.rectFull.x, realCard.rectFull.y, realCard.rectFull.width, realCard.rectFull.height);
// real card - image
g.setColor(new Color(0, 0, 255));
g.drawRect(imagePanel.getX(), imagePanel.getY(), imagePanel.getBounds().width, imagePanel.getBounds().height);
// caption
g.setColor(new Color(0, 255, 255));
g.drawRect(titleText.getX(), titleText.getY(), titleText.getBounds().width, titleText.getBounds().height);
// life points
g.setColor(new Color(120, 0, 120));
g.drawRect(ptText.getX(), ptText.getY(), ptText.getBounds().width, ptText.getBounds().height);
//*/
if (getShowCastingCost() && !isAnimationPanel() && canShowCardIcons(getCardWidth(), hasImage)) {
String manaCost = ManaSymbols.getStringManaCost(gameCard.getManaCost());
int width = getWidth(manaCost);
int manaWidth = getManaWidth(manaCost);
// right top corner with margin (sizes from any sample card, length from black border to mana icon)
int manaMarginRight = Math.round(22f / 672f * getCardWidth());
int manaMarginTop = Math.round(24f / 936f * getCardHeight());
int manaX = getCardXOffset() + getCardWidth() - manaMarginRight - manaWidth;
int manaY = getCardYOffset() + manaMarginTop;
if (hasImage) {
ManaSymbols.draw(g, manaCost, getCardXOffset() + getCardWidth() - width - 5, getCardYOffset() + 5, getSymbolWidth());
// top right corner if have image like real card
ManaSymbols.draw(g, manaCost, manaX, manaY, getSymbolWidth());
} else {
ManaSymbols.draw(g, manaCost, getCardXOffset() + 8, getCardHeight() - 9, getSymbolWidth());
// old version - bottom left corner if haven't card
// ManaSymbols.draw(g, manaCost, getCardXOffset() + manaMarginRight, getCardYOffset() + getCardHeight() - manaMarginTop - getSymbolWidth(), getSymbolWidth());
// new version - like a normal image (it's best to view and construct decks)
ManaSymbols.draw(g, manaCost, manaX, manaY, getSymbolWidth());
}
}
}
private int getWidth(String manaCost) {
private int getManaWidth(String manaCost) {
int width = 0;
manaCost = manaCost.replace("\\", "");
StringTokenizer tok = new StringTokenizer(manaCost, " ");
@ -439,24 +521,28 @@ public class CardPanelComponentImpl extends CardPanel {
int cardHeight = getCardHeight();
int cardXOffset = getCardXOffset();
int cardYOffset = getCardYOffset();
int borderSize = Math.round(cardWidth * BLACK_BORDER_SIZE);
imagePanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
imagePanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
CardSizes sizes = new CardSizes(cardXOffset, cardYOffset, cardWidth, cardHeight);
// origin card without selection
Rectangle realCardSize = sizes.rectBorder;
imagePanel.setLocation(realCardSize.x, realCardSize.y);
imagePanel.setSize(realCardSize.width, realCardSize.height);
if (hasSickness() && gameCard.isCreature() && isPermanent()) {
overlayPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
overlayPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
overlayPanel.setLocation(realCardSize.x, realCardSize.y);
overlayPanel.setSize(realCardSize.width, realCardSize.height);
} else {
overlayPanel.setVisible(false);
}
if (iconPanel != null) {
iconPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
iconPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
iconPanel.setLocation(realCardSize.x, realCardSize.y);
iconPanel.setSize(realCardSize.width, realCardSize.height);
}
if (counterPanel != null) {
counterPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize);
counterPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2);
counterPanel.setLocation(realCardSize.x, realCardSize.y);
counterPanel.setSize(realCardSize.width, realCardSize.height);
int size = cardWidth > WIDTH_LIMIT ? 40 : 20;
minusCounterLabel.setLocation(counterPanel.getWidth() - size, counterPanel.getHeight() - size * 2);
@ -472,32 +558,52 @@ public class CardPanelComponentImpl extends CardPanel {
otherCounterLabel.setSize(size, size);
}
int fontHeight = Math.round(cardHeight * (27f / 680));
boolean showText = (!isAnimationPanel() && fontHeight < 12);
// TITLE
//old version - text hide on small fonts, why?
//int fontHeight = Math.round(cardHeight * (26f / 672));
//boolean showText = (!isAnimationPanel() && fontHeight < 12);
boolean showText = !isAnimationPanel() && canShowCardIcons(cardWidth, hasImage);
titleText.setVisible(showText);
ptText.setVisible(showText);
fullImageText.setVisible(fullImagePath != null);
if (showText) {
int fontSize = cardHeight / 11;
int fontSize = cardHeight / 13; // startup font size (it same size on all zoom levels)
titleText.setFont(getFont().deriveFont(Font.BOLD, fontSize));
int titleX = Math.round(cardWidth * (20f / 480));
int titleY = Math.round(cardHeight * (9f / 680)) + getTextOffset();
titleText.setBounds(cardXOffset + titleX, cardYOffset + titleY, cardWidth - titleX, cardHeight - titleY);
// margins from card black border to text, not need? text show up good without margins
int titleMarginLeft = 0; //Math.round(28f / 672f * cardWidth);
int titleMarginRight = 0;
int titleMarginTop = 0 + Math.round(getCardCaptionTopOffset() / 100f * cardHeight);//Math.round(28f / 936f * cardHeight);
int titleMarginBottom = 0;
titleText.setBounds(
imagePanel.getX() + titleMarginLeft,
imagePanel.getY() + titleMarginTop,
imagePanel.getBounds().width - titleMarginLeft - titleMarginRight,
imagePanel.getBounds().height - titleMarginTop - titleMarginBottom
);
fullImageText.setFont(getFont().deriveFont(Font.PLAIN, 10));
fullImageText.setBounds(cardXOffset, cardYOffset + titleY, cardWidth, cardHeight - titleY);
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);
int ptX = Math.round(cardWidth * (420f / 480)) - ptSize.width / 2;
int ptY = Math.round(cardHeight * (675f / 680)) - ptSize.height;
int offsetX = Math.round((CARD_SIZE_FULL.width - cardWidth) / 10.0f);
// right bottom corner with margin (sizes from any sample card)
int ptMarginRight = Math.round(64f / 672f * cardWidth);
int ptMarginBottom = Math.round(62f / 936f * cardHeight);
ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);
int ptX = cardXOffset + cardWidth - ptMarginRight - ptSize.width;
int ptY = cardYOffset + cardHeight - ptMarginBottom - ptSize.height;
ptText.setLocation(ptX, ptY);
// old version was with TEXT_GLOW_SIZE
//ptText.setLocation(cardXOffset + ptX - TEXT_GLOW_SIZE / 2 - offsetX, cardYOffset + ptY - TEXT_GLOW_SIZE / 2);
}
}
@ -581,7 +687,7 @@ public class CardPanelComponentImpl extends CardPanel {
} else if (this.gameCard instanceof StackAbilityView) {
return ImageCache.getMorphImage();
} else {
return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename));
return ImageCache.getCardbackImage();
}
}

View file

@ -410,7 +410,7 @@ public class CardPanelRenderImpl extends CardPanel {
} else if (this.gameCard instanceof StackAbilityView) {
return ImageCache.getMorphImage();
} else {
return ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename));
return ImageCache.getCardbackImage();
}
}

View file

@ -3,7 +3,9 @@ package org.mage.plugins.card.images;
import com.google.common.base.Function;
import com.google.common.collect.ComputationException;
import com.google.common.collect.MapMaker;
import java.awt.Graphics2D;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
@ -82,12 +84,14 @@ public final class ImageCache {
CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor);
boolean cardback = false;
String path;
if (collectorId.isEmpty() || "0".equals(collectorId)) {
info.setToken(true);
path = CardImageUtils.generateTokenImagePath(info);
if (path == null) {
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename;
cardback = true;
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename; // TODO: replace empty token by other default card, not cardback
}
} else {
path = CardImageUtils.generateImagePath(info);
@ -102,6 +106,7 @@ public final class ImageCache {
}
if (thumbnail && path.endsWith(".jpg")) {
// need thumbnail image
String thumbnailPath = buildThumbnailPath(path);
TFile thumbnailFile = null;
try {
@ -119,19 +124,35 @@ public final class ImageCache {
if (exists) {
LOGGER.debug("loading thumbnail for " + key + ", path=" + thumbnailPath);
BufferedImage thumbnailImage = loadImage(thumbnailFile);
if (thumbnailImage == null) { // thumbnail exists but broken for some reason
LOGGER.warn("failed loading thumbnail for " + key + ", path=" + thumbnailPath
+ ", thumbnail file is probably broken, attempting to recreate it...");
thumbnailImage = makeThumbnailByFile(key, file, thumbnailPath);
}
if (cardback){
// unknown tokens on opponent desk
thumbnailImage = getRoundCorner(thumbnailImage);
}
return thumbnailImage;
} else {
return makeThumbnailByFile(key, file, thumbnailPath);
}
} else {
BufferedImage image = loadImage(file);
image = getWizardsCard(image);
return image;
if (cardback){
// need cardback image
BufferedImage image = loadImage(file);
image = getRoundCorner(image);
return image;
}else {
// need normal card image
BufferedImage image = loadImage(file);
image = getWizardsCard(image);
image = getRoundCorner(image);
return image;
}
}
} else {
throw new RuntimeException(
@ -149,6 +170,7 @@ public final class ImageCache {
public BufferedImage makeThumbnailByFile(String key, TFile file, String thumbnailPath) {
BufferedImage image = loadImage(file);
image = getWizardsCard(image);
image = getRoundCorner(image);
if (image == null) {
return null;
}
@ -239,7 +261,7 @@ public final class ImageCache {
info.setToken(true);
path = CardImageUtils.generateFullTokenImagePath(info);
if (path == null) {
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename;
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename; // TODO: replace empty token by other default card, not cardback
}
} else {
path = CardImageUtils.generateImagePath(info);
@ -257,6 +279,12 @@ public final class ImageCache {
private ImageCache() {
}
public static BufferedImage getCardbackImage() {
BufferedImage image = ImageCache.loadImage(new TFile(DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename));
image = getRoundCorner(image);
return image;
}
public static BufferedImage getMorphImage() {
CardDownloadData info = new CardDownloadData("Morph", "KTK", "0", false, 0, "KTK", "");
info.setToken(true);
@ -265,7 +293,10 @@ public final class ImageCache {
return null;
}
TFile file = getTFile(path);
return loadImage(file);
BufferedImage image = loadImage(file);
image = getRoundCorner(image);
return image;
}
public static BufferedImage getManifestImage() {
@ -276,7 +307,10 @@ public final class ImageCache {
return null;
}
TFile file = getTFile(path);
return loadImage(file);
BufferedImage image = loadImage(file);
image = getRoundCorner(image);
return image;
}
private static String buildThumbnailPath(String path) {
@ -289,6 +323,32 @@ public final class ImageCache {
return thumbnailPath;
}
public static BufferedImage getRoundCorner(BufferedImage image){
if (image != null) {
BufferedImage cornerImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
// corner
float ROUNDED_CORNER_SIZE = 0.15f; // see CardPanelComponentImpl
int cornerSizeBorder = Math.max(4, Math.round(image.getWidth() * ROUNDED_CORNER_SIZE));
// corner mask
Graphics2D gg = cornerImage.createGraphics();
gg.setComposite(AlphaComposite.Src);
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gg.setColor(Color.white);
gg.fill(new RoundRectangle2D.Float(0, 0, cornerImage.getWidth(), cornerImage.getHeight(), cornerSizeBorder, cornerSizeBorder));
// image draw to buffer
gg.setComposite(AlphaComposite.SrcAtop);
gg.drawImage(image, 0, 0, null);
//gg.dispose();
return cornerImage;
} else {
return image;
}
}
public static BufferedImage getWizardsCard(BufferedImage image) {
if (image != null && image.getWidth() == 265 && image.getHeight() == 370) {
BufferedImage crop = new BufferedImage(256, 360, BufferedImage.TYPE_INT_RGB);
@ -404,6 +464,7 @@ public final class ImageCache {
// return alternateName + "#" + card.getExpansionSetCode() + "#" +card.getType()+ "#" + card.getCardNumber() + "#"
// + (card.getTokenSetCode() == null ? "":card.getTokenSetCode());
// }
/**
* Load image from file
*

View file

@ -25,8 +25,8 @@ public abstract class MageCard extends JPanel {
public abstract CardView getOriginal();
// sets the vertical text offset for the card name on the image
public abstract void setTextOffset(int yOffset);
// sets the vertical text offset for the card name on the image, use to move caption to card center
public abstract void setCardCaptionTopOffset(int yOffsetPercent);
public abstract void setCardBounds(int x, int y, int width, int height);

View file

@ -0,0 +1,110 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.game.Game;
import mage.game.events.DamagePlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
/**
*
* @author L_J
*/
public class AlAbarasCarpet extends CardImpl {
public AlAbarasCarpet(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
// {5}, {T}: Prevent all damage that would be dealt to you this turn by attacking creatures without flying.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AlAbarasCarpetEffect(), new GenericManaCost(5));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
public AlAbarasCarpet(final AlAbarasCarpet card) {
super(card);
}
@Override
public AlAbarasCarpet copy() {
return new AlAbarasCarpet(this);
}
}
class AlAbarasCarpetEffect extends PreventionEffectImpl {
private static final FilterAttackingCreature filter = new FilterAttackingCreature();
static {
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
}
AlAbarasCarpetEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
staticText = "Prevent all damage that would be dealt to you this turn by attacking creatures without flying";
}
AlAbarasCarpetEffect(final AlAbarasCarpetEffect effect) {
super(effect);
}
@Override
public AlAbarasCarpetEffect copy() {
return new AlAbarasCarpetEffect(this);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (super.applies(event, source, game) && event instanceof DamagePlayerEvent && event.getAmount() > 0) {
DamagePlayerEvent damageEvent = (DamagePlayerEvent) event;
if (event.getTargetId().equals(source.getControllerId())) {
Permanent permanent = game.getPermanentOrLKIBattlefield(damageEvent.getSourceId());
if (permanent != null && filter.match(permanent, game)) {
return true;
}
}
}
return false;
}
}

View file

@ -0,0 +1,121 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
/**
*
* @author emerald000 & L_J
*/
public class AnuridScavenger extends CardImpl {
public AnuridScavenger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
this.subtype.add(SubType.FROG);
this.subtype.add(SubType.BEAST);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Protection from black
this.addAbility(ProtectionAbility.from(ObjectColor.BLACK));
// At the beginning of your upkeep, sacrifice Anurid Scavenger unless you put a card from your graveyard on the bottom of your library.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new AnuridScavengerCost()), TargetController.YOU, false));
}
public AnuridScavenger(final AnuridScavenger card) {
super(card);
}
@Override
public AnuridScavenger copy() {
return new AnuridScavenger(this);
}
}
class AnuridScavengerCost extends CostImpl {
AnuridScavengerCost() {
this.addTarget(new TargetCardInYourGraveyard(1, 1, new FilterCard()));
this.text = "put a card from your graveyard on the bottom of your library";
}
AnuridScavengerCost(final AnuridScavengerCost cost) {
super(cost);
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
if (targets.choose(Outcome.Removal, controllerId, sourceId, game)) {
for (UUID targetId: targets.get(0).getTargets()) {
Card card = game.getCard(targetId);
if (card == null || game.getState().getZone(targetId) != Zone.GRAVEYARD) {
return false;
}
paid |= controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.GRAVEYARD, false, true);
}
}
}
return paid;
}
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
return targets.canChoose(controllerId, game);
}
@Override
public AnuridScavengerCost copy() {
return new AnuridScavengerCost(this);
}
}

View file

@ -0,0 +1,161 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.b;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.condition.common.IsStepCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.RemoveFromCombatTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.common.FilterBlockingCreature;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetAttackingCreature;
import mage.watchers.common.BlockedByOnlyOneCreatureThisCombatWatcher;
/**
*
* @author L_J
*/
public class BalduvianWarlord extends CardImpl {
public BalduvianWarlord(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.BARBARIAN);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// {T}: Remove target blocking creature from combat. Creatures it was blocking that hadn't become blocked by another creature this combat become unblocked, then it blocks an attacking creature of your choice. Activate this ability only during the declare blockers step.
Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new BalduvianWarlordUnblockEffect(), new TapSourceCost(), new IsStepCondition(PhaseStep.DECLARE_BLOCKERS, false));
ability.addTarget(new TargetPermanent(new FilterBlockingCreature()));
this.addAbility(ability, new BlockedByOnlyOneCreatureThisCombatWatcher());
}
public BalduvianWarlord(final BalduvianWarlord card) {
super(card);
}
@Override
public BalduvianWarlord copy() {
return new BalduvianWarlord(this);
}
}
class BalduvianWarlordUnblockEffect extends OneShotEffect {
public BalduvianWarlordUnblockEffect() {
super(Outcome.Benefit);
this.staticText = " Remove target blocking creature from combat. Creatures it was blocking that hadn't become blocked by another creature this combat become unblocked, then it blocks an attacking creature of your choice";
}
public BalduvianWarlordUnblockEffect(final BalduvianWarlordUnblockEffect effect) {
super(effect);
}
@Override
public BalduvianWarlordUnblockEffect copy() {
return new BalduvianWarlordUnblockEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getTargets().getFirstTarget());
if (controller != null && permanent != null) {
// Remove target creature from combat
Effect effect = new RemoveFromCombatTargetEffect();
effect.apply(game, source);
// Make blocked creatures unblocked
BlockedByOnlyOneCreatureThisCombatWatcher watcher = (BlockedByOnlyOneCreatureThisCombatWatcher) game.getState().getWatchers().get(BlockedByOnlyOneCreatureThisCombatWatcher.class.getSimpleName());
if (watcher != null) {
Set<CombatGroup> combatGroups = watcher.getBlockedOnlyByCreature(permanent.getId());
if (combatGroups != null) {
for (CombatGroup combatGroup : combatGroups) {
if (combatGroup != null) {
combatGroup.setBlocked(false);
}
}
}
}
// Choose new creature to block
if (permanent.isCreature()) {
TargetAttackingCreature target = new TargetAttackingCreature(1, 1, new FilterAttackingCreature(), true);
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) {
controller.chooseTarget(outcome, target, source, game);
}
} else {
return true;
}
Permanent chosenPermanent = game.getPermanent(target.getFirstTarget());
if (chosenPermanent != null && permanent != null && chosenPermanent.isCreature() && controller != null) {
CombatGroup chosenGroup = game.getCombat().findGroup(chosenPermanent.getId());
if (chosenGroup != null) {
// Relevant ruling for Balduvian Warlord:
// 7/15/2006 If an attacking creature has an ability that triggers When this creature becomes blocked,
// it triggers when a creature blocks it due to the Warlords ability only if it was unblocked at that point.
boolean notYetBlocked = true;
if (!chosenGroup.getBlockers().isEmpty()) {
notYetBlocked = false;
}
chosenGroup.addBlocker(permanent.getId(), controller.getId(), game);
if (notYetBlocked) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, chosenPermanent.getId(), null));
}
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, chosenPermanent.getId(), permanent.getId(), permanent.getControllerId()));
}
}
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,146 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.d;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BecomesColorTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.ChoiceColor;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class DreamCoat extends CardImpl {
public DreamCoat(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Neutral));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// {0}: Enchanted creature becomes the color or colors of your choice. Activate this ability only once each turn.
this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new BecomesColorOrColorsEnchantedEffect(), new GenericManaCost(0), 1));
}
public DreamCoat(final DreamCoat card) {
super(card);
}
@Override
public DreamCoat copy() {
return new DreamCoat(this);
}
}
class BecomesColorOrColorsEnchantedEffect extends OneShotEffect {
public BecomesColorOrColorsEnchantedEffect() {
super(Outcome.Neutral);
this.staticText = "Enchanted creature becomes the color or colors of your choice";
}
public BecomesColorOrColorsEnchantedEffect(final BecomesColorOrColorsEnchantedEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId());
Permanent permanent = game.getPermanent(enchantment.getAttachedTo());
StringBuilder sb = new StringBuilder();
if (controller != null && enchantment != null && permanent != null) {
for (int i = 0; i < 5; i++) {
if (i > 0) {
if (!controller.chooseUse(Outcome.Neutral, "Do you wish to choose another color?", source, game)) {
break;
}
}
ChoiceColor choiceColor = new ChoiceColor();
controller.choose(Outcome.Benefit, choiceColor, game);
if (!controller.canRespond()) {
return false;
}
if (!game.isSimulation()) {
game.informPlayers(permanent.getName() + ": " + controller.getLogName() + " has chosen " + choiceColor.getChoice());
}
if (choiceColor.getColor().isBlack()) {
sb.append('B');
} else if (choiceColor.getColor().isBlue()) {
sb.append('U');
} else if (choiceColor.getColor().isRed()) {
sb.append('R');
} else if (choiceColor.getColor().isGreen()) {
sb.append('G');
} else if (choiceColor.getColor().isWhite()) {
sb.append('W');
}
}
String colors = new String(sb);
ObjectColor chosenColors = new ObjectColor(colors);
ContinuousEffect effect = new BecomesColorTargetEffect(chosenColors, Duration.Custom);
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
return true;
}
return false;
}
@Override
public BecomesColorOrColorsEnchantedEffect copy() {
return new BecomesColorOrColorsEnchantedEffect(this);
}
}

View file

@ -0,0 +1,153 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.game.turn.Step;
import mage.players.Library;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class ElkinBottle extends CardImpl {
public ElkinBottle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
// {3}, {tap}, Exile the top card of your library. Until the beginning of your next upkeep, you may play that card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ElkinBottleExileEffect(), new GenericManaCost(3));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
public ElkinBottle(final ElkinBottle card) {
super(card);
}
@Override
public ElkinBottle copy() {
return new ElkinBottle(this);
}
}
class ElkinBottleExileEffect extends OneShotEffect {
public ElkinBottleExileEffect() {
super(Outcome.Detriment);
this.staticText = "Exile the top card of your library. Until the beginning of your next upkeep, you may play that card";
}
public ElkinBottleExileEffect(final ElkinBottleExileEffect effect) {
super(effect);
}
@Override
public ElkinBottleExileEffect copy() {
return new ElkinBottleExileEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (sourcePermanent != null && controller != null && controller.getLibrary().hasCards()) {
Library library = controller.getLibrary();
Card card = library.removeFromTop(game);
if (card != null) {
String exileName = new StringBuilder(sourcePermanent.getIdName()).append(" <this card may be played until the beginning of your next upkeep>").toString();
controller.moveCardToExileWithInfo(card, source.getSourceId(), exileName, source.getSourceId(), game, Zone.LIBRARY, true);
ContinuousEffect effect = new ElkinBottleCastFromExileEffect();
effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source);
}
return true;
}
return false;
}
}
class ElkinBottleCastFromExileEffect extends AsThoughEffectImpl {
private boolean sameStep = true;
public ElkinBottleCastFromExileEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
this.staticText = "Until the beginning of your next upkeep, you may play that card.";
}
public ElkinBottleCastFromExileEffect(final ElkinBottleCastFromExileEffect effect) {
super(effect);
}
@Override
public ElkinBottleCastFromExileEffect copy() {
return new ElkinBottleCastFromExileEffect(this);
}
@Override
public boolean isInactive(Ability source, Game game) {
if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) {
if (!sameStep && game.getActivePlayerId().equals(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) {
return true;
}
} else {
sameStep = false;
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
return source.getControllerId().equals(affectedControllerId)
&& sourceId.equals(getTargetPointer().getFirst(game, source));
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.f;
import java.util.UUID;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.ExileCardFromOwnGraveyardControllerEffect;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
/**
*
* @author L_J
*/
public class FalseMemories extends CardImpl {
public FalseMemories(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
// Put the top seven cards of your library into your graveyard.
this.getSpellAbility().addEffect(new PutTopCardOfLibraryIntoGraveControllerEffect(7));
// At the beginning of the next end step, exile seven cards from your graveyard.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ExileCardFromOwnGraveyardControllerEffect(7))));
}
public FalseMemories(final FalseMemories card) {
super(card);
}
@Override
public FalseMemories copy() {
return new FalseMemories(this);
}
}

View file

@ -0,0 +1,176 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.f;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.RemoveFromCombatTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.PhaseStep;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.ObjectPlayer;
import mage.filter.predicate.ObjectPlayerPredicate;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetAttackingCreature;
import mage.watchers.common.BlockedByOnlyOneCreatureThisCombatWatcher;
/**
*
* @author L_J
*/
public class FalseOrders extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("creature defending player controls");
static {
filter.add(new CardTypePredicate(CardType.CREATURE));
filter.add(new FalseOrdersDefendingPlayerControlsPredicate());
}
public FalseOrders(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}");
// Cast False Orders only during the declare blockers step.
this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, PhaseStep.DECLARE_BLOCKERS, null, "Cast {this} only during the declare blockers step"));
// Remove target creature defending player controls from combat. Creatures it was blocking that had become blocked by only that creature this combat become unblocked. You may have it block an attacking creature of your choice.
this.getSpellAbility().addTarget(new TargetPermanent(filter));
this.getSpellAbility().addEffect(new FalseOrdersUnblockEffect());
this.getSpellAbility().addWatcher(new BlockedByOnlyOneCreatureThisCombatWatcher());
}
public FalseOrders(final FalseOrders card) {
super(card);
}
@Override
public FalseOrders copy() {
return new FalseOrders(this);
}
}
class FalseOrdersDefendingPlayerControlsPredicate implements ObjectPlayerPredicate<ObjectPlayer<Controllable>> {
@Override
public boolean apply(ObjectPlayer<Controllable> input, Game game) {
return game.getCombat().getPlayerDefenders(game).contains(input.getObject().getControllerId());
}
}
class FalseOrdersUnblockEffect extends OneShotEffect {
public FalseOrdersUnblockEffect() {
super(Outcome.Benefit);
this.staticText = "Remove target creature defending player controls from combat. Creatures it was blocking that had become blocked by only that creature this combat become unblocked. You may have it block an attacking creature of your choice";
}
public FalseOrdersUnblockEffect(final FalseOrdersUnblockEffect effect) {
super(effect);
}
@Override
public FalseOrdersUnblockEffect copy() {
return new FalseOrdersUnblockEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getTargets().getFirstTarget());
if (controller != null && permanent != null) {
// Remove target creature from combat
Effect effect = new RemoveFromCombatTargetEffect();
effect.apply(game, source);
// Make blocked creatures unblocked
BlockedByOnlyOneCreatureThisCombatWatcher watcher = (BlockedByOnlyOneCreatureThisCombatWatcher) game.getState().getWatchers().get(BlockedByOnlyOneCreatureThisCombatWatcher.class.getSimpleName());
if (watcher != null) {
Set<CombatGroup> combatGroups = watcher.getBlockedOnlyByCreature(permanent.getId());
if (combatGroups != null) {
for (CombatGroup combatGroup : combatGroups) {
if (combatGroup != null) {
combatGroup.setBlocked(false);
}
}
}
}
// Choose new creature to block
if (permanent.isCreature()) {
if (controller.chooseUse(Outcome.Benefit, "Do you want " + permanent.getLogName() + " to block an attacking creature?", source, game)) {
TargetAttackingCreature target = new TargetAttackingCreature(1, 1, new FilterAttackingCreature(), true);
if (target.canChoose(source.getSourceId(), controller.getId(), game)) {
while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) {
controller.chooseTarget(outcome, target, source, game);
}
} else {
return true;
}
Permanent chosenPermanent = game.getPermanent(target.getFirstTarget());
if (chosenPermanent != null && permanent != null && chosenPermanent.isCreature() && controller != null) {
CombatGroup chosenGroup = game.getCombat().findGroup(chosenPermanent.getId());
if (chosenGroup != null) {
// Relevant ruling for Balduvian Warlord:
// 7/15/2006 If an attacking creature has an ability that triggers When this creature becomes blocked,
// it triggers when a creature blocks it due to the Warlords ability only if it was unblocked at that point.
boolean notYetBlocked = true;
if (!chosenGroup.getBlockers().isEmpty()) {
notYetBlocked = false;
}
chosenGroup.addBlocker(permanent.getId(), controller.getId(), game);
if (notYetBlocked) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, chosenPermanent.getId(), null));
}
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, chosenPermanent.getId(), permanent.getId(), permanent.getControllerId()));
}
}
}
return true;
}
}
return false;
}
}

View file

@ -46,6 +46,7 @@ import mage.game.ExileZone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.turn.Step;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetOpponent;
@ -129,6 +130,8 @@ class GrinningTotemSearchAndExileEffect extends OneShotEffect {
}
class GrinningTotemMayPlayEffect extends AsThoughEffectImpl {
private boolean sameStep = true;
public GrinningTotemMayPlayEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
@ -147,9 +150,11 @@ class GrinningTotemMayPlayEffect extends AsThoughEffectImpl {
@Override
public boolean isInactive(Ability source, Game game) {
if (game.getPhase().getStep().getType() == PhaseStep.UPKEEP) {
if (game.getActivePlayerId().equals(source.getControllerId())) {
if (!sameStep && game.getActivePlayerId().equals(source.getControllerId()) || game.getPlayer(source.getControllerId()).hasReachedNextTurnAfterLeaving()) {
return true;
}
} else {
sameStep = false;
}
return false;
}

View file

@ -0,0 +1,129 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.DamageAsThoughNotBlockedAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
/**
*
* @author emerald000 & L_J
*/
public class Gurzigost extends CardImpl {
public Gurzigost(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
this.subtype.add(SubType.BEAST);
this.power = new MageInt(6);
this.toughness = new MageInt(8);
// At the beginning of your upkeep, sacrifice Gurzigost unless you put two cards from your graveyard on the bottom of your library.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new GurzigostCost()), TargetController.YOU, false));
// {G}{G}, Discard a card: You may have Gurzigost assign its combat damage this turn as though it weren't blocked.
Effect effect = new GainAbilitySourceEffect(DamageAsThoughNotBlockedAbility.getInstance(), Duration.EndOfTurn);
effect.setText("You may have Gurzigost assign its combat damage this turn as though it weren't blocked");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{G}{G}"));
ability.addCost(new DiscardCardCost());
this.addAbility(ability);
}
public Gurzigost(final Gurzigost card) {
super(card);
}
@Override
public Gurzigost copy() {
return new Gurzigost(this);
}
}
class GurzigostCost extends CostImpl {
GurzigostCost() {
this.addTarget(new TargetCardInYourGraveyard(2, 2, new FilterCard()));
this.text = "put two cards from your graveyard on the bottom of your library";
}
GurzigostCost(final GurzigostCost cost) {
super(cost);
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
if (targets.choose(Outcome.Removal, controllerId, sourceId, game)) {
for (UUID targetId: targets.get(0).getTargets()) {
Card card = game.getCard(targetId);
if (card == null || game.getState().getZone(targetId) != Zone.GRAVEYARD) {
return false;
}
paid |= controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.GRAVEYARD, false, true);
}
}
}
return paid;
}
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
return targets.canChoose(controllerId, game);
}
@Override
public GurzigostCost copy() {
return new GurzigostCost(this);
}
}

View file

@ -0,0 +1,139 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.h;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PreventDamageByTargetEffect;
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.filter.common.FilterAttackingCreature;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class Heroism extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a white creature");
static {
filter.add(new ColorPredicate(ObjectColor.WHITE));
}
public Heroism(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}");
// Sacrifice a white creature: For each attacking red creature, prevent all combat damage that would be dealt by that creature this turn unless its controller pays {2}{R}.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new HeroismEffect(), new SacrificeTargetCost(new TargetControlledCreaturePermanent(1,1, filter, true))));
}
public Heroism(final Heroism card) {
super(card);
}
@Override
public Heroism copy() {
return new Heroism(this);
}
}
class HeroismEffect extends OneShotEffect {
private static final FilterAttackingCreature filter = new FilterAttackingCreature("attacking red creature");
static {
filter.add(new ColorPredicate(ObjectColor.RED));
}
public HeroismEffect() {
super(Outcome.Benefit);
this.staticText = "For each attacking red creature, prevent all combat damage that would be dealt by that creature this turn unless its controller pays {2}{R}";
}
public HeroismEffect(final HeroismEffect effect) {
super(effect);
}
@Override
public HeroismEffect copy() {
return new HeroismEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
game.getPlayerList();
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Player player = game.getPlayer(game.getActivePlayerId());
Cost cost = new ManaCostsImpl("{2}{R}");
List<Permanent> permanentsToPrevent = new ArrayList<>();
for (Permanent permanent : game.getState().getBattlefield().getAllActivePermanents(filter, player.getId(), game)) {
String message = "Pay " + cost.getText() + "? If you don't, " + permanent.getLogName() + "'s combat damage will be prevented this turn.";
if (player != null && player.chooseUse(Outcome.Neutral, message, source, game)) {
if (cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) {
game.informPlayers(player.getLogName() + " paid " + cost.getText() + " for " + permanent.getLogName());
continue;
} else {
game.informPlayers(player.getLogName() + " didn't pay " + cost.getText() + " for " + permanent.getLogName());
permanentsToPrevent.add(permanent);
}
} else {
game.informPlayers(player.getLogName() + " didn't pay " + cost.getText() + " for " + permanent.getLogName());
permanentsToPrevent.add(permanent);
}
}
for (Permanent permanent : permanentsToPrevent) {
ContinuousEffect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn, Integer.MAX_VALUE, true);
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,109 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.h;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author L_J
*/
public class HonorTheFallen extends CardImpl {
public HonorTheFallen(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}");
// Exile all creature cards from all graveyards. You gain 1 life for each card exiled this way.
this.getSpellAbility().addEffect(new HonorTheFallenEffect());
}
public HonorTheFallen(final HonorTheFallen card) {
super(card);
}
@Override
public HonorTheFallen copy() {
return new HonorTheFallen(this);
}
}
class HonorTheFallenEffect extends OneShotEffect {
private static final FilterCreatureCard filter = new FilterCreatureCard();
public HonorTheFallenEffect() {
super(Outcome.Detriment);
staticText = "Exile all creature cards from all graveyards. You gain 1 life for each card exiled this way";
}
public HonorTheFallenEffect(final HonorTheFallenEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int exiledCards = 0;
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Card card: player.getGraveyard().getCards(game)) {
if (filter.match(card, game)) {
if (card.moveToExile(null, "", source.getSourceId(), game)) {
exiledCards++;
}
}
}
}
}
controller.gainLife(exiledCards, game);
return true;
}
return false;
}
@Override
public HonorTheFallenEffect copy() {
return new HonorTheFallenEffect(this);
}
}

View file

@ -0,0 +1,80 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility;
import mage.abilities.common.BlocksTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
/**
*
* @author L_J
*/
public class InfernalMedusa extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Wall creature");
static {
filter.add(Predicates.not(new SubtypePredicate(SubType.WALL)));
}
public InfernalMedusa(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.subtype.add(SubType.GORGON);
this.power = new MageInt(2);
this.toughness = new MageInt(4);
// Whenever Infernal Medusa blocks a creature, destroy that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true);
effect.setText("destroy that creature at end of combat");
this.addAbility(new BlocksTriggeredAbility(effect, false, true));
// Whenever Infernal Medusa becomes blocked by a non-Wall creature, destroy that creature at end of combat.
this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(effect, filter, false));
}
public InfernalMedusa(final InfernalMedusa card) {
super(card);
}
@Override
public InfernalMedusa copy() {
return new InfernalMedusa(this);
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.j;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
/**
*
* @author Backfir3
*/
public class JovialEvil extends CardImpl {
public JovialEvil(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}");
// Jovial Evil deals X damage to target opponent, where X is twice the number of white creatures that player controls.
this.getSpellAbility().addEffect(new JovialEvilEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
}
public JovialEvil(final JovialEvil card) {
super(card);
}
@Override
public JovialEvil copy() {
return new JovialEvil(this);
}
}
class JovialEvilEffect extends OneShotEffect {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
static{
filter.add(new ColorPredicate(ObjectColor.WHITE));
}
JovialEvilEffect() {
super(Outcome.Damage);
staticText = "{this} deals X damage to target opponent, where X is twice the number of white creatures that player controls";
}
JovialEvilEffect(final JovialEvilEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player opponent = game.getPlayer(source.getFirstTarget());
if (opponent != null) {
int amount = 0;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, opponent.getId(), game)) {
amount++;
}
if (amount > 0) {
opponent.damage(amount * 2, source.getSourceId(), game, false, true);
}
return true;
}
return false;
}
@Override
public JovialEvilEffect copy() {
return new JovialEvilEffect(this);
}
}

View file

@ -0,0 +1,133 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.l;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
/**
*
* @author L_J
*/
public class LostHours extends CardImpl {
public LostHours(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}");
// Target player reveals his or her hand. You choose a nonland card from it. That player puts that card into his or her library third from the top.
this.getSpellAbility().addEffect(new LostHoursEffect());
this.getSpellAbility().addTarget(new TargetPlayer());
}
public LostHours(final LostHours card) {
super(card);
}
@Override
public LostHours copy() {
return new LostHours(this);
}
}
class LostHoursEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard("nonland card");
static {
filter.add(Predicates.not(new CardTypePredicate(CardType.LAND)));
}
public LostHoursEffect() {
super(Outcome.Discard);
this.staticText = "Target player reveals his or her hand. You choose a nonland card from it. That player puts that card into his or her library third from the top.";
}
public LostHoursEffect(final LostHoursEffect effect) {
super(effect);
}
@Override
public LostHoursEffect copy() {
return new LostHoursEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
Player controller = game.getPlayer(source.getControllerId());
if (player != null && controller != null) {
player.revealCards("Lost Hours", player.getHand(), game);
if (player.getHand().size() > 0) {
TargetCard target = new TargetCard(Zone.HAND, new FilterCard(filter));
if (controller.choose(Outcome.Discard, player.getHand(), target, game)) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
// Move card to third position
CardsImpl cards = new CardsImpl();
cards.add(card);
Card cardTop = null;
Card cardSecond = null;
if (player.getLibrary().hasCards()) {
cardTop = player.getLibrary().removeFromTop(game);
}
if (player.getLibrary().hasCards()) {
cardSecond = player.getLibrary().removeFromTop(game);
}
player.putCardsOnTopOfLibrary(cards, game, source, true);
if (cardSecond != null) {
player.getLibrary().putOnTop(cardSecond, game);
}
if (cardTop != null) {
player.getLibrary().putOnTop(cardTop, game);
}
game.informPlayers(card.getLogName() + " is put into " + player.getLogName() +"'s library " + (cardTop != null ? (cardSecond != null ? "third" : "second") : "first") + " from the top");
}
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class PitchstoneWall extends CardImpl {
public PitchstoneWall(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
this.subtype.add(SubType.WALL);
this.power = new MageInt(2);
this.toughness = new MageInt(5);
// Defender (This creature can't attack.)
this.addAbility(DefenderAbility.getInstance());
// Whenever you discard a card, you may sacrifice Pitchstone Wall. If you do, return the discarded card from your graveyard to your hand.
this.addAbility(new PitchstoneWallTriggeredAbility());
}
public PitchstoneWall(final PitchstoneWall card) {
super(card);
}
@Override
public PitchstoneWall copy() {
return new PitchstoneWall(this);
}
}
class PitchstoneWallTriggeredAbility extends TriggeredAbilityImpl {
public PitchstoneWallTriggeredAbility() {
super(Zone.BATTLEFIELD, new DoIfCostPaid(new ReturnToHandTargetEffect().setText("return the discarded card from your graveyard to your hand"), new SacrificeSourceCost()), false);
}
public PitchstoneWallTriggeredAbility(final PitchstoneWallTriggeredAbility ability) {
super(ability);
}
@Override
public PitchstoneWallTriggeredAbility copy() {
return new PitchstoneWallTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DISCARDED_CARD;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(controllerId)) {
Effect effect = this.getEffects().get(0);
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
return true;
}
return false;
}
@Override
public String getRule() {
return "Whenever you discard a card, " + super.getRule();
}
}

View file

@ -0,0 +1,113 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksEachCombatStaticAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
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.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author L_J
*/
public class PrimordialOoze extends CardImpl {
public PrimordialOoze(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}");
this.subtype.add(SubType.OOZE);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Primordial Ooze attacks each combat if able.
this.addAbility(new AttacksEachCombatStaticAbility());
// At the beginning of your upkeep, put a +1/+1 counter on Primordial Ooze. Then you may pay {X}, where X is the number of +1/+1 counters on it. If you don't, tap Primordial Ooze and it deals X damage to you.
Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), TargetController.YOU, false);
ability.addEffect(new PrimordialOozeEffect());
this.addAbility(ability);
}
public PrimordialOoze(final PrimordialOoze card) {
super(card);
}
@Override
public PrimordialOoze copy() {
return new PrimordialOoze(this);
}
}
class PrimordialOozeEffect extends OneShotEffect {
public PrimordialOozeEffect() {
super(Outcome.Detriment);
this.staticText = "Then you may pay {X}, where X is the number of +1/+1 counters on it. If you don't, tap {this} and it deals X damage to you";
}
public PrimordialOozeEffect(final PrimordialOozeEffect effect) {
super(effect);
}
@Override
public PrimordialOozeEffect copy() {
return new PrimordialOozeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent sourceObject = (Permanent) source.getSourceObjectIfItStillExists(game);
if (controller != null && sourceObject != null) {
int counter = sourceObject.getCounters(game).getCount(CounterType.P1P1);
Cost cost = new ManaCostsImpl<>("{" + counter + '}');
if (!(controller.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + " to prevent taking " + counter + " damage from " + sourceObject.getLogName() + "?", source, game)
&& cost.pay(source, game, source.getSourceId(), controller.getId(), false, null))) {
sourceObject.tap(game);
controller.damage(counter, source.getSourceId(), game, false, true);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,114 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.StackObject;
import mage.target.common.TargetCreatureOrPlayer;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class PsychicPurge extends CardImpl {
public PsychicPurge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}");
// Psychic Purge deals 1 damage to target creature or player.
this.getSpellAbility().addEffect(new DamageTargetEffect(1));
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
// When a spell or ability an opponent controls causes you to discard Psychic Purge, that player loses 5 life.
Ability ability = new PsychicPurgeTriggeredAbility();
this.addAbility(ability);
}
public PsychicPurge(final PsychicPurge card) {
super(card);
}
@Override
public PsychicPurge copy() {
return new PsychicPurge(this);
}
}
class PsychicPurgeTriggeredAbility extends TriggeredAbilityImpl {
public PsychicPurgeTriggeredAbility() {
super(Zone.GRAVEYARD, new LoseLifeTargetEffect(5), false);
}
public PsychicPurgeTriggeredAbility(final PsychicPurgeTriggeredAbility ability) {
super(ability);
}
@Override
public PsychicPurgeTriggeredAbility copy() {
return new PsychicPurgeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.DISCARDED_CARD;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (getSourceId().equals(event.getTargetId())) {
StackObject stackObject = game.getStack().getStackObject(event.getSourceId());
if (stackObject != null) {
if (game.getOpponents(this.getControllerId()).contains(stackObject.getControllerId())) {
Effect effect = this.getEffects().get(0);
effect.setTargetPointer(new FixedTarget(stackObject.getControllerId()));
return true;
}
}
}
return false;
}
@Override
public String getRule() {
return "When a spell or ability an opponent controls causes you to discard {this}, that player loses 5 life.";
}
}

View file

@ -0,0 +1,108 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.s;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PreventDamageToTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author L_J
*/
public class SamiteCenserBearer extends CardImpl {
public SamiteCenserBearer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.REBEL);
this.subtype.add(SubType.CLERIC);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {W}, Sacrifice Samite Censer-Bearer: Prevent the next 1 damage that would be dealt to each creature you control this turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SamiteCenserBearerEffect(), new ManaCostsImpl("{W}"));
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
}
public SamiteCenserBearer(final SamiteCenserBearer card) {
super(card);
}
@Override
public SamiteCenserBearer copy() {
return new SamiteCenserBearer(this);
}
}
class SamiteCenserBearerEffect extends OneShotEffect {
public SamiteCenserBearerEffect() {
super(Outcome.PreventDamage);
this.staticText = "Prevent the next 1 damage that would be dealt to each creature you control this turn";
}
public SamiteCenserBearerEffect(final SamiteCenserBearerEffect effect) {
super(effect);
}
@Override
public SamiteCenserBearerEffect copy() {
return new SamiteCenserBearerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
PreventDamageToTargetEffect effect = new PreventDamageToTargetEffect(Duration.EndOfTurn, 1);
List<Permanent> permanents = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), game);
for (Permanent permanent : permanents) {
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,119 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToHandFromGraveyardAllEffect;
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.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.players.Player;
/**
*
* @author L_J
*/
public class SaprazzanBailiff extends CardImpl {
private static final FilterCard filter = new FilterCard("artifact and enchantment cards");
static {
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.ENCHANTMENT)));
}
public SaprazzanBailiff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}");
this.subtype.add(SubType.MERFOLK);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// When Saprazzan Bailiff enters the battlefield, exile all artifact and enchantment cards from all graveyards.
this.addAbility(new EntersBattlefieldTriggeredAbility(new SaprazzanBailiffEffect()));
// When Saprazzan Bailiff leaves the battlefield, return all artifact and enchantment cards from all graveyards to their owners' hands.
this.addAbility(new LeavesBattlefieldTriggeredAbility(new ReturnToHandFromGraveyardAllEffect(filter).setText("return all artifact and enchantment cards from all graveyards to their owners' hands"), false));
}
public SaprazzanBailiff(final SaprazzanBailiff card) {
super(card);
}
@Override
public SaprazzanBailiff copy() {
return new SaprazzanBailiff(this);
}
}
class SaprazzanBailiffEffect extends OneShotEffect {
public SaprazzanBailiffEffect() {
super(Outcome.Detriment);
staticText = "exile all artifact and enchantment cards from all graveyards";
}
@Override
public SaprazzanBailiffEffect copy() {
return new SaprazzanBailiffEffect();
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (UUID cid : player.getGraveyard().copy()) {
Card card = game.getCard(cid);
if (card != null && (card.isArtifact() || card.isEnchantment())) {
controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.GRAVEYARD, true);
}
}
}
}
return true;
}
}

View file

@ -0,0 +1,174 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.s;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author jeffwadsworth & L_J
*/
public class Spawnbroker extends CardImpl {
private static final String rule = "you may exchange control of target creature you control and target creature with power less than or equal to that creature's power an opponent controls";
public Spawnbroker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// When Spawnbroker enters the battlefield, you may exchange control of target creature you control and target creature with power less than or equal to that creature's power an opponent controls.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExchangeControlTargetEffect(Duration.Custom, rule, false, true), true);
ability.addTarget(new TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent());
ability.addTarget(new SpawnbrokerSecondTarget());
this.addAbility(ability);
}
public Spawnbroker(final Spawnbroker card) {
super(card);
}
@Override
public Spawnbroker copy() {
return new Spawnbroker(this);
}
}
class TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent extends TargetControlledPermanent {
public TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent() {
super();
filter.add(new CardTypePredicate(CardType.CREATURE));
setTargetName("creature you control");
}
public TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent(final TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent target) {
super(target);
}
@Override
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
return super.canTarget(controllerId, id, source, game);
}
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
MageObject targetSource = game.getObject(sourceId);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) {
possibleTargets.add(permanent.getId());
}
}
return possibleTargets;
}
@Override
public TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent copy() {
return new TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent(this);
}
}
class SpawnbrokerSecondTarget extends TargetPermanent {
private Permanent firstTarget = null;
public SpawnbrokerSecondTarget() {
super();
filter.add(new ControllerPredicate(TargetController.OPPONENT));
filter.add(new CardTypePredicate(CardType.CREATURE));
setTargetName("creature with power less than or equal to that creature's power an opponent controls");
}
public SpawnbrokerSecondTarget(final SpawnbrokerSecondTarget target) {
super(target);
this.firstTarget = target.firstTarget;
}
@Override
public boolean canTarget(UUID id, Ability source, Game game) {
if (super.canTarget(id, source, game)) {
Permanent target1 = game.getPermanent(source.getFirstTarget());
Permanent opponentPermanent = game.getPermanent(id);
if (target1 != null && opponentPermanent != null) {
return target1.getPower().getValue() >= opponentPermanent.getPower().getValue();
}
}
return false;
}
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = new HashSet<>();
if (firstTarget != null) {
MageObject targetSource = game.getObject(sourceId);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) {
if (firstTarget.getPower().getValue() >= permanent.getPower().getValue()) {
possibleTargets.add(permanent.getId());
}
}
}
}
return possibleTargets;
}
@Override
public boolean chooseTarget(Outcome outcome, UUID playerId, Ability source, Game game) {
firstTarget = game.getPermanent(source.getFirstTarget());
return super.chooseTarget(Outcome.GainControl, playerId, source, game);
}
@Override
public SpawnbrokerSecondTarget copy() {
return new SpawnbrokerSecondTarget(this);
}
}

View file

@ -0,0 +1,113 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.target.Target;
import mage.util.CardUtil;
/**
*
* @author LevelX2 & L_J
*/
public class SpellwildOuphe extends CardImpl {
public SpellwildOuphe(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add(SubType.OUPHE);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// Spells that target Elderwood Scion cost {2} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellwildOupheCostReductionEffect()));
}
public SpellwildOuphe(final SpellwildOuphe card) {
super(card);
}
@Override
public SpellwildOuphe copy() {
return new SpellwildOuphe(this);
}
}
class SpellwildOupheCostReductionEffect extends CostModificationEffectImpl {
private static final String effectText = "Spells that target {this} cost {2} less to cast";
SpellwildOupheCostReductionEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
staticText = effectText;
}
SpellwildOupheCostReductionEffect(SpellwildOupheCostReductionEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
SpellAbility spellAbility = (SpellAbility) abilityToModify;
CardUtil.adjustCost(spellAbility, 2);
return true;
}
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) {
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
Mode mode = abilityToModify.getModes().get(modeId);
for (Target target : mode.getTargets()) {
for (UUID targetUUID : target.getTargets()) {
if (targetUUID.equals(source.getSourceId())) {
return true;
}
}
}
}
}
return false;
}
@Override
public SpellwildOupheCostReductionEffect copy() {
return new SpellwildOupheCostReductionEffect(this);
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.UUID;
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
import mage.abilities.effects.common.PreventCombatDamageBySourceEffect;
import mage.abilities.effects.common.TapTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public class Telekinesis extends CardImpl {
public Telekinesis(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}{U}");
// Tap target creature. Prevent all combat damage that would be dealt by that creature this turn. It doesn't untap during its controller's next two untap steps.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new TapTargetEffect());
this.getSpellAbility().addEffect(new PreventCombatDamageBySourceEffect(Duration.EndOfTurn).setText("Prevent all combat damage that would be dealt by that creature this turn"));
this.getSpellAbility().addEffect(new DontUntapInControllersNextUntapStepTargetEffect("It", true, null));
}
public Telekinesis(final Telekinesis card) {
super(card);
}
@Override
public Telekinesis copy() {
return new Telekinesis(this);
}
}

View file

@ -0,0 +1,134 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* @author spjspj & L_J
*/
public class ThelonsCurse extends CardImpl {
private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent("blue creatures");
static {
filterCreature.add(new ColorPredicate(ObjectColor.BLUE));
}
public ThelonsCurse(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}{G}");
// Blue creatures don't untap during their controllers' untap steps.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepAllEffect(Duration.WhileOnBattlefield, TargetController.ANY, filterCreature)));
// At the beginning of each player's upkeep, that player may choose any number of tapped blue creatures he or she controls and pay {U} for each creature chosen this way. If the player does, untap those creatures.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new ThelonsCurseEffect(), TargetController.ANY, false));
}
public ThelonsCurse(final ThelonsCurse card) {
super(card);
}
@Override
public ThelonsCurse copy() {
return new ThelonsCurse(this);
}
}
class ThelonsCurseEffect extends OneShotEffect {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("tapped blue creature");
static {
filter.add(new TappedPredicate());
filter.add(new ColorPredicate(ObjectColor.BLUE));
}
ThelonsCurseEffect() {
super(Outcome.Benefit);
staticText = "that player may choose any number of tapped blue creatures he or she controls and pay {U} for each creature chosen this way. If the player does, untap those creatures.";
}
ThelonsCurseEffect(ThelonsCurseEffect effect) {
super(effect);
}
@Override
public ThelonsCurseEffect copy() {
return new ThelonsCurseEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (player != null && sourcePermanent != null) {
int countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size();
while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.AIDontUseIt, "Pay {U} and untap a tapped blue creature under your control?", source, game)) {
Target tappedCreatureTarget = new TargetControlledCreaturePermanent(1, 1, filter, true);
if (player.choose(Outcome.Detriment, tappedCreatureTarget, source.getSourceId(), game)) {
Cost cost = new ManaCostsImpl("U");
Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget());
if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) {
tappedCreature.untap(game);
}
}
countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size();
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,232 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.CumulativeUpkeepAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.TombspawnZombieToken;
import mage.game.permanent.token.Token;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
*
* @author L_J
*/
public class TombstoneStairwell extends CardImpl {
public TombstoneStairwell(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}");
addSuperType(SuperType.WORLD);
// Cumulative upkeep-Pay {1}{B}.
this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}{B}")));
// At the beginning of each upkeep, if Tombstone Stairwell is on the battlefield, each player creates a 2/2 black Zombie creature token with haste named Tombspawn for each creature card in his or her graveyard.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TombstoneStairwellCreateTokenEffect(), TargetController.ANY, false));
// At the beginning of each end step or when Tombstone Stairwell leaves the battlefield, destroy all tokens created with Tombstone Stairwell. They can't be regenerated.
this.addAbility(new TombstoneStairwellTriggeredAbility());
}
public TombstoneStairwell(final TombstoneStairwell card) {
super(card);
}
@Override
public TombstoneStairwell copy() {
return new TombstoneStairwell(this);
}
}
class TombstoneStairwellCreateTokenEffect extends OneShotEffect {
TombstoneStairwellCreateTokenEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "if {this} is on the battlefield, each player creates a 2/2 black Zombie creature token with haste named Tombspawn for each creature card in his or her graveyard";
}
TombstoneStairwellCreateTokenEffect(final TombstoneStairwellCreateTokenEffect effect) {
super(effect);
}
@Override
public TombstoneStairwellCreateTokenEffect copy() {
return new TombstoneStairwellCreateTokenEffect(this);
}
@Override
@SuppressWarnings("unchecked")
public boolean apply(Game game, Ability source) {
Token token = new TombspawnZombieToken();
Player activePlayer = game.getPlayer(game.getActivePlayerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (game.getPlayer(source.getControllerId()) != null && activePlayer != null && permanent != null) {
Object object = game.getState().getValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game));
Set<UUID> tokensCreated;
if (object != null) {
tokensCreated = (Set<UUID>) object;
} else {
tokensCreated = new HashSet<>();
}
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
int creatureCardsInGraveyard = player.getGraveyard().count(new FilterCreatureCard(), source.getControllerId(), source.getSourceId(), game);
token.putOntoBattlefield(creatureCardsInGraveyard, game, source.getSourceId(), playerId);
for (UUID tokenId : token.getLastAddedTokenIds()) {
tokensCreated.add(tokenId);
}
}
game.getState().setValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game), tokensCreated);
return true;
}
return false;
}
}
class TombstoneStairwellTriggeredAbility extends TriggeredAbilityImpl {
TombstoneStairwellTriggeredAbility() {
super(Zone.BATTLEFIELD, new TombstoneStairwellDestroyEffect(), false);
}
TombstoneStairwellTriggeredAbility(TombstoneStairwellTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.END_TURN_STEP_PRE
|| event.getType() == EventType.ZONE_CHANGE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == EventType.END_TURN_STEP_PRE) {
Permanent permanent = game.getPermanentOrLKIBattlefield(sourceId);
if (permanent != null) {
for (Effect effect : this.getEffects()) {
if (effect instanceof TombstoneStairwellDestroyEffect) {
((TombstoneStairwellDestroyEffect) effect).setCardZoneString(CardUtil.getCardZoneString("_tokensCreated", this.getSourceId(), game, false));
}
if (getTargets().isEmpty()) {
effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
}
}
return true;
}
}
else if (event.getType() == EventType.ZONE_CHANGE) {
if (event.getTargetId().equals(this.getSourceId())) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
for (Effect effect : this.getEffects()) {
if (effect instanceof TombstoneStairwellDestroyEffect) {
((TombstoneStairwellDestroyEffect) effect).setCardZoneString(CardUtil.getCardZoneString("_tokensCreated", this.getSourceId(), game, true));
}
}
return true;
}
}
}
return false;
}
@Override
public TombstoneStairwellTriggeredAbility copy() {
return new TombstoneStairwellTriggeredAbility(this);
}
@Override
public String getRule() {
return "At the beginning of each end step or when {this} leaves the battlefield, " + modes.getText();
}
}
class TombstoneStairwellDestroyEffect extends OneShotEffect {
private String cardZoneString;
TombstoneStairwellDestroyEffect() {
super(Outcome.Benefit);
this.staticText = "destroy all tokens created with {this}. They can't be regenerated";
}
TombstoneStairwellDestroyEffect(final TombstoneStairwellDestroyEffect effect) {
super(effect);
this.cardZoneString = effect.cardZoneString;
}
@Override
public TombstoneStairwellDestroyEffect copy() {
return new TombstoneStairwellDestroyEffect(this);
}
@Override
@SuppressWarnings("unchecked")
public boolean apply(Game game, Ability source) {
Object object = game.getState().getValue(cardZoneString);
if (object != null) {
Set<UUID> tokensCreated = (Set<UUID>) object;
for (UUID tokenId : tokensCreated) {
Permanent token = game.getPermanent(tokenId);
if (token != null) {
token.destroy(source.getSourceId(), game, true);
}
}
}
return true;
}
public void setCardZoneString(String cardZoneString) {
this.cardZoneString = cardZoneString;
}
}

View file

@ -0,0 +1,106 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.t;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author L_J
*/
public class Typhoon extends CardImpl {
public Typhoon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}");
// Typhoon deals damage to each opponent equal to the number of Islands that player controls.
this.getSpellAbility().addEffect(new TyphoonEffect());
}
public Typhoon(final Typhoon card) {
super(card);
}
@Override
public Typhoon copy() {
return new Typhoon(this);
}
}
class TyphoonEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent();
static{
filter.add(new SubtypePredicate(SubType.ISLAND));
}
TyphoonEffect() {
super(Outcome.Damage);
staticText = "{this} deals damage to each opponent equal to the number of Islands that player controls";
}
TyphoonEffect(final TyphoonEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
if (playerId != source.getControllerId()) {
Player player = game.getPlayer(playerId);
if (player != null) {
int amount = 0;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) {
amount++;
}
if (amount > 0) {
player.damage(amount, source.getSourceId(), game, false, true);
}
}
}
}
return true;
}
@Override
public TyphoonEffect copy() {
return new TyphoonEffect(this);
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.v;
import java.util.UUID;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.filter.common.FilterPermanentOrSuspendedCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.common.TargetPermanentOrSuspendedCard;
/**
*
* @author L_J
*/
public class VensersDiffusion extends CardImpl {
private static final FilterPermanentOrSuspendedCard filter = new FilterPermanentOrSuspendedCard("nonland permanent or suspended card");
static {
filter.add(Predicates.not(new CardTypePredicate(CardType.LAND)));
}
public VensersDiffusion (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}");
// Return target nonland permanent or suspended card to its owner's hand.
this.getSpellAbility().addTarget(new TargetPermanentOrSuspendedCard(filter, false));
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
}
public VensersDiffusion (final VensersDiffusion card) {
super(card);
}
@Override
public VensersDiffusion copy() {
return new VensersDiffusion(this);
}
}

View file

@ -114,6 +114,7 @@ public class Chronicles extends ExpansionSet {
cards.add(new SetCardInfo("Obelisk of Undoing", 84, Rarity.RARE, mage.cards.o.ObeliskOfUndoing.class));
cards.add(new SetCardInfo("Palladia-Mors", 117, Rarity.RARE, mage.cards.p.PalladiaMors.class));
cards.add(new SetCardInfo("Petra Sphinx", 66, Rarity.RARE, mage.cards.p.PetraSphinx.class));
cards.add(new SetCardInfo("Primordial Ooze", 54, Rarity.UNCOMMON, mage.cards.p.PrimordialOoze.class));
cards.add(new SetCardInfo("Rabid Wombat", 39, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class));
cards.add(new SetCardInfo("Rakalite", 85, Rarity.RARE, mage.cards.r.Rakalite.class));
cards.add(new SetCardInfo("Recall", 24, Rarity.UNCOMMON, mage.cards.r.Recall.class));

View file

@ -62,6 +62,7 @@ public class Coldsnap extends ExpansionSet {
cards.add(new SetCardInfo("Arcum Dagsson", 27, Rarity.RARE, mage.cards.a.ArcumDagsson.class));
cards.add(new SetCardInfo("Aurochs Herd", 103, Rarity.COMMON, mage.cards.a.AurochsHerd.class));
cards.add(new SetCardInfo("Balduvian Rage", 76, Rarity.UNCOMMON, mage.cards.b.BalduvianRage.class));
cards.add(new SetCardInfo("Balduvian Warlord", 77, Rarity.UNCOMMON, mage.cards.b.BalduvianWarlord.class));
cards.add(new SetCardInfo("Blizzard Specter", 126, Rarity.UNCOMMON, mage.cards.b.BlizzardSpecter.class));
cards.add(new SetCardInfo("Boreal Centaur", 104, Rarity.COMMON, mage.cards.b.BorealCentaur.class));
cards.add(new SetCardInfo("Boreal Druid", 105, Rarity.COMMON, mage.cards.b.BorealDruid.class));
@ -84,7 +85,7 @@ public class Coldsnap extends ExpansionSet {
cards.add(new SetCardInfo("Diamond Faerie", 128, Rarity.RARE, mage.cards.d.DiamondFaerie.class));
cards.add(new SetCardInfo("Disciple of Tevesh Szat", 55, Rarity.COMMON, mage.cards.d.DiscipleOfTeveshSzat.class));
cards.add(new SetCardInfo("Drelnoch", 32, Rarity.COMMON, mage.cards.d.Drelnoch.class));
cards.add(new SetCardInfo("Earthen Goo", 80, Rarity.UNCOMMON, mage.cards.e.EarthenGoo.class));
cards.add(new SetCardInfo("Earthen Goo", 80, Rarity.UNCOMMON, mage.cards.e.EarthenGoo.class));
cards.add(new SetCardInfo("Field Marshal", 5, Rarity.RARE, mage.cards.f.FieldMarshal.class));
cards.add(new SetCardInfo("Flashfreeze", 33, Rarity.UNCOMMON, mage.cards.f.Flashfreeze.class));
cards.add(new SetCardInfo("Freyalise's Radiance", 108, Rarity.UNCOMMON, mage.cards.f.FreyalisesRadiance.class));
@ -116,7 +117,7 @@ public class Coldsnap extends ExpansionSet {
cards.add(new SetCardInfo("Karplusan Strider", 112, Rarity.UNCOMMON, mage.cards.k.KarplusanStrider.class));
cards.add(new SetCardInfo("Karplusan Wolverine", 87, Rarity.COMMON, mage.cards.k.KarplusanWolverine.class));
cards.add(new SetCardInfo("Kjeldoran Gargoyle", 10, Rarity.UNCOMMON, mage.cards.k.KjeldoranGargoyle.class));
cards.add(new SetCardInfo("Kjeldoran Javelineer", 11, Rarity.COMMON, mage.cards.k.KjeldoranJavelineer.class));
cards.add(new SetCardInfo("Kjeldoran Javelineer", 11, Rarity.COMMON, mage.cards.k.KjeldoranJavelineer.class));
cards.add(new SetCardInfo("Kjeldoran Outrider", 12, Rarity.COMMON, mage.cards.k.KjeldoranOutrider.class));
cards.add(new SetCardInfo("Krovikan Mist", 38, Rarity.COMMON, mage.cards.k.KrovikanMist.class));
cards.add(new SetCardInfo("Krovikan Rot", 63, Rarity.UNCOMMON, mage.cards.k.KrovikanRot.class));
@ -126,7 +127,7 @@ public class Coldsnap extends ExpansionSet {
cards.add(new SetCardInfo("Lightning Storm", 89, Rarity.UNCOMMON, mage.cards.l.LightningStorm.class));
cards.add(new SetCardInfo("Lovisa Coldeyes", 90, Rarity.RARE, mage.cards.l.LovisaColdeyes.class));
cards.add(new SetCardInfo("Luminesce", 14, Rarity.UNCOMMON, mage.cards.l.Luminesce.class));
cards.add(new SetCardInfo("Magmatic Core", 91, Rarity.UNCOMMON, mage.cards.m.MagmaticCore.class));
cards.add(new SetCardInfo("Magmatic Core", 91, Rarity.UNCOMMON, mage.cards.m.MagmaticCore.class));
cards.add(new SetCardInfo("Martyr of Ashes", 92, Rarity.COMMON, mage.cards.m.MartyrOfAshes.class));
cards.add(new SetCardInfo("Martyr of Bones", 65, Rarity.COMMON, mage.cards.m.MartyrOfBones.class));
cards.add(new SetCardInfo("Martyr of Frost", 40, Rarity.COMMON, mage.cards.m.MartyrOfFrost.class));
@ -153,7 +154,7 @@ public class Coldsnap extends ExpansionSet {
cards.add(new SetCardInfo("Rimewind Taskmage", 44, Rarity.COMMON, mage.cards.r.RimewindTaskmage.class));
cards.add(new SetCardInfo("Rite of Flame", 96, Rarity.COMMON, mage.cards.r.RiteOfFlame.class));
cards.add(new SetCardInfo("Ronom Hulk", 119, Rarity.COMMON, mage.cards.r.RonomHulk.class));
cards.add(new SetCardInfo("Ronom Serpent", 45, Rarity.COMMON, mage.cards.r.RonomSerpent.class));
cards.add(new SetCardInfo("Ronom Serpent", 45, Rarity.COMMON, mage.cards.r.RonomSerpent.class));
cards.add(new SetCardInfo("Ronom Unicorn", 16, Rarity.COMMON, mage.cards.r.RonomUnicorn.class));
cards.add(new SetCardInfo("Rune Snag", 46, Rarity.COMMON, mage.cards.r.RuneSnag.class));
cards.add(new SetCardInfo("Scrying Sheets", 149, Rarity.RARE, mage.cards.s.ScryingSheets.class));

View file

@ -152,6 +152,7 @@ public class FallenEmpires extends ExpansionSet {
cards.add(new SetCardInfo("Goblin Warrens", 122, Rarity.RARE, mage.cards.g.GoblinWarrens.class));
cards.add(new SetCardInfo("Hand of Justice", 142, Rarity.RARE, mage.cards.h.HandOfJustice.class));
cards.add(new SetCardInfo("Havenwood Battleground", 181, Rarity.UNCOMMON, mage.cards.h.HavenwoodBattleground.class));
cards.add(new SetCardInfo("Heroism", 143, Rarity.UNCOMMON, mage.cards.h.Heroism.class));
cards.add(new SetCardInfo("High Tide", 35, Rarity.COMMON, HighTide.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("High Tide", 36, Rarity.COMMON, HighTide.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("High Tide", 37, Rarity.COMMON, HighTide.class, NON_FULL_USE_VARIOUS));
@ -232,6 +233,7 @@ public class FallenEmpires extends ExpansionSet {
cards.add(new SetCardInfo("Thallid Devourer", 91, Rarity.UNCOMMON, mage.cards.t.ThallidDevourer.class));
cards.add(new SetCardInfo("Thelonite Druid", 92, Rarity.UNCOMMON, mage.cards.t.TheloniteDruid.class));
cards.add(new SetCardInfo("Thelonite Monk", 93, Rarity.RARE, mage.cards.t.TheloniteMonk.class));
cards.add(new SetCardInfo("Thelon's Curse", 95, Rarity.RARE, mage.cards.t.ThelonsCurse.class));
cards.add(new SetCardInfo("Thorn Thallid", 96, Rarity.COMMON, ThornThallid.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Thorn Thallid", 97, Rarity.COMMON, ThornThallid.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Thorn Thallid", 98, Rarity.COMMON, ThornThallid.class, NON_FULL_USE_VARIOUS));

View file

@ -144,6 +144,7 @@ public class FifthEdition extends ExpansionSet {
cards.add(new SetCardInfo("Earthquake", 223, Rarity.RARE, mage.cards.e.Earthquake.class));
cards.add(new SetCardInfo("Ebon Stronghold", 416, Rarity.UNCOMMON, mage.cards.e.EbonStronghold.class));
cards.add(new SetCardInfo("Elder Druid", 152, Rarity.RARE, mage.cards.e.ElderDruid.class));
cards.add(new SetCardInfo("Elkin Bottle", 367, Rarity.RARE, mage.cards.e.ElkinBottle.class));
cards.add(new SetCardInfo("Elven Riders", 153, Rarity.UNCOMMON, mage.cards.e.ElvenRiders.class));
cards.add(new SetCardInfo("Elvish Archers", 154, Rarity.RARE, mage.cards.e.ElvishArchers.class));
cards.add(new SetCardInfo("Energy Flux", 83, Rarity.UNCOMMON, mage.cards.e.EnergyFlux.class));
@ -328,7 +329,8 @@ public class FifthEdition extends ExpansionSet {
cards.add(new SetCardInfo("Pradesh Gypsies", 179, Rarity.COMMON, mage.cards.p.PradeshGypsies.class));
cards.add(new SetCardInfo("Primal Clay", 395, Rarity.RARE, mage.cards.p.PrimalClay.class));
cards.add(new SetCardInfo("Primal Order", 180, Rarity.RARE, mage.cards.p.PrimalOrder.class));
cards.add(new SetCardInfo("Prismatic Ward", 329, Rarity.COMMON, mage.cards.p.PrismaticWard.class));
cards.add(new SetCardInfo("Primordial Ooze", 261, Rarity.UNCOMMON, mage.cards.p.PrimordialOoze.class));
cards.add(new SetCardInfo("Prismatic Ward", 329, Rarity.COMMON, mage.cards.p.PrismaticWard.class));
cards.add(new SetCardInfo("Prodigal Sorcerer", 112, Rarity.COMMON, mage.cards.p.ProdigalSorcerer.class));
cards.add(new SetCardInfo("Psychic Venom", 113, Rarity.COMMON, mage.cards.p.PsychicVenom.class));
cards.add(new SetCardInfo("Pyroblast", 262, Rarity.UNCOMMON, mage.cards.p.Pyroblast.class));

View file

@ -137,6 +137,7 @@ public class FutureSight extends ExpansionSet {
cards.add(new SetCardInfo("Llanowar Reborn", 171, Rarity.UNCOMMON, mage.cards.l.LlanowarReborn.class));
cards.add(new SetCardInfo("Logic Knot", 52, Rarity.COMMON, mage.cards.l.LogicKnot.class));
cards.add(new SetCardInfo("Lost Auramancers", 11, Rarity.UNCOMMON, mage.cards.l.LostAuramancers.class));
cards.add(new SetCardInfo("Lost Hours", 69, Rarity.COMMON, mage.cards.l.LostHours.class));
cards.add(new SetCardInfo("Lucent Liminid", 24, Rarity.COMMON, mage.cards.l.LucentLiminid.class));
cards.add(new SetCardInfo("Lumithread Field", 25, Rarity.COMMON, mage.cards.l.LumithreadField.class));
cards.add(new SetCardInfo("Lymph Sliver", 26, Rarity.COMMON, mage.cards.l.LymphSliver.class));
@ -181,6 +182,7 @@ public class FutureSight extends ExpansionSet {
cards.add(new SetCardInfo("Rites of Flourishing", 137, Rarity.RARE, mage.cards.r.RitesOfFlourishing.class));
cards.add(new SetCardInfo("River of Tears", 179, Rarity.RARE, mage.cards.r.RiverOfTears.class));
cards.add(new SetCardInfo("Saltskitter", 14, Rarity.COMMON, mage.cards.s.Saltskitter.class));
cards.add(new SetCardInfo("Samite Censer-Bearer", 15, Rarity.COMMON, mage.cards.s.SamiteCenserBearer.class));
cards.add(new SetCardInfo("Sarcomite Myr", 56, Rarity.COMMON, mage.cards.s.SarcomiteMyr.class));
cards.add(new SetCardInfo("Scourge of Kher Ridges", 107, Rarity.RARE, mage.cards.s.ScourgeOfKherRidges.class));
cards.add(new SetCardInfo("Scout's Warning", 16, Rarity.RARE, mage.cards.s.ScoutsWarning.class));
@ -197,6 +199,7 @@ public class FutureSight extends ExpansionSet {
cards.add(new SetCardInfo("Snake Cult Initiation", 89, Rarity.UNCOMMON, mage.cards.s.SnakeCultInitiation.class));
cards.add(new SetCardInfo("Soultether Golem", 164, Rarity.UNCOMMON, mage.cards.s.SoultetherGolem.class));
cards.add(new SetCardInfo("Sparkspitter", 109, Rarity.UNCOMMON, mage.cards.s.Sparkspitter.class));
cards.add(new SetCardInfo("Spellwild Ouphe", 151, Rarity.UNCOMMON, mage.cards.s.SpellwildOuphe.class));
cards.add(new SetCardInfo("Spin into Myth", 60, Rarity.UNCOMMON, mage.cards.s.SpinIntoMyth.class));
cards.add(new SetCardInfo("Spirit en-Dal", 17, Rarity.UNCOMMON, mage.cards.s.SpiritEnDal.class));
cards.add(new SetCardInfo("Sporoloth Ancient", 152, Rarity.COMMON, mage.cards.s.SporolothAncient.class));
@ -217,6 +220,7 @@ public class FutureSight extends ExpansionSet {
cards.add(new SetCardInfo("Vedalken Aethermage", 61, Rarity.COMMON, mage.cards.v.VedalkenAethermage.class));
cards.add(new SetCardInfo("Veilstone Amulet", 166, Rarity.RARE, mage.cards.v.VeilstoneAmulet.class));
cards.add(new SetCardInfo("Venser, Shaper Savant", 46, Rarity.RARE, mage.cards.v.VenserShaperSavant.class));
cards.add(new SetCardInfo("Venser's Diffusion", 47, Rarity.COMMON, mage.cards.v.VensersDiffusion.class));
cards.add(new SetCardInfo("Virulent Sliver", 155, Rarity.COMMON, mage.cards.v.VirulentSliver.class));
cards.add(new SetCardInfo("Whetwheel", 168, Rarity.RARE, mage.cards.w.Whetwheel.class));
cards.add(new SetCardInfo("Whip-Spine Drake", 62, Rarity.COMMON, mage.cards.w.WhipSpineDrake.class));

View file

@ -114,6 +114,7 @@ public class IceAge extends ExpansionSet {
cards.add(new SetCardInfo("Earthlink", 363, Rarity.RARE, mage.cards.e.Earthlink.class));
cards.add(new SetCardInfo("Elder Druid", 120, Rarity.RARE, mage.cards.e.ElderDruid.class));
cards.add(new SetCardInfo("Elemental Augury", 364, Rarity.RARE, mage.cards.e.ElementalAugury.class));
cards.add(new SetCardInfo("Elkin Bottle", 292, Rarity.RARE, mage.cards.e.ElkinBottle.class));
cards.add(new SetCardInfo("Enduring Renewal", 247, Rarity.RARE, mage.cards.e.EnduringRenewal.class));
cards.add(new SetCardInfo("Energy Storm", 248, Rarity.RARE, mage.cards.e.EnergyStorm.class));
cards.add(new SetCardInfo("Enervate", 67, Rarity.COMMON, mage.cards.e.Enervate.class));

View file

@ -59,6 +59,7 @@ public class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Aerathi Berserker", 131, Rarity.UNCOMMON, mage.cards.a.AerathiBerserker.class));
cards.add(new SetCardInfo("Aisling Leprechaun", 87, Rarity.COMMON, mage.cards.a.AislingLeprechaun.class));
cards.add(new SetCardInfo("Akron Legionnaire", 170, Rarity.RARE, mage.cards.a.AkronLegionnaire.class));
cards.add(new SetCardInfo("Al-abara's Carpet", 213, Rarity.RARE, mage.cards.a.AlAbarasCarpet.class));
cards.add(new SetCardInfo("Alabaster Potion", 171, Rarity.COMMON, mage.cards.a.AlabasterPotion.class));
cards.add(new SetCardInfo("Alchor's Tomb", 214, Rarity.RARE, mage.cards.a.AlchorsTomb.class));
cards.add(new SetCardInfo("All Hallow's Eve", 2, Rarity.RARE, mage.cards.a.AllHallowsEve.class));
@ -105,6 +106,7 @@ public class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Divine Intervention", 177, Rarity.RARE, mage.cards.d.DivineIntervention.class));
cards.add(new SetCardInfo("Divine Offering", 178, Rarity.COMMON, mage.cards.d.DivineOffering.class));
cards.add(new SetCardInfo("Divine Transformation", 179, Rarity.RARE, mage.cards.d.DivineTransformation.class));
cards.add(new SetCardInfo("Dream Coat", 51, Rarity.UNCOMMON, mage.cards.d.DreamCoat.class));
cards.add(new SetCardInfo("Durkwood Boars", 96, Rarity.COMMON, mage.cards.d.DurkwoodBoars.class));
cards.add(new SetCardInfo("Dwarven Song", 141, Rarity.UNCOMMON, mage.cards.d.DwarvenSong.class));
cards.add(new SetCardInfo("Elder Land Wurm", 180, Rarity.RARE, mage.cards.e.ElderLandWurm.class));
@ -148,6 +150,7 @@ public class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Immolation", 151, Rarity.COMMON, mage.cards.i.Immolation.class));
cards.add(new SetCardInfo("In the Eye of Chaos", 61, Rarity.RARE, mage.cards.i.InTheEyeOfChaos.class));
cards.add(new SetCardInfo("Indestructible Aura", 190, Rarity.COMMON, mage.cards.i.IndestructibleAura.class));
cards.add(new SetCardInfo("Infernal Medusa", 22, Rarity.UNCOMMON, mage.cards.i.InfernalMedusa.class));
cards.add(new SetCardInfo("Invoke Prejudice", 62, Rarity.RARE, mage.cards.i.InvokePrejudice.class));
cards.add(new SetCardInfo("Ivory Guardians", 192, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class));
cards.add(new SetCardInfo("Jacques le Vert", 272, Rarity.RARE, mage.cards.j.JacquesLeVert.class));
@ -155,6 +158,7 @@ public class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Jedit Ojanen", 274, Rarity.UNCOMMON, mage.cards.j.JeditOjanen.class));
cards.add(new SetCardInfo("Jerrard of the Closed Fist", 275, Rarity.UNCOMMON, mage.cards.j.JerrardOfTheClosedFist.class));
cards.add(new SetCardInfo("Johan", 276, Rarity.RARE, mage.cards.j.Johan.class));
cards.add(new SetCardInfo("Jovial Evil", 23, Rarity.RARE, mage.cards.j.JovialEvil.class));
cards.add(new SetCardInfo("Juxtapose", 63, Rarity.RARE, mage.cards.j.Juxtapose.class));
cards.add(new SetCardInfo("Karakas", 248, Rarity.UNCOMMON, mage.cards.k.Karakas.class));
cards.add(new SetCardInfo("Kasimir the Lone Wolf", 277, Rarity.UNCOMMON, mage.cards.k.KasimirTheLoneWolf.class));
@ -199,8 +203,10 @@ public class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Planar Gate", 235, Rarity.RARE, mage.cards.p.PlanarGate.class));
cards.add(new SetCardInfo("Pradesh Gypsies", 111, Rarity.UNCOMMON, mage.cards.p.PradeshGypsies.class));
cards.add(new SetCardInfo("Presence of the Master", 200, Rarity.UNCOMMON, mage.cards.p.PresenceOfTheMaster.class));
cards.add(new SetCardInfo("Primordial Ooze", 157, Rarity.UNCOMMON, mage.cards.p.PrimordialOoze.class));
cards.add(new SetCardInfo("Princess Lucrezia", 289, Rarity.UNCOMMON, mage.cards.p.PrincessLucrezia.class));
cards.add(new SetCardInfo("Psionic Entity", 67, Rarity.RARE, mage.cards.p.PsionicEntity.class));
cards.add(new SetCardInfo("Psychic Purge", 68, Rarity.COMMON, mage.cards.p.PsychicPurge.class));
cards.add(new SetCardInfo("Pyrotechnics", 158, Rarity.COMMON, mage.cards.p.Pyrotechnics.class));
cards.add(new SetCardInfo("Rabid Wombat", 112, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class));
cards.add(new SetCardInfo("Radjan Spirit", 113, Rarity.UNCOMMON, mage.cards.r.RadjanSpirit.class));
@ -240,6 +246,7 @@ public class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Sylvan Library", 121, Rarity.UNCOMMON, mage.cards.s.SylvanLibrary.class));
cards.add(new SetCardInfo("Sylvan Paradise", 122, Rarity.UNCOMMON, mage.cards.s.SylvanParadise.class));
cards.add(new SetCardInfo("Syphon Soul", 32, Rarity.COMMON, mage.cards.s.SyphonSoul.class));
cards.add(new SetCardInfo("Telekinesis", 79, Rarity.RARE, mage.cards.t.Telekinesis.class));
cards.add(new SetCardInfo("Teleport", 80, Rarity.RARE, mage.cards.t.Teleport.class));
cards.add(new SetCardInfo("Tetsuo Umezawa", 302, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class));
cards.add(new SetCardInfo("The Abyss", 34, Rarity.RARE, mage.cards.t.TheAbyss.class));
@ -257,6 +264,7 @@ public class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Triassic Egg", 242, Rarity.RARE, mage.cards.t.TriassicEgg.class));
cards.add(new SetCardInfo("Tuknir Deathlock", 307, Rarity.RARE, mage.cards.t.TuknirDeathlock.class));
cards.add(new SetCardInfo("Tundra Wolves", 209, Rarity.COMMON, mage.cards.t.TundraWolves.class));
cards.add(new SetCardInfo("Typhoon", 123, Rarity.RARE, mage.cards.t.Typhoon.class));
cards.add(new SetCardInfo("Underworld Dreams", 38, Rarity.UNCOMMON, mage.cards.u.UnderworldDreams.class));
cards.add(new SetCardInfo("Untamed Wilds", 124, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class));
cards.add(new SetCardInfo("Urborg", 255, Rarity.UNCOMMON, mage.cards.u.Urborg.class));

View file

@ -93,6 +93,7 @@ public class LimitedEditionAlpha extends ExpansionSet {
cards.add(new SetCardInfo("Earthquake", 147, Rarity.RARE, mage.cards.e.Earthquake.class));
cards.add(new SetCardInfo("Elvish Archers", 100, Rarity.RARE, mage.cards.e.ElvishArchers.class));
cards.add(new SetCardInfo("Evil Presence", 16, Rarity.UNCOMMON, mage.cards.e.EvilPresence.class));
cards.add(new SetCardInfo("False Orders", 148, Rarity.COMMON, mage.cards.f.FalseOrders.class));
cards.add(new SetCardInfo("Farmstead", 203, Rarity.RARE, mage.cards.f.Farmstead.class));
cards.add(new SetCardInfo("Fastbond", 101, Rarity.RARE, mage.cards.f.Fastbond.class));
cards.add(new SetCardInfo("Fear", 17, Rarity.COMMON, mage.cards.f.Fear.class));

View file

@ -94,6 +94,7 @@ public class LimitedEditionBeta extends ExpansionSet {
cards.add(new SetCardInfo("Earthquake", 148, Rarity.RARE, mage.cards.e.Earthquake.class));
cards.add(new SetCardInfo("Elvish Archers", 100, Rarity.RARE, mage.cards.e.ElvishArchers.class));
cards.add(new SetCardInfo("Evil Presence", 16, Rarity.UNCOMMON, mage.cards.e.EvilPresence.class));
cards.add(new SetCardInfo("False Orders", 149, Rarity.COMMON, mage.cards.f.FalseOrders.class));
cards.add(new SetCardInfo("Farmstead", 205, Rarity.RARE, mage.cards.f.Farmstead.class));
cards.add(new SetCardInfo("Fastbond", 101, Rarity.RARE, mage.cards.f.Fastbond.class));
cards.add(new SetCardInfo("Fear", 17, Rarity.COMMON, mage.cards.f.Fear.class));

View file

@ -195,6 +195,7 @@ public class MastersEdition extends ExpansionSet {
cards.add(new SetCardInfo("Pox", 82, Rarity.RARE, mage.cards.p.Pox.class));
cards.add(new SetCardInfo("Preacher", 24, Rarity.RARE, mage.cards.p.Preacher.class));
cards.add(new SetCardInfo("Primal Order", 125, Rarity.RARE, mage.cards.p.PrimalOrder.class));
cards.add(new SetCardInfo("Psychic Purge", 45, Rarity.UNCOMMON, mage.cards.p.PsychicPurge.class));
cards.add(new SetCardInfo("Psychic Venom", 46, Rarity.COMMON, mage.cards.p.PsychicVenom.class));
cards.add(new SetCardInfo("Pyroblast", 107, Rarity.COMMON, mage.cards.p.Pyroblast.class));
cards.add(new SetCardInfo("Rabid Wombat", 126, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class));
@ -224,6 +225,7 @@ public class MastersEdition extends ExpansionSet {
cards.add(new SetCardInfo("Swamp", 189, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Sylvan Library", 133, Rarity.RARE, mage.cards.s.SylvanLibrary.class));
cards.add(new SetCardInfo("Tawnos's Coffin", 169, Rarity.RARE, mage.cards.t.TawnossCoffin.class));
cards.add(new SetCardInfo("Telekinesis", 52, Rarity.COMMON, mage.cards.t.Telekinesis.class));
cards.add(new SetCardInfo("Thawing Glaciers", 180, Rarity.RARE, mage.cards.t.ThawingGlaciers.class));
cards.add(new SetCardInfo("Thicket Basilisk", 134, Rarity.UNCOMMON, mage.cards.t.ThicketBasilisk.class));
cards.add(new SetCardInfo("Thorn Thallid", 135, Rarity.COMMON, ThornThallid.class));

View file

@ -114,6 +114,7 @@ public class MastersEditionII extends ExpansionSet {
cards.add(new SetCardInfo("Ebon Praetor", 89, Rarity.RARE, mage.cards.e.EbonPraetor.class));
cards.add(new SetCardInfo("Ebon Stronghold", 228, Rarity.UNCOMMON, mage.cards.e.EbonStronghold.class));
cards.add(new SetCardInfo("Elemental Augury", 193, Rarity.RARE, mage.cards.e.ElementalAugury.class));
cards.add(new SetCardInfo("Elkin Bottle", 207, Rarity.RARE, mage.cards.e.ElkinBottle.class));
cards.add(new SetCardInfo("Elven Lyre", 208, Rarity.COMMON, mage.cards.e.ElvenLyre.class));
cards.add(new SetCardInfo("Elvish Farmer", 156, Rarity.RARE, mage.cards.e.ElvishFarmer.class));
cards.add(new SetCardInfo("Elvish Hunter", 157, Rarity.COMMON, ElvishHunter.class));

View file

@ -57,6 +57,7 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Acid Rain", 36, Rarity.RARE, mage.cards.a.AcidRain.class));
cards.add(new SetCardInfo("Aesthir Glider", 176, Rarity.COMMON, AesthirGlider.class));
cards.add(new SetCardInfo("Air Elemental", 37, Rarity.UNCOMMON, mage.cards.a.AirElemental.class));
cards.add(new SetCardInfo("Al-abara's Carpet", 177, Rarity.RARE, mage.cards.a.AlAbarasCarpet.class));
cards.add(new SetCardInfo("Alaborn Musketeer", 1, Rarity.COMMON, mage.cards.a.AlabornMusketeer.class));
cards.add(new SetCardInfo("Alaborn Trooper", 2, Rarity.COMMON, mage.cards.a.AlabornTrooper.class));
cards.add(new SetCardInfo("Aladdin", 106, Rarity.RARE, mage.cards.a.Aladdin.class));
@ -95,7 +96,7 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Clay Statue", 189, Rarity.UNCOMMON, mage.cards.c.ClayStatue.class));
cards.add(new SetCardInfo("Clockwork Avian", 190, Rarity.UNCOMMON, mage.cards.c.ClockworkAvian.class));
cards.add(new SetCardInfo("Clockwork Gnomes", 191, Rarity.UNCOMMON, mage.cards.c.ClockworkGnomes.class));
cards.add(new SetCardInfo("Clockwork Swarm", 192, Rarity.COMMON, mage.cards.c.ClockworkSwarm.class));
cards.add(new SetCardInfo("Clockwork Swarm", 192, Rarity.COMMON, mage.cards.c.ClockworkSwarm.class));
cards.add(new SetCardInfo("Cloud Dragon", 41, Rarity.RARE, mage.cards.c.CloudDragon.class));
cards.add(new SetCardInfo("Cloud Spirit", 42, Rarity.COMMON, mage.cards.c.CloudSpirit.class));
cards.add(new SetCardInfo("Colossus of Sardia", 193, Rarity.RARE, mage.cards.c.ColossusOfSardia.class));
@ -186,7 +187,7 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Mahamoti Djinn", 52, Rarity.RARE, mage.cards.m.MahamotiDjinn.class));
cards.add(new SetCardInfo("Mana Matrix", 213, Rarity.RARE, mage.cards.m.ManaMatrix.class));
cards.add(new SetCardInfo("Mana Vault", 214, Rarity.RARE, mage.cards.m.ManaVault.class));
cards.add(new SetCardInfo("Martyr's Cry", 19, Rarity.RARE, mage.cards.m.MartyrsCry.class));
cards.add(new SetCardInfo("Martyr's Cry", 19, Rarity.RARE, mage.cards.m.MartyrsCry.class));
cards.add(new SetCardInfo("Martyrs of Korlis", 20, Rarity.UNCOMMON, mage.cards.m.MartyrsOfKorlis.class));
cards.add(new SetCardInfo("Maze of Ith", 246, Rarity.RARE, mage.cards.m.MazeOfIth.class));
cards.add(new SetCardInfo("Mightstone", 215, Rarity.COMMON, mage.cards.m.Mightstone.class));
@ -243,10 +244,10 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Sinkhole", 97, Rarity.RARE, mage.cards.s.Sinkhole.class));
cards.add(new SetCardInfo("Sleight of Hand", 62, Rarity.COMMON, mage.cards.s.SleightOfHand.class));
cards.add(new SetCardInfo("Smoke", 137, Rarity.RARE, mage.cards.s.Smoke.class));
cards.add(new SetCardInfo("Soldevi Golem", 228, Rarity.UNCOMMON, mage.cards.s.SoldeviGolem.class));
cards.add(new SetCardInfo("Soldevi Golem", 228, Rarity.UNCOMMON, mage.cards.s.SoldeviGolem.class));
cards.add(new SetCardInfo("Soldevi Machinist", 63, Rarity.UNCOMMON, mage.cards.s.SoldeviMachinist.class));
cards.add(new SetCardInfo("Sol Ring", 227, Rarity.RARE, mage.cards.s.SolRing.class));
cards.add(new SetCardInfo("Soldevi Golem", 228, Rarity.UNCOMMON, mage.cards.s.SoldeviGolem.class));
cards.add(new SetCardInfo("Soldevi Golem", 228, Rarity.UNCOMMON, mage.cards.s.SoldeviGolem.class));
cards.add(new SetCardInfo("Soul Shred", 98, Rarity.COMMON, mage.cards.s.SoulShred.class));
cards.add(new SetCardInfo("Southern Elephant", 167, Rarity.COMMON, mage.cards.s.SouthernElephant.class));
cards.add(new SetCardInfo("Spotted Griffin", 28, Rarity.COMMON, mage.cards.s.SpottedGriffin.class));

View file

@ -174,6 +174,7 @@ public class MercadianMasques extends ExpansionSet {
cards.add(new SetCardInfo("High Market", 320, Rarity.RARE, mage.cards.h.HighMarket.class));
cards.add(new SetCardInfo("High Seas", 83, Rarity.UNCOMMON, mage.cards.h.HighSeas.class));
cards.add(new SetCardInfo("Highway Robber", 139, Rarity.COMMON, mage.cards.h.HighwayRobber.class));
cards.add(new SetCardInfo("Honor the Fallen", 21, Rarity.RARE, mage.cards.h.HonorTheFallen.class));
cards.add(new SetCardInfo("Hoodwink", 84, Rarity.COMMON, mage.cards.h.Hoodwink.class));
cards.add(new SetCardInfo("Horned Troll", 251, Rarity.COMMON, mage.cards.h.HornedTroll.class));
cards.add(new SetCardInfo("Horn of Plenty", 298, Rarity.RARE, mage.cards.h.HornOfPlenty.class));
@ -278,6 +279,7 @@ public class MercadianMasques extends ExpansionSet {
cards.add(new SetCardInfo("Sailmonger", 95, Rarity.UNCOMMON, mage.cards.s.Sailmonger.class));
cards.add(new SetCardInfo("Sand Squid", 96, Rarity.RARE, mage.cards.s.SandSquid.class));
cards.add(new SetCardInfo("Sandstone Needle", 326, Rarity.COMMON, mage.cards.s.SandstoneNeedle.class));
cards.add(new SetCardInfo("Saprazzan Bailiff", 97, Rarity.RARE, mage.cards.s.SaprazzanBailiff.class));
cards.add(new SetCardInfo("Saprazzan Cove", 327, Rarity.UNCOMMON, mage.cards.s.SaprazzanCove.class));
cards.add(new SetCardInfo("Saprazzan Heir", 99, Rarity.RARE, mage.cards.s.SaprazzanHeir.class));
cards.add(new SetCardInfo("Saprazzan Legate", 100, Rarity.UNCOMMON, mage.cards.s.SaprazzanLegate.class));

View file

@ -304,6 +304,7 @@ public class Mirage extends ExpansionSet {
cards.add(new SetCardInfo("Telim'Tor's Edict", 198, Rarity.RARE, mage.cards.t.TelimTorsEdict.class));
cards.add(new SetCardInfo("Thirst", 99, Rarity.COMMON, mage.cards.t.Thirst.class));
cards.add(new SetCardInfo("Tidal Wave", 100, Rarity.UNCOMMON, mage.cards.t.TidalWave.class));
cards.add(new SetCardInfo("Tombstone Stairwell", 47, Rarity.RARE, mage.cards.t.TombstoneStairwell.class));
cards.add(new SetCardInfo("Tranquil Domain", 143, Rarity.COMMON, mage.cards.t.TranquilDomain.class));
cards.add(new SetCardInfo("Tropical Storm", 144, Rarity.UNCOMMON, mage.cards.t.TropicalStorm.class));
cards.add(new SetCardInfo("Uktabi Faerie", 145, Rarity.COMMON, mage.cards.u.UktabiFaerie.class));

View file

@ -296,6 +296,7 @@ public class RavnicaCityOfGuilds extends ExpansionSet {
cards.add(new SetCardInfo("Smash", 143, Rarity.COMMON, mage.cards.s.Smash.class));
cards.add(new SetCardInfo("Snapping Drake", 64, Rarity.COMMON, mage.cards.s.SnappingDrake.class));
cards.add(new SetCardInfo("Sparkmage Apprentice", 144, Rarity.COMMON, mage.cards.s.SparkmageApprentice.class));
cards.add(new SetCardInfo("Spawnbroker", 65, Rarity.RARE, mage.cards.s.Spawnbroker.class));
cards.add(new SetCardInfo("Spectral Searchlight", 271, Rarity.UNCOMMON, mage.cards.s.SpectralSearchlight.class));
cards.add(new SetCardInfo("Stasis Cell", 66, Rarity.COMMON, mage.cards.s.StasisCell.class));
cards.add(new SetCardInfo("Stinkweed Imp", 107, Rarity.COMMON, mage.cards.s.StinkweedImp.class));

View file

@ -58,6 +58,7 @@ public class Torment extends ExpansionSet {
cards.add(new SetCardInfo("Acorn Harvest", 118, Rarity.COMMON, mage.cards.a.AcornHarvest.class));
cards.add(new SetCardInfo("Ambassador Laquatus", 23, Rarity.RARE, mage.cards.a.AmbassadorLaquatus.class));
cards.add(new SetCardInfo("Angel of Retribution", 1, Rarity.RARE, mage.cards.a.AngelOfRetribution.class));
cards.add(new SetCardInfo("Anurid Scavenger", 119, Rarity.COMMON, mage.cards.a.AnuridScavenger.class));
cards.add(new SetCardInfo("Aquamoeba", 24, Rarity.COMMON, mage.cards.a.Aquamoeba.class));
cards.add(new SetCardInfo("Arrogant Wurm", 120, Rarity.UNCOMMON, mage.cards.a.ArrogantWurm.class));
cards.add(new SetCardInfo("Aven Trooper", 2, Rarity.COMMON, mage.cards.a.AvenTrooper.class));
@ -93,6 +94,7 @@ public class Torment extends ExpansionSet {
cards.add(new SetCardInfo("Dwell on the Past", 124, Rarity.UNCOMMON, mage.cards.d.DwellOnThePast.class));
cards.add(new SetCardInfo("Enslaved Dwarf", 96, Rarity.COMMON, mage.cards.e.EnslavedDwarf.class));
cards.add(new SetCardInfo("Faceless Butcher", 60, Rarity.COMMON, mage.cards.f.FacelessButcher.class));
cards.add(new SetCardInfo("False Memories", 37, Rarity.RARE, mage.cards.f.FalseMemories.class));
cards.add(new SetCardInfo("Far Wanderings", 125, Rarity.COMMON, mage.cards.f.FarWanderings.class));
cards.add(new SetCardInfo("Fiery Temper", 97, Rarity.COMMON, mage.cards.f.FieryTemper.class));
cards.add(new SetCardInfo("Flash of Defiance", 99, Rarity.COMMON, mage.cards.f.FlashOfDefiance.class));
@ -102,6 +104,7 @@ public class Torment extends ExpansionSet {
cards.add(new SetCardInfo("Gravegouger", 62, Rarity.COMMON, mage.cards.g.Gravegouger.class));
cards.add(new SetCardInfo("Grim Lavamancer", 100, Rarity.RARE, mage.cards.g.GrimLavamancer.class));
cards.add(new SetCardInfo("Grotesque Hybrid", 63, Rarity.UNCOMMON, mage.cards.g.GrotesqueHybrid.class));
cards.add(new SetCardInfo("Gurzigost", 126, Rarity.RARE, mage.cards.g.Gurzigost.class));
cards.add(new SetCardInfo("Hell-Bent Raider", 101, Rarity.RARE, mage.cards.h.HellBentRaider.class));
cards.add(new SetCardInfo("Hydromorph Guardian", 39, Rarity.COMMON, mage.cards.h.HydromorphGuardian.class));
cards.add(new SetCardInfo("Hydromorph Gull", 40, Rarity.UNCOMMON, mage.cards.h.HydromorphGull.class));
@ -144,6 +147,7 @@ public class Torment extends ExpansionSet {
cards.add(new SetCardInfo("Pay No Heed", 12, Rarity.COMMON, mage.cards.p.PayNoHeed.class));
cards.add(new SetCardInfo("Petradon", 108, Rarity.RARE, mage.cards.p.Petradon.class));
cards.add(new SetCardInfo("Petravark", 109, Rarity.COMMON, mage.cards.p.Petravark.class));
cards.add(new SetCardInfo("Pitchstone Wall", 110, Rarity.UNCOMMON, mage.cards.p.PitchstoneWall.class));
cards.add(new SetCardInfo("Plagiarize", 44, Rarity.RARE, mage.cards.p.Plagiarize.class));
cards.add(new SetCardInfo("Possessed Aven", 45, Rarity.RARE, mage.cards.p.PossessedAven.class));
cards.add(new SetCardInfo("Possessed Barbarian", 111, Rarity.RARE, mage.cards.p.PossessedBarbarian.class));

View file

@ -94,6 +94,7 @@ public class UnlimitedEdition extends ExpansionSet {
cards.add(new SetCardInfo("Earthquake", 147, Rarity.RARE, mage.cards.e.Earthquake.class));
cards.add(new SetCardInfo("Elvish Archers", 100, Rarity.RARE, mage.cards.e.ElvishArchers.class));
cards.add(new SetCardInfo("Evil Presence", 16, Rarity.UNCOMMON, mage.cards.e.EvilPresence.class));
cards.add(new SetCardInfo("False Orders", 148, Rarity.COMMON, mage.cards.f.FalseOrders.class));
cards.add(new SetCardInfo("Farmstead", 204, Rarity.RARE, mage.cards.f.Farmstead.class));
cards.add(new SetCardInfo("Fastbond", 101, Rarity.RARE, mage.cards.f.Fastbond.class));
cards.add(new SetCardInfo("Fear", 17, Rarity.COMMON, mage.cards.f.Fear.class));

View file

@ -49,6 +49,8 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
private UUID onlyIfControlledByPlayer;
private String targetName;
// used for Telekinesis - skips next two untap steps if true
private boolean twoSteps;
// holds the info what target was already handled in Untap of its controller
private final Map<UUID, Boolean> handledTargetsDuringTurn = new HashMap<>();
@ -63,7 +65,7 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
}
public DontUntapInControllersNextUntapStepTargetEffect(String targetName) {
this(targetName, null);
this(targetName, false, null);
}
/**
@ -73,14 +75,20 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
* controlled by that controller, null = it works for all players
*/
public DontUntapInControllersNextUntapStepTargetEffect(String targetName, UUID onlyIfControlledByPlayer) {
this(targetName, false, onlyIfControlledByPlayer);
}
public DontUntapInControllersNextUntapStepTargetEffect(String targetName, boolean twoSteps, UUID onlyIfControlledByPlayer) {
super(Duration.Custom, Outcome.Detriment, false, true);
this.targetName = targetName;
this.twoSteps = twoSteps;
this.onlyIfControlledByPlayer = onlyIfControlledByPlayer;
}
public DontUntapInControllersNextUntapStepTargetEffect(final DontUntapInControllersNextUntapStepTargetEffect effect) {
super(effect);
this.targetName = effect.targetName;
this.twoSteps = effect.twoSteps;
this.handledTargetsDuringTurn.putAll(effect.handledTargetsDuringTurn);
this.onlyIfControlledByPlayer = effect.onlyIfControlledByPlayer;
}
@ -112,7 +120,7 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
// the check if a permanent untap pahse is already handled is needed if multiple effects are added to prevent untap in next untap step of controller
// the check if a permanent untap phase is already handled is needed if multiple effects are added to prevent untap in next untap step of controller
// if we don't check it for every untap step of a turn only one effect would be consumed instead of all be valid for the next untap step
if (event.getType() == EventType.UNTAP_STEP) {
boolean allHandled = true;
@ -127,13 +135,14 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
allHandled = false;
} else if (!handledTargetsDuringTurn.get(targetId)) {
// if it was already ready to be handled on an previous Untap step set it to done if not already so
handledTargetsDuringTurn.put(targetId, true);
handledTargetsDuringTurn.put(targetId, !twoSteps);
}
} else {
allHandled = false;
}
}
}
if (allHandled) {
discard();
}
@ -146,7 +155,7 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null && game.getActivePlayerId().equals(permanent.getControllerId())) {
if ((onlyIfControlledByPlayer == null) || game.getActivePlayerId().equals(onlyIfControlledByPlayer)) { // If onlyIfControlledByPlayer is set, then don't apply unless we're currently controlled by the specified player.
handledTargetsDuringTurn.put(event.getTargetId(), true);
handledTargetsDuringTurn.put(event.getTargetId(), !twoSteps);
return true;
}
}
@ -162,11 +171,11 @@ public class DontUntapInControllersNextUntapStepTargetEffect extends ContinuousR
}
if (targetName != null && !targetName.isEmpty()) {
if (targetName.equals("Those creatures") || targetName.equals("They")) {
return targetName + " don't untap during their controller's next untap step";
return targetName + " don't untap during their controller's next " + (twoSteps ? "two " : "") + "untap step" + (twoSteps ? "s" : "");
} else
return targetName + " doesn't untap during its controller's next untap step";
return targetName + " doesn't untap during its controller's next " + (twoSteps ? "two " : "") + "untap step" + (twoSteps ? "s" : "");
} else {
return "target " + (mode == null ? "creature" : mode.getTargets().get(0).getTargetName()) + " doesn't untap during its controller's next untap step";
return "target " + (mode == null ? "creature" : mode.getTargets().get(0).getTargetName()) + " doesn't untap during its controller's next " + (twoSteps ? "two " : "") + "untap step" + (twoSteps ? "s" : "");
}
}

View file

@ -72,6 +72,7 @@ public class SacrificeSourceUnlessPaysEffect extends OneShotEffect {
if (costText.toLowerCase().startsWith("discard")
|| costText.toLowerCase().startsWith("remove")
|| costText.toLowerCase().startsWith("return")
|| costText.toLowerCase().startsWith("put")
|| costText.toLowerCase().startsWith("exile")
|| costText.toLowerCase().startsWith("sacrifice")) {
sb.append(costText.substring(0, 1).toLowerCase());

View file

@ -13,7 +13,7 @@ public enum PhaseStep {
PRECOMBAT_MAIN ("Precombat Main", 3,"precombat main step"),
BEGIN_COMBAT ("Begin Combat", 4, "begin combat step"),
DECLARE_ATTACKERS ("Declare Attackers", 5, "declare attackers step"),
DECLARE_BLOCKERS ("Declare Blockers", 6, "declare blockers"),
DECLARE_BLOCKERS ("Declare Blockers", 6, "declare blockers step"),
FIRST_COMBAT_DAMAGE ("First Combat Damage", 7, "first combat damage"),
COMBAT_DAMAGE ("Combat Damage", 8, "combat damage step"),
END_COMBAT ("End Combat", 9, "end combat step"),

View file

@ -0,0 +1,50 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com AS IS AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.game.permanent.token;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.MageInt;
import mage.abilities.keyword.HasteAbility;
/**
*
* @author L_J
*/
public class TombspawnZombieToken extends Token {
public TombspawnZombieToken() {
super("Tombspawn", "2/2 black Zombie creature token with haste named Tombspawn");
cardType.add(CardType.CREATURE);
subtype.add(SubType.ZOMBIE);
color.setBlack(true);
power = new MageInt(2);
toughness = new MageInt(2);
this.addAbility(HasteAbility.getInstance());
}
}

View file

@ -0,0 +1,100 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.watchers.common;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.events.GameEvent;
import mage.watchers.Watcher;
/**
*
* @author L_J
*/
public class BlockedByOnlyOneCreatureThisCombatWatcher extends Watcher {
private final Map<CombatGroup, UUID> blockedByOneCreature = new HashMap<>();
public BlockedByOnlyOneCreatureThisCombatWatcher() {
super(BlockedByOnlyOneCreatureThisCombatWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public BlockedByOnlyOneCreatureThisCombatWatcher(final BlockedByOnlyOneCreatureThisCombatWatcher watcher) {
super(watcher);
this.blockedByOneCreature.putAll(watcher.blockedByOneCreature);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.BEGIN_COMBAT_STEP_PRE) {
this.blockedByOneCreature.clear();
}
else if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) {
CombatGroup combatGroup = game.getCombat().findGroup(event.getTargetId());
if (combatGroup != null) {
if (combatGroup.getBlockers().size() == 1) {
if (!blockedByOneCreature.containsKey(combatGroup)) {
blockedByOneCreature.put(combatGroup, event.getSourceId());
}
else if (blockedByOneCreature.get(combatGroup) != event.getSourceId()) {
blockedByOneCreature.put(combatGroup, null);
}
}
else if (combatGroup.getBlockers().size() > 1) {
blockedByOneCreature.put(combatGroup, null);
}
}
}
}
public Set<CombatGroup> getBlockedOnlyByCreature(UUID creature) {
Set<CombatGroup> combatGroups = new HashSet<>();
for (Map.Entry<CombatGroup, UUID> entry : blockedByOneCreature.entrySet()) {
if (entry.getValue() != null) {
if (entry.getValue().equals(creature)) {
combatGroups.add(entry.getKey());
}
}
}
if (combatGroups.size() > 0) {
return combatGroups;
}
return null;
}
@Override
public BlockedByOnlyOneCreatureThisCombatWatcher copy() {
return new BlockedByOnlyOneCreatureThisCombatWatcher(this);
}
}