mirror of
https://github.com/correl/mage.git
synced 2024-12-26 03:00:11 +00:00
commit
fcc7b63547
58 changed files with 3538 additions and 83 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,20 +124,36 @@ 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 {
|
||||
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(
|
||||
"Requested image doesn't fit the requirement for key (<cardname>#<setname>#<collectorID>): " + key);
|
||||
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
110
Mage.Sets/src/mage/cards/a/AlAbarasCarpet.java
Normal file
110
Mage.Sets/src/mage/cards/a/AlAbarasCarpet.java
Normal 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;
|
||||
}
|
||||
}
|
121
Mage.Sets/src/mage/cards/a/AnuridScavenger.java
Normal file
121
Mage.Sets/src/mage/cards/a/AnuridScavenger.java
Normal 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);
|
||||
}
|
||||
}
|
161
Mage.Sets/src/mage/cards/b/BalduvianWarlord.java
Normal file
161
Mage.Sets/src/mage/cards/b/BalduvianWarlord.java
Normal 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 Warlord’s 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;
|
||||
}
|
||||
}
|
146
Mage.Sets/src/mage/cards/d/DreamCoat.java
Normal file
146
Mage.Sets/src/mage/cards/d/DreamCoat.java
Normal 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);
|
||||
}
|
||||
}
|
153
Mage.Sets/src/mage/cards/e/ElkinBottle.java
Normal file
153
Mage.Sets/src/mage/cards/e/ElkinBottle.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
62
Mage.Sets/src/mage/cards/f/FalseMemories.java
Normal file
62
Mage.Sets/src/mage/cards/f/FalseMemories.java
Normal 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);
|
||||
}
|
||||
}
|
176
Mage.Sets/src/mage/cards/f/FalseOrders.java
Normal file
176
Mage.Sets/src/mage/cards/f/FalseOrders.java
Normal 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 Warlord’s 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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
@ -130,6 +131,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);
|
||||
this.staticText = "Until the beginning of your next upkeep, you may play that card.";
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
129
Mage.Sets/src/mage/cards/g/Gurzigost.java
Normal file
129
Mage.Sets/src/mage/cards/g/Gurzigost.java
Normal 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);
|
||||
}
|
||||
}
|
139
Mage.Sets/src/mage/cards/h/Heroism.java
Normal file
139
Mage.Sets/src/mage/cards/h/Heroism.java
Normal 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;
|
||||
}
|
||||
}
|
109
Mage.Sets/src/mage/cards/h/HonorTheFallen.java
Normal file
109
Mage.Sets/src/mage/cards/h/HonorTheFallen.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
80
Mage.Sets/src/mage/cards/i/InfernalMedusa.java
Normal file
80
Mage.Sets/src/mage/cards/i/InfernalMedusa.java
Normal 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);
|
||||
}
|
||||
}
|
106
Mage.Sets/src/mage/cards/j/JovialEvil.java
Normal file
106
Mage.Sets/src/mage/cards/j/JovialEvil.java
Normal 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);
|
||||
}
|
||||
}
|
133
Mage.Sets/src/mage/cards/l/LostHours.java
Normal file
133
Mage.Sets/src/mage/cards/l/LostHours.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
110
Mage.Sets/src/mage/cards/p/PitchstoneWall.java
Normal file
110
Mage.Sets/src/mage/cards/p/PitchstoneWall.java
Normal 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();
|
||||
}
|
||||
}
|
113
Mage.Sets/src/mage/cards/p/PrimordialOoze.java
Normal file
113
Mage.Sets/src/mage/cards/p/PrimordialOoze.java
Normal 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;
|
||||
}
|
||||
}
|
114
Mage.Sets/src/mage/cards/p/PsychicPurge.java
Normal file
114
Mage.Sets/src/mage/cards/p/PsychicPurge.java
Normal 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.";
|
||||
}
|
||||
}
|
108
Mage.Sets/src/mage/cards/s/SamiteCenserBearer.java
Normal file
108
Mage.Sets/src/mage/cards/s/SamiteCenserBearer.java
Normal 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;
|
||||
}
|
||||
}
|
119
Mage.Sets/src/mage/cards/s/SaprazzanBailiff.java
Normal file
119
Mage.Sets/src/mage/cards/s/SaprazzanBailiff.java
Normal 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;
|
||||
}
|
||||
}
|
174
Mage.Sets/src/mage/cards/s/Spawnbroker.java
Normal file
174
Mage.Sets/src/mage/cards/s/Spawnbroker.java
Normal 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);
|
||||
}
|
||||
}
|
113
Mage.Sets/src/mage/cards/s/SpellwildOuphe.java
Normal file
113
Mage.Sets/src/mage/cards/s/SpellwildOuphe.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
64
Mage.Sets/src/mage/cards/t/Telekinesis.java
Normal file
64
Mage.Sets/src/mage/cards/t/Telekinesis.java
Normal 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);
|
||||
}
|
||||
}
|
134
Mage.Sets/src/mage/cards/t/ThelonsCurse.java
Normal file
134
Mage.Sets/src/mage/cards/t/ThelonsCurse.java
Normal 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;
|
||||
}
|
||||
}
|
232
Mage.Sets/src/mage/cards/t/TombstoneStairwell.java
Normal file
232
Mage.Sets/src/mage/cards/t/TombstoneStairwell.java
Normal 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;
|
||||
}
|
||||
}
|
106
Mage.Sets/src/mage/cards/t/Typhoon.java
Normal file
106
Mage.Sets/src/mage/cards/t/Typhoon.java
Normal 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);
|
||||
}
|
||||
}
|
70
Mage.Sets/src/mage/cards/v/VensersDiffusion.java
Normal file
70
Mage.Sets/src/mage/cards/v/VensersDiffusion.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,6 +329,7 @@ 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("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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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" : "");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue