mirror of
https://github.com/correl/mage.git
synced 2025-01-14 03:00:10 +00:00
commit
7b71f12f5d
86 changed files with 2932 additions and 338 deletions
BIN
Mage.Client/plugins/sounds/OnPlayerJoinedTable.wav
Normal file
BIN
Mage.Client/plugins/sounds/OnPlayerJoinedTable.wav
Normal file
Binary file not shown.
BIN
Mage.Client/release/backgrounds/Blue-Abstract.jpg
Normal file
BIN
Mage.Client/release/backgrounds/Blue-Abstract.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 KiB |
BIN
Mage.Client/release/backgrounds/Distant-Galaxy.jpg
Normal file
BIN
Mage.Client/release/backgrounds/Distant-Galaxy.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 254 KiB |
BIN
Mage.Client/release/backgrounds/Galaxy.jpg
Normal file
BIN
Mage.Client/release/backgrounds/Galaxy.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 273 KiB |
BIN
Mage.Client/release/backgrounds/Gray.jpg
Normal file
BIN
Mage.Client/release/backgrounds/Gray.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
|
@ -0,0 +1,28 @@
|
|||
NAME:Gadin's Robots
|
||||
4 [DDF:72] Darksteel Citadel
|
||||
3 [MMA:220] Blinkmoth Nexus
|
||||
3 [MBS:145] Inkmoth Nexus
|
||||
4 [NPH:76] Vault Skirge
|
||||
4 [HOP:110] Cranial Plating
|
||||
4 [MMA:223] Glimmervoid
|
||||
3 [LRW:261] Springleaf Drum
|
||||
2 [MMA:198] Arcbound Ravager
|
||||
1 [RTR:265] Mountain
|
||||
3 [SOM:154] Etched Champion
|
||||
4 [DDF:48] Master of Etherium
|
||||
4 [M11:211] Ornithopter
|
||||
3 [SOM:179] Mox Opal
|
||||
4 [SOM:91] Galvanic Blast
|
||||
4 [DDF:71] Thoughtcast
|
||||
1 [RTR:255] Island
|
||||
3 [SOM:174] Memnite
|
||||
3 [MBS:131] Signal Pest
|
||||
3 [DDF:44] Steel Overseer
|
||||
SB: 1 [ROE:92] Unified Will
|
||||
SB: 3 [NPH:159] Spellskite
|
||||
SB: 1 [NPH:102] Whipflare
|
||||
SB: 3 [MMA:213] Relic of Progenitus
|
||||
SB: 1 [M13:62] Negate
|
||||
SB: 3 [MMA:106] Blood Moon
|
||||
SB: 2 [PC2:7] Ghostly Prison
|
||||
SB: 1 [ISD:127] Ancient Grudge
|
|
@ -37,7 +37,6 @@ package mage.client;
|
|||
import de.schlichtherle.truezip.file.TArchiveDetector;
|
||||
import de.schlichtherle.truezip.file.TConfig;
|
||||
import de.schlichtherle.truezip.fs.FsOutputOption;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
|
@ -479,19 +478,9 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
menu.show(component, 0, component.getHeight());
|
||||
}
|
||||
|
||||
private List<Card> getAllCards() {
|
||||
List<Card> cards = new ArrayList<Card>();
|
||||
List<CardInfo> allCards = CardRepository.instance.getAllCards();
|
||||
for (CardInfo cardInfo : allCards) {
|
||||
cards.add(cardInfo.getCard());
|
||||
}
|
||||
|
||||
return cards;
|
||||
}
|
||||
|
||||
private void checkForNewImages() {
|
||||
long beforeCall = System.currentTimeMillis();
|
||||
List<Card> cards = getAllCards();
|
||||
List<CardInfo> cards = CardRepository.instance.getAllCards();
|
||||
logger.info("Card pool load time: " + ((System.currentTimeMillis() - beforeCall) / 1000 + " seconds"));
|
||||
|
||||
String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
|
@ -507,7 +496,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
}
|
||||
|
||||
public void btnImagesActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
List<Card> cards = getAllCards();
|
||||
List<CardInfo> cards = CardRepository.instance.getAllCards();
|
||||
|
||||
String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
String path = useDefault.equals("true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
|
|
|
@ -26,8 +26,11 @@ public class HoverButton extends JPanel implements MouseListener {
|
|||
private int textOffsetY = 0;
|
||||
private int textOffsetButtonY = 2;
|
||||
private int textOffsetX = -1;
|
||||
private int topTextOffsetX = -1;
|
||||
private Dimension overlayImageSize;
|
||||
|
||||
private String topText;
|
||||
|
||||
private boolean isHovered = false;
|
||||
private boolean isSelected = false;
|
||||
private boolean drawSet = false;
|
||||
|
@ -36,6 +39,7 @@ public class HoverButton extends JPanel implements MouseListener {
|
|||
private Command observer = null;
|
||||
private Command onHover = null;
|
||||
private Color textColor = Color.white;
|
||||
private Color textBGColor = Color.black;
|
||||
|
||||
static final Font textFont = new Font("Arial", Font.PLAIN, 12);
|
||||
static final Font textFontMini = new Font("Arial", Font.PLAIN, 11);
|
||||
|
@ -100,6 +104,18 @@ public class HoverButton extends JPanel implements MouseListener {
|
|||
} else {
|
||||
g.drawImage(disabledImage, 0, 0, imageSize.width, imageSize.height, this);
|
||||
}
|
||||
if (topText != null) {
|
||||
if (useMiniFont) {
|
||||
g2d.setFont(textFontMini);
|
||||
} else {
|
||||
g2d.setFont(textFont);
|
||||
}
|
||||
topTextOffsetX = calculateOffsetForTop(g2d, topText);
|
||||
g2d.setColor(textBGColor);
|
||||
g2d.drawString(topText, topTextOffsetX+1, 13);
|
||||
g2d.setColor(textColor);
|
||||
g2d.drawString(topText, topTextOffsetX, 12);
|
||||
}
|
||||
if (overlayImage != null) {
|
||||
g.drawImage(overlayImage, (imageSize.width - overlayImageSize.width) / 2, 10, this);
|
||||
} else if (set != null) {
|
||||
|
@ -136,6 +152,15 @@ public class HoverButton extends JPanel implements MouseListener {
|
|||
return textOffsetX;
|
||||
}
|
||||
|
||||
private int calculateOffsetForTop(Graphics2D g2d, String text) {
|
||||
if (topTextOffsetX == -1) { // calculate once
|
||||
FontRenderContext frc = g2d.getFontRenderContext();
|
||||
int textWidth = (int) textFont.getStringBounds(text, frc).getWidth();
|
||||
topTextOffsetX = (imageSize.width - textWidth) / 2;
|
||||
}
|
||||
return topTextOffsetX;
|
||||
}
|
||||
|
||||
public void setTextColor(Color textColor) {
|
||||
this.textColor = textColor;
|
||||
}
|
||||
|
@ -242,4 +267,8 @@ public class HoverButton extends JPanel implements MouseListener {
|
|||
observer.execute();
|
||||
}
|
||||
}
|
||||
|
||||
public void setTopText(String topText) {
|
||||
this.topText = topText;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import mage.client.util.AudioManager;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -392,6 +393,7 @@ class UpdateSeatsTask extends SwingWorker<Void, TableView> {
|
|||
if (count > 0) {
|
||||
if (current > count) {
|
||||
MageTray.getInstance().displayMessage("New player joined your game.");
|
||||
AudioManager.playPlayerJoinedTable();
|
||||
} else {
|
||||
MageTray.getInstance().displayMessage("A player left your game.");
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
package mage.client.game;
|
||||
|
||||
import mage.MageException;
|
||||
import mage.cards.MageCard;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.cards.decks.importer.DckDeckImporter;
|
||||
|
@ -51,7 +52,9 @@ import mage.client.util.Command;
|
|||
import mage.client.util.ImageHelper;
|
||||
import mage.client.util.gui.BufferedImageBuilder;
|
||||
import mage.components.ImagePanel;
|
||||
import mage.constants.Constants;
|
||||
import mage.remote.Session;
|
||||
import mage.utils.timer.PriorityTimer;
|
||||
import mage.view.CardView;
|
||||
import mage.view.ManaPoolView;
|
||||
import mage.view.PlayerView;
|
||||
|
@ -101,6 +104,8 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
|
||||
private int avatarId = -1;
|
||||
|
||||
private PriorityTimer timer;
|
||||
|
||||
/** Creates new form PlayerPanel */
|
||||
public PlayerPanelExt() {
|
||||
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
|
||||
|
@ -114,6 +119,25 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
session = MageFrame.getSession();
|
||||
cheat.setVisible(session.isTestMode());
|
||||
cheat.setFocusable(false);
|
||||
|
||||
long delay = 1000L;
|
||||
timer = new PriorityTimer(Constants.PRIORITY_TIME_SEC, delay, new mage.interfaces.Action() {
|
||||
@Override
|
||||
public void execute() throws MageException {
|
||||
// do nothing
|
||||
}
|
||||
});
|
||||
final PriorityTimer pt = timer;
|
||||
timer.setTaskOnTick(new mage.interfaces.Action() {
|
||||
@Override
|
||||
public void execute() throws MageException {
|
||||
int priorityTimeValue = pt.getCount();
|
||||
String text = getPriorityTimeLeftString(priorityTimeValue);
|
||||
PlayerPanelExt.this.avatar.setTopText(text);
|
||||
PlayerPanelExt.this.avatar.repaint();
|
||||
}
|
||||
});
|
||||
timer.init();
|
||||
}
|
||||
|
||||
public void update(PlayerView player) {
|
||||
|
@ -182,16 +206,22 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
}
|
||||
}
|
||||
this.avatar.setText(player.getName());
|
||||
String priorityTimeValue = getPriorityTimeLeftString(player);
|
||||
this.timer.setCount(player.getPriorityTimeLeft());
|
||||
this.avatar.setTopText(priorityTimeValue);
|
||||
this.btnPlayer.setText(player.getName());
|
||||
if (player.isActive()) {
|
||||
this.avatar.setBorder(greenBorder);
|
||||
this.btnPlayer.setBorder(greenBorder);
|
||||
this.timer.resume();
|
||||
} else if (player.hasLeft()) {
|
||||
this.avatar.setBorder(redBorder);
|
||||
this.btnPlayer.setBorder(redBorder);
|
||||
this.timer.pause();
|
||||
} else {
|
||||
this.avatar.setBorder(emptyBorder);
|
||||
this.btnPlayer.setBorder(emptyBorder);
|
||||
this.timer.pause();
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
|
@ -216,6 +246,18 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
update(player.getManaPool());
|
||||
}
|
||||
|
||||
private String getPriorityTimeLeftString(PlayerView player) {
|
||||
int priorityTimeLeft = player.getPriorityTimeLeft();
|
||||
return getPriorityTimeLeftString(priorityTimeLeft);
|
||||
}
|
||||
|
||||
private String getPriorityTimeLeftString(int priorityTimeLeft) {
|
||||
int h = priorityTimeLeft / 3600;
|
||||
int m = (priorityTimeLeft % 3600) / 60;
|
||||
int s = priorityTimeLeft % 60;
|
||||
return (h < 10 ? "0" : "") + h + ":" + (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
|
||||
}
|
||||
|
||||
protected void update(ManaPoolView pool) {
|
||||
manaLabels.get("B").setText(Integer.toString(pool.getBlack()));
|
||||
manaLabels.get("R").setText(Integer.toString(pool.getRed()));
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package mage.client.util;
|
||||
|
||||
import java.io.File;
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.Clip;
|
||||
import javax.sound.sampled.DataLine;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.sound.sampled.*;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Manager class for playing audio files.
|
||||
*
|
||||
|
@ -42,6 +45,8 @@ public class AudioManager {
|
|||
audioManager.addArtifactClip = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnAddArtifact.wav");
|
||||
audioManager.updateStackClip = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnStackNew.wav");
|
||||
audioManager.onHover = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnHover.wav");
|
||||
|
||||
audioManager.playerJoinedTable = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnPlayerJoinedTable.wav");
|
||||
}
|
||||
return audioManager;
|
||||
}
|
||||
|
@ -114,6 +119,10 @@ public class AudioManager {
|
|||
checkAndPlayClip(getManager().onHover);
|
||||
}
|
||||
|
||||
public static void playPlayerJoinedTable() {
|
||||
checkAndPlayClip(getManager().playerJoinedTable);
|
||||
}
|
||||
|
||||
private static void checkAndPlayClip(Clip clip) {
|
||||
try {
|
||||
if (clip != null) {
|
||||
|
@ -175,4 +184,6 @@ public class AudioManager {
|
|||
private Clip addArtifactClip = null;
|
||||
private Clip updateStackClip = null;
|
||||
private Clip onHover = null;
|
||||
|
||||
private Clip playerJoinedTable = null;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package org.mage.plugins.card.dl.sources;
|
||||
|
||||
import org.mage.plugins.card.images.CardDownloadData;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author North
|
||||
*/
|
||||
public interface CardImageSource {
|
||||
|
||||
String generateURL(Integer collectorId, String cardName, String cardSet, boolean twoFacedCard, boolean secondFace, boolean isFlipCard, boolean isSplitCard, boolean flippedView) throws Exception;
|
||||
String generateTokenUrl(String name, String set);
|
||||
String generateURL(CardDownloadData card) throws Exception;
|
||||
String generateTokenUrl(CardDownloadData card);
|
||||
Float getAverageSize();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.mage.plugins.card.dl.sources;
|
||||
|
||||
import org.mage.plugins.card.images.CardDownloadData;
|
||||
import org.mage.plugins.card.utils.CardImageUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -64,7 +65,9 @@ public class MagicCardsImageSource implements CardImageSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String generateURL(Integer collectorId, String cardName, String cardSet, boolean twoFacedCard, boolean secondSide, boolean isFlipCard, boolean isSplitCard, boolean flippedView) throws Exception {
|
||||
public String generateURL(CardDownloadData card) throws Exception {
|
||||
Integer collectorId = card.getCollectorId();
|
||||
String cardSet = card.getSet();
|
||||
if (collectorId == null || cardSet == null) {
|
||||
throw new Exception("Wrong parameters for image: collector id: " + collectorId + ",card set: " + cardSet);
|
||||
}
|
||||
|
@ -72,14 +75,14 @@ public class MagicCardsImageSource implements CardImageSource {
|
|||
StringBuilder url = new StringBuilder("http://magiccards.info/scans/en/");
|
||||
url.append(set.toLowerCase()).append("/").append(collectorId);
|
||||
|
||||
if (twoFacedCard) {
|
||||
url.append(secondSide ? "b" : "a");
|
||||
if (card.isTwoFacedCard()) {
|
||||
url.append(card.isSecondSide() ? "b" : "a");
|
||||
}
|
||||
if (isSplitCard) {
|
||||
if (card.isSplitCard()) {
|
||||
url.append("a");
|
||||
}
|
||||
if (isFlipCard) {
|
||||
if (flippedView) { // download rotated by 180 degree image
|
||||
if (card.isFlipCard()) {
|
||||
if (card.isFlippedSide()) { // download rotated by 180 degree image
|
||||
url.append("b");
|
||||
} else {
|
||||
url.append("a");
|
||||
|
@ -91,17 +94,15 @@ public class MagicCardsImageSource implements CardImageSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String generateTokenUrl(String name, String set) {
|
||||
String _name = name.replaceAll(" ", "-").replace(",", "").toLowerCase();
|
||||
String _set = "not-supported-set";
|
||||
if (setNameReplacement.containsKey(set)) {
|
||||
_set = setNameReplacement.get(set);
|
||||
public String generateTokenUrl(CardDownloadData card) {
|
||||
String name = card.getName().replaceAll(" ", "-").replace(",", "").toLowerCase();
|
||||
String set = "not-supported-set";
|
||||
if (setNameReplacement.containsKey(card.getSet())) {
|
||||
set = setNameReplacement.get(card.getSet());
|
||||
} else {
|
||||
_set += "-" + set;
|
||||
set += "-" + card.getSet();
|
||||
}
|
||||
String url = "http://magiccards.info/extras/token/" + _set + "/" + _name + ".jpg";
|
||||
return url;
|
||||
|
||||
return "http://magiccards.info/extras/token/" + set + "/" + name + ".jpg";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.mage.plugins.card.dl.sources;
|
|||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.mage.plugins.card.images.CardDownloadData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
@ -15,8 +16,8 @@ import java.util.Map;
|
|||
public class WizardCardsImageSource implements CardImageSource {
|
||||
|
||||
private static CardImageSource instance;
|
||||
private static Map setsAliases;
|
||||
private Map sets;
|
||||
private static Map<String, String> setsAliases;
|
||||
private Map<String, Map<String, String>> sets;
|
||||
|
||||
public static CardImageSource getInstance() {
|
||||
if (instance == null) {
|
||||
|
@ -26,8 +27,8 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
}
|
||||
|
||||
public WizardCardsImageSource() {
|
||||
sets = new HashMap();
|
||||
setsAliases = new HashMap();
|
||||
sets = new HashMap<String, Map<String, String>>();
|
||||
setsAliases = new HashMap<String, String>();
|
||||
setsAliases.put("MMA", "modernmasters/cig");
|
||||
setsAliases.put("DGM", "dragonsmaze/cig");
|
||||
setsAliases.put("GTC", "gatecrash/cig");
|
||||
|
@ -56,7 +57,7 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
private Map<String, String> getSetLinks(String cardSet) {
|
||||
Map<String, String> setLinks = new HashMap<String, String>();
|
||||
try {
|
||||
Document doc = Jsoup.connect("http://www.wizards.com/magic/tcg/article.aspx?x=mtg/tcg/" + (String) setsAliases.get(cardSet)).get();
|
||||
Document doc = Jsoup.connect("http://www.wizards.com/magic/tcg/article.aspx?x=mtg/tcg/" + setsAliases.get(cardSet)).get();
|
||||
Elements cardsImages = doc.select("img[height$=370]");
|
||||
for (int i = 0; i < cardsImages.size(); i++) {
|
||||
String cardName = cardsImages.get(i).attr("title").replace("\u00C6", "AE").replace("\u2019", "'");
|
||||
|
@ -94,20 +95,22 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String generateURL(Integer collectorId, String cardName, String cardSet, boolean twoFacedCard, boolean secondSide, boolean isFlipCard, boolean isSplitCard, boolean flippedView) throws Exception {
|
||||
public String generateURL(CardDownloadData card) throws Exception {
|
||||
Integer collectorId = card.getCollectorId();
|
||||
String cardSet = card.getSet();
|
||||
if (collectorId == null || cardSet == null) {
|
||||
throw new Exception("Wrong parameters for image: collector id: " + collectorId + ",card set: " + cardSet);
|
||||
}
|
||||
if (flippedView) { //doesn't support rotated images
|
||||
if (card.isFlippedSide()) { //doesn't support rotated images
|
||||
return null;
|
||||
}
|
||||
if (setsAliases.get(cardSet) != null) {
|
||||
Map<String, String> setLinks = (Map<String, String>) sets.get(cardSet);
|
||||
Map<String, String> setLinks = sets.get(cardSet);
|
||||
if (setLinks == null) {
|
||||
setLinks = getSetLinks(cardSet);
|
||||
sets.put(cardSet, setLinks);
|
||||
}
|
||||
String link = setLinks.get(cardName);
|
||||
String link = setLinks.get(card.getDownloadName());
|
||||
if (link == null) {
|
||||
if (setLinks.size() >= collectorId) {
|
||||
link = setLinks.get(Integer.toString(collectorId - 1));
|
||||
|
@ -127,7 +130,7 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String generateTokenUrl(String name, String set) {
|
||||
public String generateTokenUrl(CardDownloadData card) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -135,4 +138,4 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
public Float getAverageSize() {
|
||||
return 60.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ package org.mage.plugins.card.images;
|
|||
*
|
||||
* @author North
|
||||
*/
|
||||
public class CardInfo {
|
||||
public class CardDownloadData {
|
||||
|
||||
private String name;
|
||||
private String downloadName;
|
||||
|
@ -19,15 +19,15 @@ public class CardInfo {
|
|||
private boolean splitCard;
|
||||
private boolean usesVariousArt;
|
||||
|
||||
public CardInfo(String name, String set, Integer collectorId, boolean usesVariousArt, Integer type) {
|
||||
public CardDownloadData(String name, String set, Integer collectorId, boolean usesVariousArt, Integer type) {
|
||||
this(name, set, collectorId, usesVariousArt, type, false);
|
||||
}
|
||||
|
||||
public CardInfo(String name, String set, Integer collectorId, boolean usesVariousArt, Integer type, boolean token) {
|
||||
public CardDownloadData(String name, String set, Integer collectorId, boolean usesVariousArt, Integer type, boolean token) {
|
||||
this(name, set, collectorId, usesVariousArt, type, token, false, false);
|
||||
}
|
||||
|
||||
public CardInfo(String name, String set, Integer collectorId, boolean usesVariousArt, Integer type, boolean token, boolean twoFacedCard, boolean secondSide) {
|
||||
public CardDownloadData(String name, String set, Integer collectorId, boolean usesVariousArt, Integer type, boolean token, boolean twoFacedCard, boolean secondSide) {
|
||||
this.name = name;
|
||||
this.set = set;
|
||||
this.collectorId = collectorId;
|
||||
|
@ -38,7 +38,7 @@ public class CardInfo {
|
|||
this.secondSide = secondSide;
|
||||
}
|
||||
|
||||
public CardInfo(final CardInfo card) {
|
||||
public CardDownloadData(final CardDownloadData card) {
|
||||
this.name = card.name;
|
||||
this.set = card.set;
|
||||
this.collectorId = card.collectorId;
|
||||
|
@ -57,7 +57,7 @@ public class CardInfo {
|
|||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final CardInfo other = (CardInfo) obj;
|
||||
final CardDownloadData other = (CardDownloadData) obj;
|
||||
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -96,10 +96,6 @@ public class CardInfo {
|
|||
return collectorId;
|
||||
}
|
||||
|
||||
public void setCollectorId(Integer collectorId) {
|
||||
this.collectorId = collectorId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -160,10 +156,6 @@ public class CardInfo {
|
|||
return type;
|
||||
}
|
||||
|
||||
public void setType(Integer type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean getUsesVariousArt() {
|
||||
return usesVariousArt;
|
||||
}
|
|
@ -4,7 +4,7 @@ import de.schlichtherle.truezip.file.TFile;
|
|||
import de.schlichtherle.truezip.file.TFileOutputStream;
|
||||
import de.schlichtherle.truezip.file.TVFS;
|
||||
import de.schlichtherle.truezip.fs.FsSyncException;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.remote.Connection;
|
||||
import org.apache.log4j.Logger;
|
||||
|
@ -46,7 +46,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
private JButton closeButton;
|
||||
private JButton startDownloadButton;
|
||||
private int cardIndex;
|
||||
private ArrayList<CardInfo> cards;
|
||||
private ArrayList<CardDownloadData> cards;
|
||||
private JComboBox jComboBox1;
|
||||
private JLabel jLabel1;
|
||||
private static boolean offlineMode = false;
|
||||
|
@ -60,14 +60,12 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
|
||||
private ExecutorService executor = Executors.newFixedThreadPool(10);
|
||||
|
||||
public static final Proxy.Type[] types = Proxy.Type.values();
|
||||
|
||||
public static void main(String[] args) {
|
||||
startDownload(null, null, null);
|
||||
}
|
||||
|
||||
public static void startDownload(JFrame frame, List<Card> allCards, String imagesPath) {
|
||||
ArrayList<CardInfo> cards = getNeededCards(allCards, imagesPath);
|
||||
public static void startDownload(JFrame frame, List<CardInfo> allCards, String imagesPath) {
|
||||
ArrayList<CardDownloadData> cards = getNeededCards(allCards, imagesPath);
|
||||
|
||||
/*
|
||||
* if (cards == null || cards.size() == 0) {
|
||||
|
@ -99,33 +97,15 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
this.cancel = cancel;
|
||||
}
|
||||
|
||||
public DownloadPictures(ArrayList<CardInfo> cards, String imagesPath) {
|
||||
public DownloadPictures(ArrayList<CardDownloadData> cards, String imagesPath) {
|
||||
this.cards = cards;
|
||||
this.imagesPath = imagesPath;
|
||||
|
||||
//addr = new JTextField("Proxy Address");
|
||||
//port = new JTextField("Proxy Port");
|
||||
bar = new JProgressBar(this);
|
||||
|
||||
JPanel p0 = new JPanel();
|
||||
p0.setLayout(new BoxLayout(p0, BoxLayout.Y_AXIS));
|
||||
|
||||
// Proxy Choice
|
||||
/*ButtonGroup bg = new ButtonGroup();
|
||||
String[] labels = { "No Proxy", "HTTP Proxy", "SOCKS Proxy" };
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
JRadioButton rb = new JRadioButton(labels[i]);
|
||||
rb.addChangeListener(new ProxyHandler(i));
|
||||
bg.add(rb);
|
||||
p0.add(rb);
|
||||
if (i == 0)
|
||||
rb.setSelected(true);
|
||||
}*/
|
||||
|
||||
// Proxy config
|
||||
//p0.add(addr);
|
||||
//p0.add(port);
|
||||
|
||||
p0.add(Box.createVerticalStrut(5));
|
||||
jLabel1 = new JLabel();
|
||||
jLabel1.setText("Please select server:");
|
||||
|
@ -206,11 +186,11 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
dlg = new JOptionPane(p0, JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[1]);
|
||||
}
|
||||
|
||||
public static boolean checkForNewCards(List<Card> allCards, String imagesPath) {
|
||||
public static boolean checkForNewCards(List<CardInfo> allCards, String imagesPath) {
|
||||
TFile file;
|
||||
for (Card card : allCards) {
|
||||
if (card.getCardNumber() > 0 && !card.getExpansionSetCode().isEmpty()) {
|
||||
CardInfo url = new CardInfo(card.getName(), card.getExpansionSetCode(), card.getCardNumber(),card.getUsesVariousArt(),0 , false, card.canTransform(), card.isNightCard());
|
||||
for (CardInfo card : allCards) {
|
||||
if (card.getCardNumber() > 0 && !card.getSetCode().isEmpty()) {
|
||||
CardDownloadData url = new CardDownloadData(card.getName(), card.getSetCode(), card.getCardNumber(), usesVariousArt(card), 0, false, card.isDoubleFaced(), card.isNightCard());
|
||||
file = new TFile(CardImageUtils.getImagePath(url, imagesPath));
|
||||
if (!file.exists()) {
|
||||
return true;
|
||||
|
@ -220,47 +200,54 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
return false;
|
||||
}
|
||||
|
||||
private static ArrayList<CardInfo> getNeededCards(List<Card> allCards, String imagesPath) {
|
||||
private static boolean usesVariousArt(CardInfo card) {
|
||||
String className = card.getClassName();
|
||||
return Character.isDigit(className.charAt(className.length() - 1));
|
||||
}
|
||||
|
||||
ArrayList<CardInfo> cardsToDownload = new ArrayList<CardInfo>();
|
||||
private static String createDownloadName(CardInfo card) {
|
||||
String className = card.getClassName();
|
||||
return className.substring(className.lastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
private static ArrayList<CardDownloadData> getNeededCards(List<CardInfo> allCards, String imagesPath) {
|
||||
|
||||
ArrayList<CardDownloadData> cardsToDownload = new ArrayList<CardDownloadData>();
|
||||
|
||||
/**
|
||||
* read all card names and urls
|
||||
*/
|
||||
ArrayList<CardInfo> allCardsUrls = new ArrayList<CardInfo>();
|
||||
ArrayList<CardDownloadData> allCardsUrls = new ArrayList<CardDownloadData>();
|
||||
HashSet<String> ignoreUrls = SettingsManager.getIntance().getIgnoreUrls();
|
||||
|
||||
try {
|
||||
offlineMode = true;
|
||||
|
||||
for (Card card : allCards) {
|
||||
if (card.getCardNumber() > 0 && !card.getExpansionSetCode().isEmpty()
|
||||
&& !ignoreUrls.contains(card.getExpansionSetCode())) {
|
||||
for (CardInfo card : allCards) {
|
||||
if (card.getCardNumber() > 0 && !card.getSetCode().isEmpty()
|
||||
&& !ignoreUrls.contains(card.getSetCode())) {
|
||||
String cardName = card.getName();
|
||||
CardInfo url = new CardInfo(cardName, card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), 0, false, card.canTransform(), card.isNightCard());
|
||||
CardDownloadData url = new CardDownloadData(cardName, card.getSetCode(), card.getCardNumber(), usesVariousArt(card), 0, false, card.isDoubleFaced(), card.isNightCard());
|
||||
if (url.getUsesVariousArt()) {
|
||||
url.setDownloadName(card.getClass().getName().replace(card.getClass().getPackage().getName() + ".", ""));
|
||||
}
|
||||
if (card.isFlipCard()) {
|
||||
url.setFlipCard(true);
|
||||
}
|
||||
if (card.isSplitCard()) {
|
||||
url.setSplitCard(true);
|
||||
url.setDownloadName(createDownloadName(card));
|
||||
}
|
||||
|
||||
url.setFlipCard(card.isFlipCard());
|
||||
url.setSplitCard(card.isSplitCard());
|
||||
|
||||
allCardsUrls.add(url);
|
||||
if (card.canTransform()) {
|
||||
if (card.isDoubleFaced()) {
|
||||
// add second side for downloading
|
||||
// it has the same expansion set code and card number as original one
|
||||
// second side = true;
|
||||
Card secondSide = card.getSecondCardFace();
|
||||
url = new CardInfo(secondSide.getName(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), 0, false, card.canTransform(), true);
|
||||
url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), usesVariousArt(card), 0, false, card.isDoubleFaced(), true);
|
||||
allCardsUrls.add(url);
|
||||
}
|
||||
if (card.isFlipCard()) {
|
||||
if (card.getFlipCardName() == null || card.getFlipCardName().trim().isEmpty()) {
|
||||
throw new IllegalStateException("Flipped card can't have empty name.");
|
||||
}
|
||||
url = new CardInfo(card.getFlipCardName(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), 0, false, card.canTransform(), card.isNightCard());
|
||||
url = new CardDownloadData(card.getFlipCardName(), card.getSetCode(), card.getCardNumber(), usesVariousArt(card), 0, false, card.isDoubleFaced(), card.isNightCard());
|
||||
url.setFlipCard(true);
|
||||
url.setFlippedSide(true);
|
||||
allCardsUrls.add(url);
|
||||
|
@ -269,7 +256,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
if (card.getCardNumber() < 1) {
|
||||
System.err.println("There was a critical error!");
|
||||
log.error("Card has no collector ID and won't be sent to client: " + card);
|
||||
} else if (card.getExpansionSetCode().isEmpty()) {
|
||||
} else if (card.getSetCode().isEmpty()) {
|
||||
System.err.println("There was a critical error!");
|
||||
log.error("Card has no set name and won't be sent to client:" + card);
|
||||
}
|
||||
|
@ -286,14 +273,14 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
/**
|
||||
* check to see which cards we already have
|
||||
*/
|
||||
for (CardInfo card : allCardsUrls) {
|
||||
for (CardDownloadData card : allCardsUrls) {
|
||||
file = new TFile(CardImageUtils.getImagePath(card, imagesPath));
|
||||
if (!file.exists()) {
|
||||
cardsToDownload.add(card);
|
||||
}
|
||||
}
|
||||
|
||||
for (CardInfo card : cardsToDownload) {
|
||||
for (CardDownloadData card : cardsToDownload) {
|
||||
if (card.isToken()) {
|
||||
log.info("Card to download: " + card.getName() + " (Token) ");
|
||||
} else {
|
||||
|
@ -308,8 +295,8 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
return cardsToDownload;
|
||||
}
|
||||
|
||||
private static ArrayList<CardInfo> getTokenCardUrls() throws RuntimeException {
|
||||
ArrayList<CardInfo> list = new ArrayList<CardInfo>();
|
||||
private static ArrayList<CardDownloadData> getTokenCardUrls() throws RuntimeException {
|
||||
ArrayList<CardDownloadData> list = new ArrayList<CardDownloadData>();
|
||||
InputStream in = DownloadPictures.class.getClassLoader().getResourceAsStream("card-pictures-tok.txt");
|
||||
|
||||
if (in == null) {
|
||||
|
@ -332,15 +319,15 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
if (params.length >= 4) {
|
||||
if (params[1].toLowerCase().equals("generate") && params[2].startsWith("TOK:")) {
|
||||
String set = params[2].substring(4);
|
||||
CardInfo card = new CardInfo(params[3], set, 0, false, 0, true);
|
||||
CardDownloadData card = new CardDownloadData(params[3], set, 0, false, 0, true);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase().equals("generate") && params[2].startsWith("EMBLEM:")) {
|
||||
String set = params[2].substring(7);
|
||||
CardInfo card = new CardInfo("Emblem " + params[3], set, 0, false,0, true);
|
||||
CardDownloadData card = new CardDownloadData("Emblem " + params[3], set, 0, false,0, true);
|
||||
list.add(card);
|
||||
} else if (params[1].toLowerCase().equals("generate") && params[2].startsWith("EMBLEM-:")) {
|
||||
String set = params[2].substring(8);
|
||||
CardInfo card = new CardInfo(params[3] + " Emblem", set, 0, false, 0, true);
|
||||
CardDownloadData card = new CardDownloadData(params[3] + " Emblem", set, 0, false, 0, true);
|
||||
list.add(card);
|
||||
}
|
||||
} else {
|
||||
|
@ -408,7 +395,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
for (int i = 0; i < cards.size() && !cancel; i++) {
|
||||
try {
|
||||
|
||||
CardInfo card = cards.get(i);
|
||||
CardDownloadData card = cards.get(i);
|
||||
|
||||
log.info("Downloading card: " + card.getName() + " (" + card.getSet() + ")");
|
||||
|
||||
|
@ -417,10 +404,9 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
if (card.getCollectorId() != 0) {
|
||||
continue;
|
||||
}
|
||||
url = cardImageSource.generateTokenUrl(card.getName(), card.getSet());
|
||||
url = cardImageSource.generateTokenUrl(card);
|
||||
} else {
|
||||
url = cardImageSource.generateURL(card.getCollectorId(), card.getDownloadName(), card.getSet(),
|
||||
card.isTwoFacedCard(), card.isSecondSide(), card.isFlipCard(), card.isSplitCard(), card.isFlippedSide());
|
||||
url = cardImageSource.generateURL(card);
|
||||
}
|
||||
|
||||
if (url != null) {
|
||||
|
@ -457,10 +443,10 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
|
||||
private final class DownloadTask implements Runnable {
|
||||
|
||||
private CardInfo card;
|
||||
private CardDownloadData card;
|
||||
private URL url;
|
||||
|
||||
public DownloadTask(CardInfo card, URL url) {
|
||||
public DownloadTask(CardDownloadData card, URL url) {
|
||||
this.card = card;
|
||||
this.url = url;
|
||||
}
|
||||
|
@ -573,10 +559,10 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
bar.setString(String.format("%d of %d cards finished! Please wait! [%.1f Mb]",
|
||||
card, count, mb));
|
||||
} else {
|
||||
Iterator<CardInfo> cardsIterator = DownloadPictures.this.cards.iterator();
|
||||
Iterator<CardDownloadData> cardsIterator = DownloadPictures.this.cards.iterator();
|
||||
while (cardsIterator.hasNext()) {
|
||||
CardInfo cardInfo = cardsIterator.next();
|
||||
TFile file = new TFile(CardImageUtils.getImagePath(cardInfo, imagesPath));
|
||||
CardDownloadData cardDownloadData = cardsIterator.next();
|
||||
TFile file = new TFile(CardImageUtils.getImagePath(cardDownloadData, imagesPath));
|
||||
if (file.exists()) {
|
||||
cardsIterator.remove();
|
||||
}
|
||||
|
@ -584,7 +570,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
count = DownloadPictures.this.cards.size();
|
||||
|
||||
if (count == 0) {
|
||||
bar.setString(String.format("0 cards remaining! Please close!", count));
|
||||
bar.setString("0 cards remaining! Please close!");
|
||||
} else {
|
||||
bar.setString(String.format("%d cards remaining! Please choose another source!", count));
|
||||
//executor = Executors.newFixedThreadPool(10);
|
||||
|
|
|
@ -71,7 +71,7 @@ public class ImageCache {
|
|||
Integer type = Integer.parseInt(m.group(3));
|
||||
Integer collectorId = Integer.parseInt(m.group(4));
|
||||
|
||||
CardInfo info = new CardInfo(name, set, collectorId, usesVariousArt, type);
|
||||
CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type);
|
||||
|
||||
if (collectorId == 0) {
|
||||
info.setToken(true);
|
||||
|
|
|
@ -4,12 +4,12 @@ import de.schlichtherle.truezip.file.TFile;
|
|||
import java.util.HashMap;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import org.mage.plugins.card.images.CardInfo;
|
||||
import org.mage.plugins.card.images.CardDownloadData;
|
||||
import org.mage.plugins.card.properties.SettingsManager;
|
||||
|
||||
public class CardImageUtils {
|
||||
|
||||
private static HashMap<CardInfo, String> pathCache = new HashMap<CardInfo, String>();
|
||||
private static HashMap<CardDownloadData, String> pathCache = new HashMap<CardDownloadData, String>();
|
||||
|
||||
/**
|
||||
* Get path to image for specific card.
|
||||
|
@ -18,7 +18,7 @@ public class CardImageUtils {
|
|||
* card to get path for
|
||||
* @return String if image exists, else null
|
||||
*/
|
||||
public static String getImagePath(CardInfo card) {
|
||||
public static String getImagePath(CardDownloadData card) {
|
||||
String filePath;
|
||||
|
||||
TFile file;
|
||||
|
@ -51,19 +51,19 @@ public class CardImageUtils {
|
|||
}
|
||||
}
|
||||
|
||||
private static String getTokenImagePath(CardInfo card) {
|
||||
private static String getTokenImagePath(CardDownloadData card) {
|
||||
String useDefault = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_USE_DEFAULT, "true");
|
||||
String path = useDefault.equals("true") ? null : PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PATH, null);
|
||||
String filename = getImagePath(card, path);
|
||||
|
||||
TFile file = new TFile(filename);
|
||||
if (!file.exists()) {
|
||||
CardInfo updated = new CardInfo(card);
|
||||
CardDownloadData updated = new CardDownloadData(card);
|
||||
updated.setName(card.getName() + " 1");
|
||||
filename = getImagePath(updated, path);
|
||||
file = new TFile(filename);
|
||||
if (!file.exists()) {
|
||||
updated = new CardInfo(card);
|
||||
updated = new CardDownloadData(card);
|
||||
updated.setName(card.getName() + " 2");
|
||||
filename = getImagePath(updated, path);
|
||||
}
|
||||
|
@ -72,10 +72,10 @@ public class CardImageUtils {
|
|||
return filename;
|
||||
}
|
||||
|
||||
private static String searchForCardImage(CardInfo card) {
|
||||
private static String searchForCardImage(CardDownloadData card) {
|
||||
TFile file;
|
||||
String path;
|
||||
CardInfo c = new CardInfo(card);
|
||||
CardDownloadData c = new CardDownloadData(card);
|
||||
|
||||
for (String set : SettingsManager.getIntance().getTokenLookupOrder()) {
|
||||
c.setSet(set);
|
||||
|
@ -100,7 +100,7 @@ public class CardImageUtils {
|
|||
return set;
|
||||
}
|
||||
|
||||
private static String getImageDir(CardInfo card, String imagesPath) {
|
||||
private static String getImageDir(CardDownloadData card, String imagesPath) {
|
||||
if (card.getSet() == null) {
|
||||
return "";
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ public class CardImageUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static String getImagePath(CardInfo card, String imagesPath) {
|
||||
public static String getImagePath(CardDownloadData card, String imagesPath) {
|
||||
String imageDir = getImageDir(card, imagesPath);
|
||||
String imageName;
|
||||
|
||||
|
|
|
@ -68,6 +68,11 @@ public final class Constants {
|
|||
|
||||
public static final double SCALE_FACTOR = 0.5;
|
||||
|
||||
/**
|
||||
* Time each player has during the game to play using his\her priority.
|
||||
*/
|
||||
public static final int PRIORITY_TIME_SEC = 1200;
|
||||
|
||||
public enum SessionState {
|
||||
DISCONNECTED, CONNECTED, CONNECTING, DISCONNECTING, SERVER_UNAVAILABLE, SERVER_STARTING;
|
||||
}
|
||||
|
|
127
Mage.Common/src/mage/utils/timer/PriorityTimer.java
Normal file
127
Mage.Common/src/mage/utils/timer/PriorityTimer.java
Normal file
|
@ -0,0 +1,127 @@
|
|||
package mage.utils.timer;
|
||||
|
||||
import mage.MageException;
|
||||
import mage.interfaces.Action;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
*/
|
||||
public class PriorityTimer extends TimerTask {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(PriorityTimer.class);
|
||||
|
||||
private int count;
|
||||
|
||||
private long delay;
|
||||
|
||||
private Action taskOnTimeout;
|
||||
|
||||
private Action taskOnTick;
|
||||
|
||||
private States state = States.NONE;
|
||||
|
||||
enum States {
|
||||
NONE,
|
||||
INIT,
|
||||
RUNNING,
|
||||
PAUSED,
|
||||
FINISHED
|
||||
}
|
||||
|
||||
public PriorityTimer(int count, long delay, Action taskOnTimeout) {
|
||||
this.count = count;
|
||||
this.delay = delay;
|
||||
this.taskOnTimeout = taskOnTimeout;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
state = States.INIT;
|
||||
Timer timer = new Timer("Priority Timer", false);
|
||||
long delayMs = delay * (int) (1000L / delay);
|
||||
timer.scheduleAtFixedRate(this, delayMs, delayMs);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (state == States.NONE) {
|
||||
throw new IllegalStateException("Timer should have been initialized first");
|
||||
}
|
||||
if (state == States.FINISHED) {
|
||||
throw new IllegalStateException("Timer has already finished its work");
|
||||
}
|
||||
state = States.RUNNING;
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
state = States.PAUSED;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
state = States.FINISHED;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
if (state == States.FINISHED) {
|
||||
throw new IllegalStateException("Timer has already finished its work");
|
||||
}
|
||||
state = States.RUNNING;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public void setTaskOnTick(Action taskOnTick) {
|
||||
this.taskOnTick = taskOnTick;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (state == States.RUNNING) {
|
||||
count--;
|
||||
if (taskOnTick != null) {
|
||||
try {
|
||||
taskOnTick.execute();
|
||||
} catch (MageException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) logger.debug("Count is: " + count);
|
||||
//System.out.println("Count is: " + count);
|
||||
if (count <= 0) {
|
||||
cancel();
|
||||
try {
|
||||
taskOnTimeout.execute();
|
||||
} catch (MageException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
long delay = 250L;
|
||||
int count = 5;
|
||||
PriorityTimer timer = new PriorityTimer(count, delay, new Action() {
|
||||
@Override
|
||||
public void execute() throws MageException {
|
||||
System.out.println("Exit");
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
timer.init();
|
||||
timer.start();
|
||||
Thread.sleep(2000);
|
||||
timer.pause();
|
||||
Thread.sleep(3000);
|
||||
timer.resume();
|
||||
}
|
||||
}
|
|
@ -63,6 +63,7 @@ public class PlayerView implements Serializable {
|
|||
private List<EmblemView> emblemList = new ArrayList<EmblemView>();
|
||||
private List<UUID> attachments = new ArrayList<UUID>();
|
||||
private int statesSavedSize;
|
||||
private int priorityTimeLeft;
|
||||
|
||||
public PlayerView(Player player, GameState state, Game game) {
|
||||
this.playerId = player.getId();
|
||||
|
@ -108,6 +109,7 @@ public class PlayerView implements Serializable {
|
|||
}
|
||||
|
||||
this.statesSavedSize = player.getStoredBookmark();
|
||||
this.priorityTimeLeft = player.getPriorityTimeLeft();
|
||||
}
|
||||
|
||||
private boolean showInBattlefield(Permanent permanent, GameState state) {
|
||||
|
@ -191,4 +193,8 @@ public class PlayerView implements Serializable {
|
|||
public int getStatesSavedSize() {
|
||||
return statesSavedSize;
|
||||
}
|
||||
|
||||
public int getPriorityTimeLeft() {
|
||||
return priorityTimeLeft;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,11 +28,6 @@
|
|||
|
||||
package mage.player.human;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
|
@ -46,6 +41,9 @@ import mage.cards.Cards;
|
|||
import mage.cards.decks.Deck;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterAttackingCreature;
|
||||
import mage.filter.common.FilterBlockingCreature;
|
||||
import mage.filter.common.FilterCreatureForCombat;
|
||||
|
@ -67,6 +65,9 @@ import mage.target.common.TargetDefender;
|
|||
import mage.util.ManaUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -98,40 +99,43 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
super(player);
|
||||
}
|
||||
|
||||
protected void waitForResponse() {
|
||||
protected void waitForResponse(Game game) {
|
||||
response.clear();
|
||||
log.debug("Waiting response from player: " + getId());
|
||||
game.resumeTimer(playerId);
|
||||
synchronized(response) {
|
||||
try {
|
||||
response.wait();
|
||||
log.debug("Got response from player: " + getId());
|
||||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
game.pauseTimer(playerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void waitForBooleanResponse() {
|
||||
protected void waitForBooleanResponse(Game game) {
|
||||
do {
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
} while (response.getBoolean() == null && !abort);
|
||||
}
|
||||
|
||||
protected void waitForUUIDResponse() {
|
||||
protected void waitForUUIDResponse(Game game) {
|
||||
do {
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
} while (response.getUUID() == null && !abort);
|
||||
}
|
||||
|
||||
protected void waitForStringResponse() {
|
||||
protected void waitForStringResponse(Game game) {
|
||||
do {
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
} while (response.getString() == null && !abort);
|
||||
}
|
||||
|
||||
protected void waitForIntegerResponse() {
|
||||
protected void waitForIntegerResponse(Game game) {
|
||||
do {
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
} while (response.getInteger() == null && !abort);
|
||||
}
|
||||
|
||||
|
@ -143,7 +147,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
.append(getHand().size() > nextHandSize?"down to ":"for free, draw ")
|
||||
.append(nextHandSize)
|
||||
.append(nextHandSize == 1?" card?":" cards?").toString());
|
||||
waitForBooleanResponse();
|
||||
waitForBooleanResponse(game);
|
||||
if (!abort) {
|
||||
return response.getBoolean();
|
||||
}
|
||||
|
@ -154,7 +158,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
public boolean chooseUse(Outcome outcome, String message, Game game) {
|
||||
updateGameStatePriority("chooseUse", game);
|
||||
game.fireAskPlayerEvent(playerId, message);
|
||||
waitForBooleanResponse();
|
||||
waitForBooleanResponse(game);
|
||||
if (!abort) {
|
||||
return response.getBoolean();
|
||||
}
|
||||
|
@ -175,7 +179,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
}
|
||||
while (!abort) {
|
||||
game.fireChooseEvent(playerId, replacementEffectChoice);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
log.debug("Choose effect: " + response.getString());
|
||||
if (response.getString() != null) {
|
||||
replacementEffectChoice.setChoice(response.getString());
|
||||
|
@ -196,7 +200,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
updateGameStatePriority("choose(3)", game);
|
||||
while (!abort) {
|
||||
game.fireChooseEvent(playerId, choice);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getString() != null) {
|
||||
choice.setChoice(response.getString());
|
||||
return true;
|
||||
|
@ -218,7 +222,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
while (!abort) {
|
||||
Set<UUID> cards = target.possibleTargets(null, playerId, game);
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired(), options);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (target instanceof TargetPermanent) {
|
||||
if (((TargetPermanent)target).canTarget(playerId, response.getUUID(), sourceId, game, false)) {
|
||||
|
@ -267,7 +271,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
Set<UUID> possibleTargets = target.possibleTargets(source==null?null:source.getSourceId(), playerId, game);
|
||||
boolean required = possibleTargets.isEmpty() ? false : target.isRequired();
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), possibleTargets, required, getOptions(target));
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (possibleTargets.contains(response.getUUID())) {
|
||||
if (target instanceof TargetPermanent) {
|
||||
|
@ -323,7 +327,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
options.put("chosen", (Serializable)chosen);
|
||||
}
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, required, options);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (target.canTarget(response.getUUID(), cards, game)) {
|
||||
target.add(response.getUUID(), game);
|
||||
|
@ -358,7 +362,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
}
|
||||
}
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired(), null);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (target.canTarget(response.getUUID(), cards, game)) {
|
||||
target.addTarget(response.getUUID(), source, game);
|
||||
|
@ -383,7 +387,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
updateGameStatePriority("chooseTargetAmount", game);
|
||||
while (!abort) {
|
||||
game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), target.possibleTargets(source==null?null:source.getId(), playerId, game), target.isRequired(), null);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (target.canTarget(response.getUUID(), source, game)) {
|
||||
UUID targetId = response.getUUID();
|
||||
|
@ -412,7 +416,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
}
|
||||
updateGameStatePriority("priority", game);
|
||||
game.firePriorityEvent(playerId);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getBoolean() != null) {
|
||||
pass(game);
|
||||
return false;
|
||||
|
@ -450,7 +454,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
updateGameStatePriority("chooseTriggeredAbility", game);
|
||||
while (!abort) {
|
||||
game.fireSelectTargetEvent(playerId, "Pick triggered ability (goes to the stack first)", abilities);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
for (TriggeredAbility ability: abilities) {
|
||||
if (ability.getId().equals(response.getUUID())) {
|
||||
|
@ -466,7 +470,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
public boolean playMana(ManaCost unpaid, Game game) {
|
||||
updateGameStatePriority("playMana", game);
|
||||
game.firePlayManaEvent(playerId, "Pay " + unpaid.getText());
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getBoolean() != null) {
|
||||
return false;
|
||||
} else if (response.getUUID() != null) {
|
||||
|
@ -500,7 +504,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
|
||||
updateGameStatePriority("announceXMana", game);
|
||||
game.fireGetAmountEvent(playerId, message, min, max);
|
||||
waitForIntegerResponse();
|
||||
waitForIntegerResponse(game);
|
||||
return response.getInteger();
|
||||
}
|
||||
|
||||
|
@ -530,7 +534,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
return;
|
||||
}
|
||||
game.fireSelectEvent(playerId, "Select attackers");
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getBoolean() != null) {
|
||||
return;
|
||||
} else if (response.getInteger() != null) {
|
||||
|
@ -593,7 +597,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
filter.add(new ControllerIdPredicate(defendingPlayerId));
|
||||
while (!abort) {
|
||||
game.fireSelectEvent(playerId, "Select blockers");
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getBoolean() != null) {
|
||||
return;
|
||||
} else if (response.getInteger() != null) {
|
||||
|
@ -622,7 +626,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
updateGameStatePriority("chooseAttackerOrder", game);
|
||||
while (!abort) {
|
||||
game.fireSelectTargetEvent(playerId, "Pick attacker", attackers, true);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
for (Permanent perm: attackers) {
|
||||
if (perm.getId().equals(response.getUUID())) {
|
||||
|
@ -640,7 +644,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
updateGameStatePriority("chooseBlockerOrder", game);
|
||||
while (!abort) {
|
||||
game.fireSelectTargetEvent(playerId, "Pick blocker", blockers, true);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
for (Permanent perm: blockers) {
|
||||
if (perm.getId().equals(response.getUUID())) {
|
||||
|
@ -656,7 +660,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
updateGameStatePriority("selectCombatGroup", game);
|
||||
TargetAttackingCreature target = new TargetAttackingCreature();
|
||||
game.fireSelectTargetEvent(playerId, "Select attacker to block", target.possibleTargets(null, playerId, game), target.isRequired(), null);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getBoolean() != null) {
|
||||
// do nothing
|
||||
} else if (response.getUUID() != null) {
|
||||
|
@ -696,7 +700,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
public int getAmount(int min, int max, String message, Game game) {
|
||||
updateGameStatePriority("getAmount", game);
|
||||
game.fireGetAmountEvent(playerId, message, min, max);
|
||||
waitForIntegerResponse();
|
||||
waitForIntegerResponse(game);
|
||||
return response.getInteger();
|
||||
}
|
||||
|
||||
|
@ -719,7 +723,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
updateGameStatePriority("specialAction", game);
|
||||
LinkedHashMap<UUID, SpecialAction> specialActions = game.getState().getSpecialActions().getControlledBy(playerId);
|
||||
game.fireGetChoiceEvent(playerId, name, new ArrayList<SpecialAction>(specialActions.values()));
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (specialActions.containsKey(response.getUUID())) {
|
||||
activateAbility(specialActions.get(response.getUUID()), game);
|
||||
|
@ -737,7 +741,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
}
|
||||
}
|
||||
game.fireGetChoiceEvent(playerId, name, new ArrayList<ActivatedAbility>(abilities.values()));
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (abilities.containsKey(response.getUUID())) {
|
||||
activateAbility(abilities.get(response.getUUID()), game);
|
||||
|
@ -757,7 +761,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
return (SpellAbility) useableAbilities.values().iterator().next();
|
||||
} else if (useableAbilities != null && useableAbilities.size() > 0) {
|
||||
game.fireGetChoiceEvent(playerId, name, new ArrayList<ActivatedAbility>(useableAbilities.values()));
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
if (useableAbilities.containsKey(response.getUUID())) {
|
||||
return (SpellAbility) useableAbilities.get(response.getUUID());
|
||||
|
@ -785,7 +789,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
modeMap.put(mode.getId(), modeText);
|
||||
}
|
||||
game.fireGetModeEvent(playerId, "Choose Mode", modeMap);
|
||||
waitForResponse();
|
||||
waitForResponse(game);
|
||||
if (response.getUUID() != null) {
|
||||
for (Mode mode: modes.values()) {
|
||||
if (mode.getId().equals(response.getUUID())) {
|
||||
|
@ -802,7 +806,7 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
|
|||
public boolean choosePile(Outcome outcome, String message, List<? extends Card> pile1, List<? extends Card> pile2, Game game) {
|
||||
updateGameStatePriority("choosePile", game);
|
||||
game.fireChoosePileEvent(playerId, message, pile1, pile2);
|
||||
waitForBooleanResponse();
|
||||
waitForBooleanResponse(game);
|
||||
if (!abort) {
|
||||
return response.getBoolean();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#default levels
|
||||
log4j.rootLogger=info, console, logfile
|
||||
log4j.rootLogger=warn, console, logfile
|
||||
|
||||
#console log
|
||||
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
package mage.server.game;
|
||||
|
||||
import mage.constants.Zone;
|
||||
import mage.MageException;
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
|
@ -37,17 +36,21 @@ import mage.cards.decks.Deck;
|
|||
import mage.cards.decks.DeckCardLists;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.Constants;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameException;
|
||||
import mage.game.events.Listener;
|
||||
import mage.game.events.PlayerQueryEvent;
|
||||
import mage.game.events.TableEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.interfaces.Action;
|
||||
import mage.players.Player;
|
||||
import mage.server.*;
|
||||
import mage.server.util.Splitter;
|
||||
import mage.server.util.SystemUtil;
|
||||
import mage.server.util.ThreadExecutor;
|
||||
import mage.utils.timer.PriorityTimer;
|
||||
import mage.view.AbilityPickerView;
|
||||
import mage.view.CardsView;
|
||||
import mage.view.ChatMessage.MessageColor;
|
||||
|
@ -75,6 +78,8 @@ public class GameController implements GameCallback {
|
|||
|
||||
private ConcurrentHashMap<UUID, GameSession> gameSessions = new ConcurrentHashMap<UUID, GameSession>();
|
||||
private ConcurrentHashMap<UUID, GameWatcher> watchers = new ConcurrentHashMap<UUID, GameWatcher>();
|
||||
private ConcurrentHashMap<UUID, PriorityTimer> timers = new ConcurrentHashMap<UUID, PriorityTimer>();
|
||||
|
||||
private ConcurrentHashMap<UUID, UUID> userPlayerMap;
|
||||
private UUID gameSessionId;
|
||||
private Game game;
|
||||
|
@ -106,6 +111,8 @@ public class GameController implements GameCallback {
|
|||
@Override
|
||||
public void event(TableEvent event) {
|
||||
try {
|
||||
PriorityTimer timer;
|
||||
UUID playerId;
|
||||
switch (event.getEventType()) {
|
||||
case UPDATE:
|
||||
updateGame();
|
||||
|
@ -124,6 +131,44 @@ public class GameController implements GameCallback {
|
|||
case ERROR:
|
||||
error(event.getMessage(), event.getException());
|
||||
break;
|
||||
case INIT_TIMER:
|
||||
final UUID initPlayerId = event.getPlayerId();
|
||||
if (initPlayerId == null) {
|
||||
throw new IllegalStateException("INIT_TIMER: playerId can't be null");
|
||||
}
|
||||
long delay = 250L; // run each 250 ms
|
||||
timer = new PriorityTimer(Constants.PRIORITY_TIME_SEC, delay, new Action() {
|
||||
@Override
|
||||
public void execute() throws MageException {
|
||||
game.concede(initPlayerId);
|
||||
logger.info("Game timeout for player: " + initPlayerId + ". Conceding.");
|
||||
}
|
||||
});
|
||||
timers.put(initPlayerId, timer);
|
||||
timer.init();
|
||||
break;
|
||||
case RESUME_TIMER:
|
||||
playerId = event.getPlayerId();
|
||||
if (playerId == null) {
|
||||
throw new IllegalStateException("RESUME_TIMER: playerId can't be null");
|
||||
}
|
||||
timer = timers.get(playerId);
|
||||
if (timer == null) {
|
||||
throw new IllegalStateException("RESUME_TIMER: couldn't find timer for player: " + playerId);
|
||||
}
|
||||
timer.resume();
|
||||
break;
|
||||
case PAUSE_TIMER:
|
||||
playerId = event.getPlayerId();
|
||||
if (playerId == null) {
|
||||
throw new IllegalStateException("PAUSE_TIMER: playerId can't be null");
|
||||
}
|
||||
timer = timers.get(playerId);
|
||||
if (timer == null) {
|
||||
throw new IllegalStateException("PAUSE_TIMER: couldn't find timer for player: " + playerId);
|
||||
}
|
||||
timer.pause();
|
||||
break;
|
||||
}
|
||||
} catch (MageException ex) {
|
||||
logger.fatal("Table event listener error ", ex);
|
||||
|
@ -388,6 +433,12 @@ public class GameController implements GameCallback {
|
|||
}
|
||||
|
||||
private synchronized void updateGame() {
|
||||
for (Player player: game.getState().getPlayers().values()) {
|
||||
PriorityTimer timer = timers.get(player.getId());
|
||||
if (timer != null) {
|
||||
player.setPriorityTimeLeft(timer.getCount());
|
||||
}
|
||||
}
|
||||
for (final GameSession gameSession: gameSessions.values()) {
|
||||
gameSession.update();
|
||||
}
|
||||
|
|
80
Mage.Sets/src/mage/sets/alarareborn/KathariBomber.java
Normal file
80
Mage.Sets/src/mage/sets/alarareborn/KathariBomber.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.sets.alarareborn;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.SacrificeSourceEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.UnearthAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.game.permanent.token.GoblinToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class KathariBomber extends CardImpl<KathariBomber> {
|
||||
|
||||
public KathariBomber(UUID ownerId) {
|
||||
super(ownerId, 41, "Kathari Bomber", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}{R}");
|
||||
this.expansionSetCode = "ARB";
|
||||
this.subtype.add("Bird");
|
||||
this.subtype.add("Shaman");
|
||||
|
||||
this.color.setRed(true);
|
||||
this.color.setBlack(true);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
// When Kathari Bomber deals combat damage to a player, put two 1/1 red Goblin creature tokens onto the battlefield and sacrifice Kathari Bomber.
|
||||
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new CreateTokenEffect(new GoblinToken(), 2), false);
|
||||
ability.addEffect(new SacrificeSourceEffect());
|
||||
this.addAbility(ability);
|
||||
|
||||
// Unearth {3}{B}{R}
|
||||
this.addAbility(new UnearthAbility(new ManaCostsImpl("{3}{B}{R}")));
|
||||
}
|
||||
|
||||
public KathariBomber(final KathariBomber card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KathariBomber copy() {
|
||||
return new KathariBomber(this);
|
||||
}
|
||||
}
|
|
@ -62,6 +62,7 @@ public class Earthshaker extends CardImpl<Earthshaker> {
|
|||
this.color.setRed(true);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(5);
|
||||
// Whenever you cast a Spirit or Arcane spell, Earthshaker deals 2 damage to each creature without flying.
|
||||
this.addAbility(new SpellCastTriggeredAbility(new DamageAllEffect(new StaticValue(2) , creatureFilter), filter, false));
|
||||
}
|
||||
|
||||
|
|
108
Mage.Sets/src/mage/sets/conflux/BrackwaterElemental.java
Normal file
108
Mage.Sets/src/mage/sets/conflux/BrackwaterElemental.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.sets.conflux;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.common.AttacksOrBlocksTriggeredAbility;
|
||||
import mage.abilities.common.delayed.AtEndOfTurnDelayedTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.SacrificeTargetEffect;
|
||||
import mage.abilities.keyword.UnearthAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class BrackwaterElemental extends CardImpl<BrackwaterElemental> {
|
||||
|
||||
public BrackwaterElemental(UUID ownerId) {
|
||||
super(ownerId, 21, "Brackwater Elemental", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{U}");
|
||||
this.expansionSetCode = "CON";
|
||||
this.subtype.add("Elemental");
|
||||
|
||||
this.color.setBlue(true);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// When Brackwater Elemental attacks or blocks, sacrifice it at the beginning of the next end step.
|
||||
this.addAbility(new AttacksOrBlocksTriggeredAbility(new BrackwaterElementalSacrificeEffect(), false));
|
||||
// Unearth {2}{U}
|
||||
this.addAbility(new UnearthAbility(new ManaCostsImpl("{2}{U}")));
|
||||
}
|
||||
|
||||
public BrackwaterElemental(final BrackwaterElemental card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrackwaterElemental copy() {
|
||||
return new BrackwaterElemental(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BrackwaterElementalSacrificeEffect extends OneShotEffect<BrackwaterElementalSacrificeEffect> {
|
||||
|
||||
public BrackwaterElementalSacrificeEffect() {
|
||||
super(Outcome.Sacrifice);
|
||||
this.staticText = "sacrifice it at the beginning of the next end step";
|
||||
}
|
||||
|
||||
public BrackwaterElementalSacrificeEffect(final BrackwaterElementalSacrificeEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrackwaterElementalSacrificeEffect copy() {
|
||||
return new BrackwaterElementalSacrificeEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (sourcePermanent != null) {
|
||||
SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("sacrifice {this}");
|
||||
sacrificeEffect.setTargetPointer(new FixedTarget(sourcePermanent.getId()));
|
||||
DelayedTriggeredAbility delayedAbility = new AtEndOfTurnDelayedTriggeredAbility(sacrificeEffect);
|
||||
delayedAbility.setSourceId(source.getSourceId());
|
||||
delayedAbility.setControllerId(source.getControllerId());
|
||||
game.addDelayedTriggeredAbility(delayedAbility);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -32,8 +32,7 @@ import java.util.UUID;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DiscardControllerEffect;
|
||||
import mage.abilities.effects.common.DrawCardControllerEffect;
|
||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.abilities.keyword.FlashbackAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.TimingRule;
|
||||
|
@ -51,8 +50,7 @@ public class FaithlessLooting extends CardImpl<FaithlessLooting> {
|
|||
this.color.setRed(true);
|
||||
|
||||
// Draw two cards, then discard two cards.
|
||||
this.getSpellAbility().addEffect(new DrawCardControllerEffect(2));
|
||||
this.getSpellAbility().addEffect(new DiscardControllerEffect(2));
|
||||
this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(2,2));
|
||||
// Flashback {2}{R}
|
||||
this.addAbility(new FlashbackAbility(new ManaCostsImpl("{2}{R}"), TimingRule.SORCERY));
|
||||
}
|
||||
|
|
52
Mage.Sets/src/mage/sets/dissension/TrygonPredator.java
Normal file
52
Mage.Sets/src/mage/sets/dissension/TrygonPredator.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.dissension;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class TrygonPredator extends mage.sets.modernmasters.TrygonPredator {
|
||||
|
||||
public TrygonPredator(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 133;
|
||||
this.expansionSetCode = "DIS";
|
||||
}
|
||||
|
||||
public TrygonPredator(final TrygonPredator card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrygonPredator copy() {
|
||||
return new TrygonPredator(this);
|
||||
}
|
||||
}
|
|
@ -35,8 +35,8 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.StateTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SkipUntapOptionalAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.ControlsPermanentCondition;
|
||||
import mage.abilities.condition.common.SourceTappedCondition;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.decorator.ConditionalContinousEffect;
|
||||
import mage.abilities.effects.common.SacrificeSourceEffect;
|
||||
|
@ -89,7 +89,7 @@ public class Seasinger extends CardImpl<Seasinger> {
|
|||
this.addAbility(new SkipUntapOptionalAbility());
|
||||
|
||||
// {tap}: Gain control of target creature whose controller controls an Island for as long as you control Seasinger and Seasinger remains tapped.
|
||||
ConditionalContinousEffect effect = new ConditionalContinousEffect(new GainControlTargetEffect(Duration.Custom), new ControlsPermanentCondition(seasinger, ControlsPermanentCondition.CountType.EQUAL_TO, 1, TappedCondition.getInstance()), rule);
|
||||
ConditionalContinousEffect effect = new ConditionalContinousEffect(new GainControlTargetEffect(Duration.Custom), new ControlsPermanentCondition(seasinger, ControlsPermanentCondition.CountType.EQUAL_TO, 1, SourceTappedCondition.getInstance()), rule);
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
|
||||
creatureWhoseControllerControlsIsland.add(new ControllerControlsIslandPredicate());
|
||||
ability.addTarget(new TargetCreaturePermanent(creatureWhoseControllerControlsIsland));
|
||||
|
@ -148,21 +148,3 @@ class SeasingerTriggeredAbility extends StateTriggeredAbility<SeasingerTriggered
|
|||
return "When you control no islands, sacrifice {this}.";
|
||||
}
|
||||
}
|
||||
|
||||
class TappedCondition implements Condition {
|
||||
|
||||
private static TappedCondition fInstance = new TappedCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent seasinger = game.getBattlefield().getPermanent(source.getSourceId());
|
||||
if (seasinger != null) {
|
||||
return seasinger.isTapped();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
54
Mage.Sets/src/mage/sets/fifthdawn/VedalkenShackles.java
Normal file
54
Mage.Sets/src/mage/sets/fifthdawn/VedalkenShackles.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.fifthdawn;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.Rarity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class VedalkenShackles extends mage.sets.modernmasters.VedalkenShackles {
|
||||
|
||||
public VedalkenShackles(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 164;
|
||||
this.expansionSetCode = "5DN";
|
||||
this.rarity = Rarity.RARE;
|
||||
}
|
||||
|
||||
public VedalkenShackles(final VedalkenShackles card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VedalkenShackles copy() {
|
||||
return new VedalkenShackles(this);
|
||||
}
|
||||
}
|
54
Mage.Sets/src/mage/sets/futuresight/DeathRattle.java
Normal file
54
Mage.Sets/src/mage/sets/futuresight/DeathRattle.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.futuresight;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.Rarity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class DeathRattle extends mage.sets.modernmasters.DeathRattle {
|
||||
|
||||
public DeathRattle(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 82;
|
||||
this.expansionSetCode = "FUT";
|
||||
this.rarity = Rarity.COMMON;
|
||||
}
|
||||
|
||||
public DeathRattle(final DeathRattle card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeathRattle copy() {
|
||||
return new DeathRattle(this);
|
||||
}
|
||||
}
|
52
Mage.Sets/src/mage/sets/futuresight/LogicKnot.java
Normal file
52
Mage.Sets/src/mage/sets/futuresight/LogicKnot.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.futuresight;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class LogicKnot extends mage.sets.modernmasters.LogicKnot {
|
||||
|
||||
public LogicKnot(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 52;
|
||||
this.expansionSetCode = "FUT";
|
||||
}
|
||||
|
||||
public LogicKnot(final LogicKnot card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicKnot copy() {
|
||||
return new LogicKnot(this);
|
||||
}
|
||||
}
|
52
Mage.Sets/src/mage/sets/futuresight/MoltenDisaster.java
Normal file
52
Mage.Sets/src/mage/sets/futuresight/MoltenDisaster.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.futuresight;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MoltenDisaster extends mage.sets.modernmasters.MoltenDisaster {
|
||||
|
||||
public MoltenDisaster(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 102;
|
||||
this.expansionSetCode = "FUT";
|
||||
}
|
||||
|
||||
public MoltenDisaster(final MoltenDisaster card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoltenDisaster copy() {
|
||||
return new MoltenDisaster(this);
|
||||
}
|
||||
}
|
52
Mage.Sets/src/mage/sets/futuresight/Tombstalker.java
Normal file
52
Mage.Sets/src/mage/sets/futuresight/Tombstalker.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.futuresight;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class Tombstalker extends mage.sets.modernmasters.Tombstalker {
|
||||
|
||||
public Tombstalker(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 91;
|
||||
this.expansionSetCode = "FUT";
|
||||
}
|
||||
|
||||
public Tombstalker(final Tombstalker card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tombstalker copy() {
|
||||
return new Tombstalker(this);
|
||||
}
|
||||
}
|
|
@ -28,14 +28,13 @@
|
|||
package mage.sets.innistrad;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.game.Game;
|
||||
|
@ -98,7 +97,7 @@ class NightTerrorsEffect extends OneShotEffect<NightTerrorsEffect> {
|
|||
if (player.choose(Outcome.Exile, targetPlayer.getHand(), target, game)) {
|
||||
Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
card.moveToExile(null, "", source.getId(), game);
|
||||
card.moveToExile(null, "", source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
52
Mage.Sets/src/mage/sets/lorwyn/RunedStalactite.java
Normal file
52
Mage.Sets/src/mage/sets/lorwyn/RunedStalactite.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.lorwyn;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class RunedStalactite extends mage.sets.modernmasters.RunedStalactite {
|
||||
|
||||
public RunedStalactite(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 260;
|
||||
this.expansionSetCode = "LRW";
|
||||
}
|
||||
|
||||
public RunedStalactite(final RunedStalactite card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunedStalactite copy() {
|
||||
return new RunedStalactite(this);
|
||||
}
|
||||
}
|
52
Mage.Sets/src/mage/sets/lorwyn/ThundercloudShaman.java
Normal file
52
Mage.Sets/src/mage/sets/lorwyn/ThundercloudShaman.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.lorwyn;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ThundercloudShaman extends mage.sets.modernmasters.ThundercloudShaman {
|
||||
|
||||
public ThundercloudShaman(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 195;
|
||||
this.expansionSetCode = "LRW";
|
||||
}
|
||||
|
||||
public ThundercloudShaman(final ThundercloudShaman card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThundercloudShaman copy() {
|
||||
return new ThundercloudShaman(this);
|
||||
}
|
||||
}
|
|
@ -29,9 +29,6 @@
|
|||
package mage.sets.mirrodinbesieged;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
|
@ -41,9 +38,13 @@ import mage.abilities.effects.common.continious.BoostSourceEffect;
|
|||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterArtifactPermanent;
|
||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -51,6 +52,11 @@ import mage.filter.common.FilterArtifactPermanent;
|
|||
*/
|
||||
public class HellkiteIgniter extends CardImpl<HellkiteIgniter> {
|
||||
|
||||
private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("artifact you control");
|
||||
static {
|
||||
filter.add(new ControllerPredicate(TargetController.YOU));
|
||||
}
|
||||
|
||||
public HellkiteIgniter (UUID ownerId) {
|
||||
super(ownerId, 65, "Hellkite Igniter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{R}{R}");
|
||||
this.expansionSetCode = "MBS";
|
||||
|
@ -58,11 +64,14 @@ public class HellkiteIgniter extends CardImpl<HellkiteIgniter> {
|
|||
this.color.setRed(true);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Flying, haste
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
// {1}{R}: Hellkite Igniter gets +X/+0 until end of turn, where X is the number of artifacts you control.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new BoostSourceEffect(
|
||||
new PermanentsOnBattlefieldCount(new FilterArtifactPermanent()),
|
||||
new PermanentsOnBattlefieldCount(filter),
|
||||
new StaticValue(0),
|
||||
Duration.EndOfTurn),
|
||||
new ManaCostsImpl("{1}{R}")));
|
||||
|
|
|
@ -28,12 +28,13 @@
|
|||
package mage.sets.mirrodinbesieged;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SpellCastTriggeredAbility;
|
||||
import mage.abilities.effects.common.UntapTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
|
@ -53,6 +54,11 @@ public class MirranSpy extends CardImpl<MirranSpy> {
|
|||
this.color.setBlue(true);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Whenever you cast an artifact spell, you may untap target creature.
|
||||
SpellCastTriggeredAbility ability = new SpellCastTriggeredAbility(new UntapTargetEffect(), filter, true);
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CarefulConsideration extends mage.sets.timespiral.CarefulConsideration {
|
||||
|
||||
public CarefulConsideration(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 37;
|
||||
this.expansionSetCode = "MMA";
|
||||
}
|
||||
|
||||
public CarefulConsideration(final CarefulConsideration card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CarefulConsideration copy() {
|
||||
return new CarefulConsideration(this);
|
||||
}
|
||||
}
|
76
Mage.Sets/src/mage/sets/modernmasters/DeathRattle.java
Normal file
76
Mage.Sets/src/mage/sets/modernmasters/DeathRattle.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.keyword.DelveAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class DeathRattle extends CardImpl<DeathRattle> {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
static {
|
||||
filter.add(Predicates.not(new ColorPredicate(ObjectColor.GREEN)));
|
||||
}
|
||||
|
||||
public DeathRattle(UUID ownerId) {
|
||||
super(ownerId, 78, "Death Rattle", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{5}{B}");
|
||||
this.expansionSetCode = "MMA";
|
||||
|
||||
this.color.setBlack(true);
|
||||
|
||||
// Delve
|
||||
this.addAbility(new DelveAbility());
|
||||
|
||||
// Destroy target nongreen creature. It can't be regenerated.
|
||||
this.getSpellAbility().addEffect(new DestroyTargetEffect(true));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(true));
|
||||
|
||||
}
|
||||
|
||||
public DeathRattle(final DeathRattle card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeathRattle copy() {
|
||||
return new DeathRattle(this);
|
||||
}
|
||||
}
|
52
Mage.Sets/src/mage/sets/modernmasters/DemigodOfRevenge.java
Normal file
52
Mage.Sets/src/mage/sets/modernmasters/DemigodOfRevenge.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class DemigodOfRevenge extends mage.sets.shadowmoor.DemigodOfRevenge {
|
||||
|
||||
public DemigodOfRevenge(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 187;
|
||||
this.expansionSetCode = "MMA";
|
||||
}
|
||||
|
||||
public DemigodOfRevenge(final DemigodOfRevenge card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemigodOfRevenge copy() {
|
||||
return new DemigodOfRevenge(this);
|
||||
}
|
||||
}
|
67
Mage.Sets/src/mage/sets/modernmasters/LogicKnot.java
Normal file
67
Mage.Sets/src/mage/sets/modernmasters/LogicKnot.java
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||
import mage.abilities.effects.common.CounterUnlessPaysEffect;
|
||||
import mage.abilities.keyword.DelveAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.target.TargetSpell;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class LogicKnot extends CardImpl<LogicKnot> {
|
||||
|
||||
public LogicKnot(UUID ownerId) {
|
||||
super(ownerId, 51, "Logic Knot", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{X}{U}{U}");
|
||||
this.expansionSetCode = "MMA";
|
||||
|
||||
this.color.setBlue(true);
|
||||
|
||||
// Delve
|
||||
this.addAbility(new DelveAbility());
|
||||
|
||||
// Counter target spell unless its controller pays {X}.
|
||||
this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new ManacostVariableValue()));
|
||||
this.getSpellAbility().addTarget(new TargetSpell());
|
||||
}
|
||||
|
||||
public LogicKnot(final LogicKnot card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicKnot copy() {
|
||||
return new LogicKnot(this);
|
||||
}
|
||||
}
|
152
Mage.Sets/src/mage/sets/modernmasters/MoltenDisaster.java
Normal file
152
Mage.Sets/src/mage/sets/modernmasters/MoltenDisaster.java
Normal file
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.condition.common.KickedCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continious.GainAbilitySourceEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.KickerAbility;
|
||||
import mage.abilities.keyword.SplitSecondAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MoltenDisaster extends CardImpl<MoltenDisaster> {
|
||||
|
||||
public MoltenDisaster(UUID ownerId) {
|
||||
super(ownerId, 123, "Molten Disaster", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{R}{R}");
|
||||
this.expansionSetCode = "MMA";
|
||||
|
||||
this.color.setRed(true);
|
||||
|
||||
// If Molten Disaster was kicked, it has split second.
|
||||
Ability ability = new ConditionalTriggeredAbility(new MoltenDisasterTriggeredAbility(), KickedCondition.getInstance(), "");
|
||||
ability.setRuleAtTheTop(true);
|
||||
this.addAbility(ability);
|
||||
// Kicker {R}
|
||||
this.addAbility(new KickerAbility("{R}"));
|
||||
// Molten Disaster deals X damage to each creature without flying and each player.
|
||||
this.getSpellAbility().addEffect(new MoltenDisasterEffect());
|
||||
}
|
||||
|
||||
public MoltenDisaster(final MoltenDisaster card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoltenDisaster copy() {
|
||||
return new MoltenDisaster(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MoltenDisasterTriggeredAbility extends TriggeredAbilityImpl<MoltenDisasterTriggeredAbility> {
|
||||
|
||||
public MoltenDisasterTriggeredAbility() {
|
||||
super(Zone.HAND, new GainAbilitySourceEffect(SplitSecondAbility.getInstance(), Duration.WhileOnStack), false);
|
||||
}
|
||||
|
||||
public MoltenDisasterTriggeredAbility(final MoltenDisasterTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoltenDisasterTriggeredAbility copy() {
|
||||
return new MoltenDisasterTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType().equals(GameEvent.EventType.CAST_SPELL) && event.getSourceId().equals(this.getSourceId())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "If Molten Disaster was kicked, it has split second <i>(As long as this spell is on the stack, players can't cast spells or activate abilities that aren't mana abilities.)</i>";
|
||||
}
|
||||
}
|
||||
|
||||
class MoltenDisasterEffect extends OneShotEffect<MoltenDisasterEffect> {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
|
||||
}
|
||||
|
||||
public MoltenDisasterEffect() {
|
||||
super(Outcome.Damage);
|
||||
staticText = "{this} deals X damage to each creature without flying and each player";
|
||||
}
|
||||
|
||||
public MoltenDisasterEffect(final MoltenDisasterEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoltenDisasterEffect copy() {
|
||||
return new MoltenDisasterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int amount = source.getManaCostsToPay().getX();
|
||||
for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
|
||||
permanent.damage(amount, source.getId(), game, true, false);
|
||||
}
|
||||
for (UUID playerId: game.getPlayer(source.getControllerId()).getInRange()) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.damage(amount, source.getSourceId(), game, false, true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
74
Mage.Sets/src/mage/sets/modernmasters/RunedStalactite.java
Normal file
74
Mage.Sets/src/mage/sets/modernmasters/RunedStalactite.java
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.continious.BoostEquippedEffect;
|
||||
import mage.abilities.effects.common.continious.GainAbilityAttachedEffect;
|
||||
import mage.abilities.keyword.ChangelingAbility;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.AttachmentType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class RunedStalactite extends CardImpl<RunedStalactite> {
|
||||
|
||||
public RunedStalactite(UUID ownerId) {
|
||||
super(ownerId, 214, "Runed Stalactite", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}");
|
||||
this.expansionSetCode = "MMA";
|
||||
this.subtype.add("Equipment");
|
||||
|
||||
// Equipped creature gets +1/+1 and is every creature type.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1,1)));
|
||||
Effect effect = new GainAbilityAttachedEffect(ChangelingAbility.getInstance(), AttachmentType.EQUIPMENT, Duration.WhileOnBattlefield);
|
||||
effect.setText("Equipped creature is every creature type (Changeling)");
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||
// Equip {2}
|
||||
this.addAbility(new EquipAbility(Outcome.BoostCreature, new ManaCostsImpl("{2}")));
|
||||
}
|
||||
|
||||
public RunedStalactite(final RunedStalactite card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunedStalactite copy() {
|
||||
return new RunedStalactite(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DamageAllEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ThundercloudShaman extends CardImpl<ThundercloudShaman> {
|
||||
|
||||
private static final FilterCreaturePermanent filterGiants = new FilterCreaturePermanent("equal to the number of Giants you control");
|
||||
private static final FilterCreaturePermanent filterNonGiants = new FilterCreaturePermanent("non-Giant creature");
|
||||
static {
|
||||
filterGiants.add(new ControllerPredicate(TargetController.YOU));
|
||||
filterGiants.add(new SubtypePredicate("Giant"));
|
||||
filterNonGiants.add(Predicates.not(new SubtypePredicate("Giant")));
|
||||
}
|
||||
|
||||
public ThundercloudShaman(UUID ownerId) {
|
||||
super(ownerId, 135, "Thundercloud Shaman", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{R}{R}");
|
||||
this.expansionSetCode = "MMA";
|
||||
this.subtype.add("Giant");
|
||||
this.subtype.add("Shaman");
|
||||
|
||||
this.color.setRed(true);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// When Thundercloud Shaman enters the battlefield, it deals damage equal to the number of Giants you control to each non-Giant creature.
|
||||
Effect effect = new DamageAllEffect(new PermanentsOnBattlefieldCount(filterGiants),filterNonGiants);
|
||||
effect.setText("it deals damage equal to the number of Giants you control to each non-Giant creature");
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(effect, false));
|
||||
}
|
||||
|
||||
public ThundercloudShaman(final ThundercloudShaman card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThundercloudShaman copy() {
|
||||
return new ThundercloudShaman(this);
|
||||
}
|
||||
}
|
52
Mage.Sets/src/mage/sets/modernmasters/TidehollowSculler.java
Normal file
52
Mage.Sets/src/mage/sets/modernmasters/TidehollowSculler.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class TidehollowSculler extends mage.sets.shardsofalara.TidehollowSculler {
|
||||
|
||||
public TidehollowSculler(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 184;
|
||||
this.expansionSetCode = "MMA";
|
||||
}
|
||||
|
||||
public TidehollowSculler(final TidehollowSculler card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TidehollowSculler copy() {
|
||||
return new TidehollowSculler(this);
|
||||
}
|
||||
}
|
70
Mage.Sets/src/mage/sets/modernmasters/Tombstalker.java
Normal file
70
Mage.Sets/src/mage/sets/modernmasters/Tombstalker.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.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.keyword.DelveAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class Tombstalker extends CardImpl<Tombstalker> {
|
||||
|
||||
public Tombstalker(UUID ownerId) {
|
||||
super(ownerId, 102, "Tombstalker", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{6}{B}{B}");
|
||||
this.expansionSetCode = "MMA";
|
||||
this.subtype.add("Demon");
|
||||
|
||||
this.color.setBlack(true);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
// Delve
|
||||
Ability ability = new DelveAbility();
|
||||
ability.setRuleAtTheTop(false);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public Tombstalker(final Tombstalker card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tombstalker copy() {
|
||||
return new Tombstalker(this);
|
||||
}
|
||||
}
|
121
Mage.Sets/src/mage/sets/modernmasters/TrygonPredator.java
Normal file
121
Mage.Sets/src/mage/sets/modernmasters/TrygonPredator.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.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedPlayerEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class TrygonPredator extends CardImpl<TrygonPredator> {
|
||||
|
||||
public TrygonPredator(UUID ownerId) {
|
||||
super(ownerId, 185, "Trygon Predator", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{G}{U}");
|
||||
this.expansionSetCode = "MMA";
|
||||
this.subtype.add("Beast");
|
||||
|
||||
this.color.setBlue(true);
|
||||
this.color.setGreen(true);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
// Whenever Trygon Predator deals combat damage to a player, you may destroy target artifact or enchantment that player controls.
|
||||
this.addAbility(new TrygonPredatorTriggeredAbility());
|
||||
}
|
||||
|
||||
public TrygonPredator(final TrygonPredator card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrygonPredator copy() {
|
||||
return new TrygonPredator(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TrygonPredatorTriggeredAbility extends TriggeredAbilityImpl<TrygonPredatorTriggeredAbility> {
|
||||
|
||||
public TrygonPredatorTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true);
|
||||
}
|
||||
|
||||
public TrygonPredatorTriggeredAbility(final TrygonPredatorTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrygonPredatorTriggeredAbility copy() {
|
||||
return new TrygonPredatorTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType() == EventType.DAMAGED_PLAYER && event.getSourceId().equals(this.sourceId)
|
||||
&& ((DamagedPlayerEvent) event).isCombatDamage()) {
|
||||
Player player = game.getPlayer(event.getTargetId());
|
||||
if (player != null) {
|
||||
FilterPermanent filter = new FilterPermanent("an artifact or enchantment controlled by " + player.getName());
|
||||
filter.add(Predicates.or(
|
||||
new CardTypePredicate(CardType.ARTIFACT),
|
||||
new CardTypePredicate(CardType.ENCHANTMENT)));
|
||||
filter.add(new ControllerIdPredicate(event.getTargetId()));
|
||||
|
||||
this.getTargets().clear();
|
||||
this.addTarget(new TargetPermanent(filter));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} deals combat damage to a player, you may destroy target artifact or enchantment that player controls.";
|
||||
}
|
||||
}
|
113
Mage.Sets/src/mage/sets/modernmasters/VedalkenShackles.java
Normal file
113
Mage.Sets/src/mage/sets/modernmasters/VedalkenShackles.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.sets.modernmasters;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SkipUntapOptionalAbility;
|
||||
import mage.abilities.condition.common.SourceTappedCondition;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.decorator.ConditionalContinousEffect;
|
||||
import mage.abilities.effects.common.continious.GainControlTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.common.FilterLandPermanent;
|
||||
import mage.filter.predicate.ObjectPlayer;
|
||||
import mage.filter.predicate.ObjectPlayerPredicate;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class VedalkenShackles extends CardImpl<VedalkenShackles> {
|
||||
|
||||
private static final FilterCreaturePermanent controllableCreatures = new FilterCreaturePermanent("creature with power less than or equal to the number of Islands you control");
|
||||
static {
|
||||
controllableCreatures.add(new PowerIslandPredicate());
|
||||
}
|
||||
|
||||
|
||||
public VedalkenShackles(UUID ownerId) {
|
||||
super(ownerId, 218, "Vedalken Shackles", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
this.expansionSetCode = "MMA";
|
||||
|
||||
// You may choose not to untap Vedalken Shackles during your untap step.
|
||||
this.addAbility(new SkipUntapOptionalAbility());
|
||||
|
||||
// {2}, {tap}: Gain control of target creature with power less than or equal to the number of Islands you control for as long as Vedalken Shackles remains tapped.
|
||||
ConditionalContinousEffect effect = new ConditionalContinousEffect(
|
||||
new GainControlTargetEffect(Duration.Custom), SourceTappedCondition.getInstance(),
|
||||
"Gain control of target creature with power less than or equal to the number of Islands you control for as long as {this} remains tapped");
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
|
||||
ability.addTarget(new TargetCreaturePermanent(controllableCreatures));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public VedalkenShackles(final VedalkenShackles card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VedalkenShackles copy() {
|
||||
return new VedalkenShackles(this);
|
||||
}
|
||||
}
|
||||
|
||||
class PowerIslandPredicate implements ObjectPlayerPredicate<ObjectPlayer<Permanent>> {
|
||||
|
||||
public static final FilterLandPermanent filter = new FilterLandPermanent("Island");
|
||||
static {
|
||||
filter.add(new SubtypePredicate("Island"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectPlayer<Permanent> input, Game game) {
|
||||
Permanent permanent = input.getObject();
|
||||
if (permanent != null) {
|
||||
int islands = game.getBattlefield().countAll(filter, input.getPlayerId(), game);
|
||||
if (permanent.getPower().getValue() <= islands) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "creature with power less than or equal to the number of Islands you control";
|
||||
}
|
||||
}
|
|
@ -36,11 +36,13 @@ import mage.MageInt;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.TurnPhase;
|
||||
import mage.game.Game;
|
||||
import mage.game.turn.TurnMod;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -80,15 +82,15 @@ class SkipNextCombatEffect extends OneShotEffect<SkipNextCombatEffect> {
|
|||
staticText = "that player skips his or her next combat phase";
|
||||
}
|
||||
|
||||
public SkipNextCombatEffect(SkipNextCombatEffect effect) {
|
||||
public SkipNextCombatEffect(final SkipNextCombatEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
UUID targetId = source.getFirstTarget();
|
||||
if (targetId != null) {
|
||||
game.getState().getTurnMods().add(new TurnMod(targetId, TurnPhase.COMBAT, null, true));
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (player != null) {
|
||||
game.getState().getTurnMods().add(new TurnMod(player.getId(), TurnPhase.COMBAT, null, true));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -96,6 +98,6 @@ class SkipNextCombatEffect extends OneShotEffect<SkipNextCombatEffect> {
|
|||
|
||||
@Override
|
||||
public SkipNextCombatEffect copy() {
|
||||
return new SkipNextCombatEffect();
|
||||
return new SkipNextCombatEffect(this);
|
||||
}
|
||||
}
|
|
@ -29,23 +29,22 @@
|
|||
package mage.sets.newphyrexia;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.ExileFromGraveCost;
|
||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.ExileTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterArtifactCard;
|
||||
import mage.game.permanent.token.GolemToken;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.common.TargetCardInGraveyard;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -56,10 +55,13 @@ public class ConversionChamber extends CardImpl<ConversionChamber> {
|
|||
public ConversionChamber (UUID ownerId) {
|
||||
super(ownerId, 133, "Conversion Chamber", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
this.expansionSetCode = "NPH";
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), new GenericManaCost(2));
|
||||
// {2}, {T}: Exile target artifact card from a graveyard. Put a charge counter on Conversion Chamber.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new GenericManaCost(2));
|
||||
ability.addEffect(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()));
|
||||
ability.addTarget(new TargetCardInGraveyard(new FilterArtifactCard("artifact card from a graveyard")));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(new FilterArtifactCard("artifact card from a graveyard"))));
|
||||
this.addAbility(ability);
|
||||
// {2}, {T}, Remove a charge counter from Conversion Chamber: Put a 3/3 colorless Golem artifact creature token onto the battlefield.
|
||||
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new GolemToken()), new GenericManaCost(2));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new RemoveCountersSourceCost(CounterType.CHARGE.createInstance()));
|
||||
|
|
|
@ -28,15 +28,16 @@
|
|||
package mage.sets.newphyrexia;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.continious.BoostSourceEffect;
|
||||
import mage.abilities.keyword.InfectAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -52,7 +53,10 @@ public class OgreMenial extends CardImpl<OgreMenial> {
|
|||
this.color.setRed(true);
|
||||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(4);
|
||||
// Infect (This creature deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters.)
|
||||
this.addAbility(InfectAbility.getInstance());
|
||||
|
||||
// {R}: Ogre Menial gets +1/+0 until end of turn.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}")));
|
||||
}
|
||||
|
||||
|
|
|
@ -27,13 +27,11 @@
|
|||
*/
|
||||
package mage.sets.odyssey;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.effects.common.DiscardControllerEffect;
|
||||
import mage.abilities.effects.common.DrawCardControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author magenoxx_at_gmail.com
|
||||
|
@ -47,8 +45,7 @@ public class CarefulStudy extends CardImpl<CarefulStudy> {
|
|||
this.color.setBlue(true);
|
||||
|
||||
// Draw two cards, then discard two cards.
|
||||
this.getSpellAbility().addEffect(new DrawCardControllerEffect(2));
|
||||
this.getSpellAbility().addEffect(new DiscardControllerEffect(2));
|
||||
this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(2,2));
|
||||
}
|
||||
|
||||
public CarefulStudy(final CarefulStudy card) {
|
||||
|
|
|
@ -56,7 +56,7 @@ public class EtchedOracle extends CardImpl<EtchedOracle> {
|
|||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(0);
|
||||
|
||||
// Sunburst
|
||||
// Sunburst (This enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.)
|
||||
this.addAbility(new SunburstAbility());
|
||||
// {1}, Remove four +1/+1 counters from Etched Oracle: Target player draws three cards.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardTargetEffect(3), new ManaCostsImpl("{1}"));
|
||||
|
|
|
@ -28,11 +28,6 @@
|
|||
package mage.sets.returntoravnica;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
|
||||
|
@ -41,6 +36,10 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
|
@ -52,6 +51,7 @@ import mage.game.permanent.Permanent;
|
|||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInGraveyard;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -156,7 +156,7 @@ class AngelOfSerenityEnterEffect extends OneShotEffect<AngelOfSerenityEnterEffec
|
|||
for (UUID permanentId : target.getTargets()) {
|
||||
Permanent permanent = game.getPermanent(permanentId);
|
||||
if (permanent != null) {
|
||||
result |= permanent.moveToExile(source.getSourceId(), "Angel of Serenity", source.getId(), game);
|
||||
result |= permanent.moveToExile(CardUtil.getCardExileZoneId(game, source), "Angel of Serenity", source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ class AngelOfSerenityEnterEffect extends OneShotEffect<AngelOfSerenityEnterEffec
|
|||
for (UUID cardId : target.getTargets()) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card != null) {
|
||||
result |= card.moveToExile(source.getSourceId(), "Angel of Serenity", source.getId(), game);
|
||||
result |= card.moveToExile(CardUtil.getCardExileZoneId(game, source), "Angel of Serenity", source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,15 +192,15 @@ class AngelOfSerenityLeaveEffect extends OneShotEffect<AngelOfSerenityLeaveEffec
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
ExileZone exZone = game.getExile().getExileZone(source.getSourceId());
|
||||
ExileZone exZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
|
||||
if (exZone != null) {
|
||||
for (Card card : exZone.getCards(game)) {
|
||||
if (card != null) {
|
||||
card.moveToZone(Zone.HAND, source.getId(), game, false);
|
||||
card.moveToZone(Zone.HAND, source.getSourceId(), game, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ import mage.abilities.Mode;
|
|||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.CounterUnlessPaysEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.DiscardControllerEffect;
|
||||
import mage.abilities.effects.common.DrawCardControllerEffect;
|
||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.Predicates;
|
||||
|
@ -73,8 +72,7 @@ public class IzzetCharm extends CardImpl<IzzetCharm> {
|
|||
|
||||
// or draw two cards, then discard two cards.
|
||||
mode = new Mode();
|
||||
mode.getEffects().add(new DrawCardControllerEffect(2));
|
||||
mode.getEffects().add(new DiscardControllerEffect(2));
|
||||
mode.getEffects().add(new DrawDiscardControllerEffect(2, 2));
|
||||
this.getSpellAbility().addMode(mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,9 @@
|
|||
package mage.sets.returntoravnica;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.effects.common.DiscardControllerEffect;
|
||||
import mage.abilities.effects.common.DrawCardControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
||||
/**
|
||||
|
@ -47,8 +46,7 @@ public class Thoughtflare extends CardImpl<Thoughtflare> {
|
|||
this.color.setRed(true);
|
||||
|
||||
// Draw four cards, then discard two cards.
|
||||
this.getSpellAbility().addEffect(new DrawCardControllerEffect(4));
|
||||
this.getSpellAbility().addEffect(new DiscardControllerEffect(2));
|
||||
this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(4, 2));
|
||||
}
|
||||
|
||||
public Thoughtflare(final Thoughtflare card) {
|
||||
|
|
|
@ -28,12 +28,6 @@
|
|||
|
||||
package mage.sets.scarsofmirrodin;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.*;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -51,6 +45,7 @@ import mage.abilities.effects.common.UntapTargetEffect;
|
|||
import mage.abilities.effects.common.continious.BecomesCreatureTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterLandPermanent;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
|
@ -62,6 +57,8 @@ import mage.game.permanent.token.Token;
|
|||
import mage.target.common.TargetCreatureOrPlayer;
|
||||
import mage.target.common.TargetLandPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Loki, North
|
||||
|
@ -95,7 +92,7 @@ public class KothOfTheHammer extends CardImpl<KothOfTheHammer> {
|
|||
// -2: Add {R} to your mana pool for each Mountain you control.
|
||||
this.addAbility(new LoyaltyAbility(new DynamicManaEffect(Mana.RedMana, new PermanentsOnBattlefieldCount(filterCount)), -2));
|
||||
|
||||
// -5: You get an emblem with "Mountains you control have ‘{T}: This land deals 1 damage to target creature or player.'
|
||||
// -5: You get an emblem with "Mountains you control have '{T}: This land deals 1 damage to target creature or player.'
|
||||
this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new KothOfTheHammerEmblem()), -5));
|
||||
}
|
||||
|
||||
|
|
145
Mage.Sets/src/mage/sets/shadowmoor/DemigodOfRevenge.java
Normal file
145
Mage.Sets/src/mage/sets/shadowmoor/DemigodOfRevenge.java
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.shadowmoor;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class DemigodOfRevenge extends CardImpl<DemigodOfRevenge> {
|
||||
|
||||
public DemigodOfRevenge(UUID ownerId) {
|
||||
super(ownerId, 183, "Demigod of Revenge", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{B/R}{B/R}{B/R}{B/R}{B/R}");
|
||||
this.expansionSetCode = "SHM";
|
||||
this.subtype.add("Spirit");
|
||||
this.subtype.add("Avatar");
|
||||
|
||||
this.color.setRed(true);
|
||||
this.color.setBlack(true);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
// Haste
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
// When you cast Demigod of Revenge, return all cards named Demigod of Revenge from your graveyard to the battlefield.
|
||||
this.addAbility(new DemigodOfRevengeTriggeredAbility());
|
||||
}
|
||||
|
||||
public DemigodOfRevenge(final DemigodOfRevenge card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemigodOfRevenge copy() {
|
||||
return new DemigodOfRevenge(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DemigodOfRevengeTriggeredAbility extends TriggeredAbilityImpl<DemigodOfRevengeTriggeredAbility> {
|
||||
|
||||
public DemigodOfRevengeTriggeredAbility() {
|
||||
super(Zone.STACK, new DemigodOfRevengeReturnEffect(), false);
|
||||
}
|
||||
|
||||
public DemigodOfRevengeTriggeredAbility(final DemigodOfRevengeTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemigodOfRevengeTriggeredAbility copy() {
|
||||
return new DemigodOfRevengeTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType().equals(GameEvent.EventType.SPELL_CAST) && event.getSourceId().equals(this.getSourceId())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When you cast Demigod of Revenge, " + super.getRule();
|
||||
}
|
||||
}
|
||||
|
||||
class DemigodOfRevengeReturnEffect extends OneShotEffect<DemigodOfRevengeReturnEffect> {
|
||||
|
||||
private static final FilterCard filter = new FilterCard();
|
||||
static {
|
||||
filter.add(new NamePredicate("Demigod of Revenge"));
|
||||
}
|
||||
|
||||
public DemigodOfRevengeReturnEffect() {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
staticText = "return all cards named Demigod of Revenge from your graveyard to the battlefield";
|
||||
}
|
||||
|
||||
public DemigodOfRevengeReturnEffect(final DemigodOfRevengeReturnEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemigodOfRevengeReturnEffect copy() {
|
||||
return new DemigodOfRevengeReturnEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
for (Card creature : player.getGraveyard().getCards(filter, game)) {
|
||||
creature.putOntoBattlefield(game, Zone.GRAVEYARD, source.getId(), source.getControllerId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
155
Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java
Normal file
155
Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.shardsofalara;
|
||||
|
||||
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.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class TidehollowSculler extends CardImpl<TidehollowSculler> {
|
||||
|
||||
public TidehollowSculler(UUID ownerId) {
|
||||
super(ownerId, 202, "Tidehollow Sculler", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{W}{B}");
|
||||
this.expansionSetCode = "ALA";
|
||||
this.subtype.add("Zombie");
|
||||
|
||||
this.color.setBlack(true);
|
||||
this.color.setWhite(true);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// When Tidehollow Sculler enters the battlefield, target opponent reveals his or her hand and you choose a nonland card from it. Exile that card.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new TidehollowScullerExileEffect(), false);
|
||||
ability.addTarget(new TargetOpponent(true));
|
||||
this.addAbility(ability);
|
||||
|
||||
|
||||
// When Tidehollow Sculler leaves the battlefield, return the exiled card to its owner's hand.
|
||||
this.addAbility(new LeavesBattlefieldTriggeredAbility(new TidehollowScullerLeaveEffect(), false ));
|
||||
}
|
||||
|
||||
public TidehollowSculler(final TidehollowSculler card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TidehollowSculler copy() {
|
||||
return new TidehollowSculler(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TidehollowScullerExileEffect extends OneShotEffect<TidehollowScullerExileEffect> {
|
||||
|
||||
public TidehollowScullerExileEffect() {
|
||||
super(Outcome.Exile);
|
||||
this.staticText = "target opponent reveals his or her hand and you choose a nonland card from it. Exile that card";
|
||||
}
|
||||
|
||||
public TidehollowScullerExileEffect(final TidehollowScullerExileEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TidehollowScullerExileEffect copy() {
|
||||
return new TidehollowScullerExileEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Player targetPlayer = game.getPlayer(source.getFirstTarget());
|
||||
if (player != null && targetPlayer != null) {
|
||||
targetPlayer.revealCards("Tidehollow Sculler", targetPlayer.getHand(), game);
|
||||
|
||||
TargetCard target = new TargetCard(Zone.PICK, new FilterNonlandCard("nonland card to exile"));
|
||||
target.setRequired(true);
|
||||
if (player.choose(Outcome.Exile, targetPlayer.getHand(), target, game)) {
|
||||
Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
card.moveToExile(CardUtil.getCardExileZoneId(game, source), "Tidehollow Sculler", source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class TidehollowScullerLeaveEffect extends OneShotEffect<TidehollowScullerLeaveEffect> {
|
||||
|
||||
public TidehollowScullerLeaveEffect() {
|
||||
super(Outcome.ReturnToHand);
|
||||
this.staticText = "return the exiled card to its owner's hand";
|
||||
}
|
||||
|
||||
public TidehollowScullerLeaveEffect(final TidehollowScullerLeaveEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TidehollowScullerLeaveEffect copy() {
|
||||
return new TidehollowScullerLeaveEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
ExileZone exZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
|
||||
if (exZone != null) {
|
||||
for (Card card : exZone.getCards(game)) {
|
||||
if (card != null) {
|
||||
card.moveToZone(Zone.HAND, source.getId(), game, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
65
Mage.Sets/src/mage/sets/tempest/EmmessiTome.java
Normal file
65
Mage.Sets/src/mage/sets/tempest/EmmessiTome.java
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.tempest;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class EmmessiTome extends CardImpl<EmmessiTome> {
|
||||
|
||||
public EmmessiTome(UUID ownerId) {
|
||||
super(ownerId, 274, "Emmessi Tome", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}");
|
||||
this.expansionSetCode = "TMP";
|
||||
|
||||
// {5}, {tap}: Draw two cards, then discard a card.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawDiscardControllerEffect(2,1), new ManaCostsImpl("{5}"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public EmmessiTome(final EmmessiTome card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmmessiTome copy() {
|
||||
return new EmmessiTome(this);
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ import java.util.UUID;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.effects.common.DiscardControllerEffect;
|
||||
import mage.abilities.effects.common.DrawCardControllerEffect;
|
||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
||||
/**
|
||||
|
@ -47,8 +47,7 @@ public class Sift extends CardImpl<Sift> {
|
|||
this.color.setBlue(true);
|
||||
|
||||
// Draw three cards, then discard a card.
|
||||
this.getSpellAbility().addEffect(new DrawCardControllerEffect(3));
|
||||
this.getSpellAbility().addEffect(new DiscardControllerEffect(1));
|
||||
this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(3,1));
|
||||
}
|
||||
|
||||
public Sift(final Sift card) {
|
||||
|
|
68
Mage.Sets/src/mage/sets/timespiral/CarefulConsideration.java
Normal file
68
Mage.Sets/src/mage/sets/timespiral/CarefulConsideration.java
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.timespiral;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.condition.common.MyMainPhaseCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.DrawDiscardTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.target.TargetPlayer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CarefulConsideration extends CardImpl<CarefulConsideration> {
|
||||
|
||||
public CarefulConsideration(UUID ownerId) {
|
||||
super(ownerId, 52, "Careful Consideration", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
|
||||
this.expansionSetCode = "TSP";
|
||||
|
||||
this.color.setBlue(true);
|
||||
|
||||
// Target player draws four cards, then discards three cards. If you cast this spell during your main phase, instead that player draws four cards, then discards two cards.
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new DrawDiscardTargetEffect(4,2),
|
||||
new DrawDiscardTargetEffect(4,3),
|
||||
MyMainPhaseCondition.getInstance(),
|
||||
"Target player draws four cards, then discards three cards. If you cast this spell during your main phase, instead that player draws four cards, then discards two cards"));
|
||||
this.getSpellAbility().addTarget(new TargetPlayer(true));
|
||||
}
|
||||
|
||||
public CarefulConsideration(final CarefulConsideration card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CarefulConsideration copy() {
|
||||
return new CarefulConsideration(this);
|
||||
}
|
||||
}
|
|
@ -28,10 +28,9 @@
|
|||
package mage.sets.urzaslegacy;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.effects.common.DiscardControllerEffect;
|
||||
import mage.abilities.effects.common.DrawCardControllerEffect;
|
||||
import mage.abilities.effects.common.UntapLandsEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
||||
|
@ -48,8 +47,7 @@ public class FranticSearch extends CardImpl<FranticSearch> {
|
|||
this.color.setBlue(true);
|
||||
|
||||
// Draw two cards, then discard two cards. Untap up to three lands.
|
||||
this.getSpellAbility().addEffect(new DrawCardControllerEffect(2));
|
||||
this.getSpellAbility().addEffect(new DiscardControllerEffect(2));
|
||||
this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(2, 2));
|
||||
this.getSpellAbility().addEffect(new UntapLandsEffect(3));
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
@ -49,7 +50,7 @@ public class Catalog extends CardImpl<Catalog> {
|
|||
this.color.setBlue(true);
|
||||
|
||||
// Draw two cards, then discard a card.
|
||||
this.getSpellAbility().addEffect(new CatalogEffect());
|
||||
this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(2,1));
|
||||
}
|
||||
|
||||
public Catalog(final Catalog card) {
|
||||
|
@ -61,31 +62,3 @@ public class Catalog extends CardImpl<Catalog> {
|
|||
return new Catalog(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CatalogEffect extends OneShotEffect<CatalogEffect> {
|
||||
|
||||
public CatalogEffect() {
|
||||
super(Outcome.DrawCard);
|
||||
this.staticText = "Draw two cards, then discard a card";
|
||||
}
|
||||
|
||||
public CatalogEffect(final CatalogEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CatalogEffect copy() {
|
||||
return new CatalogEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
player.drawCards(2, game);
|
||||
player.discard(1, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class ChainReaction extends CardImpl<ChainReaction> {
|
|||
|
||||
this.color.setRed(true);
|
||||
|
||||
// Chain Reaction deals X damage to each creature, where X is the number of creatures on the battlefield.
|
||||
this.getSpellAbility().addEffect(new DamageAllEffect(new PermanentsOnBattlefieldCount(new FilterCreaturePermanent()), new FilterCreaturePermanent()));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
|
||||
public class SourceTappedCondition implements Condition {
|
||||
|
||||
private static SourceTappedCondition fInstance = new SourceTappedCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
return permanent.isTapped();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
package mage.abilities.decorator;
|
||||
|
||||
import mage.constants.Duration;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.FixedCondition;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.game.Game;
|
||||
|
@ -84,6 +84,9 @@ public class ConditionalContinousEffect extends ContinuousEffectImpl<Conditional
|
|||
if (!condition.apply(game, source) && effect.getDuration() == Duration.OneUse) {
|
||||
used = true;
|
||||
}
|
||||
if (!condition.apply(game, source) && effect.getDuration() == Duration.Custom) {
|
||||
this.discard();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,7 +156,8 @@ public class ContinuousEffects implements Serializable {
|
|||
case WhileInGraveyard:
|
||||
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId());
|
||||
for (Ability ability: abilities) {
|
||||
if (ability.isInUseableZone(game, null, false)) {
|
||||
// If e.g. triggerd abilities (non static) created the effect, the ability must not be in usable zone (e.g. Unearth giving Haste effect)
|
||||
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, false)) {
|
||||
layerEffects.add(effect);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -28,11 +28,12 @@
|
|||
|
||||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.constants.Outcome;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -40,13 +41,29 @@ import mage.players.Player;
|
|||
*/
|
||||
public class DrawDiscardControllerEffect extends OneShotEffect<DrawDiscardControllerEffect> {
|
||||
|
||||
private int cardsToDraw;
|
||||
private int cardsToDiscard;
|
||||
|
||||
public DrawDiscardControllerEffect() {
|
||||
this(1,1);
|
||||
}
|
||||
|
||||
public DrawDiscardControllerEffect(int cardsToDraw, int cardsToDiscard) {
|
||||
super(Outcome.DrawCard);
|
||||
staticText = "Draw a card, then discard a card";
|
||||
this.cardsToDraw = cardsToDraw;
|
||||
this.cardsToDiscard = cardsToDiscard;
|
||||
staticText = new StringBuilder("Draw ")
|
||||
.append(cardsToDraw == 1?"a": CardUtil.numberToText(cardsToDraw))
|
||||
.append(" card").append(cardsToDraw == 1?" ": "s")
|
||||
.append(", then discard ")
|
||||
.append(cardsToDiscard == 1?"a": CardUtil.numberToText(cardsToDiscard))
|
||||
.append(" card").append(cardsToDiscard == 1?" ": "s").toString();
|
||||
}
|
||||
|
||||
public DrawDiscardControllerEffect(final DrawDiscardControllerEffect effect) {
|
||||
super(effect);
|
||||
this.cardsToDraw = effect.cardsToDraw;
|
||||
this.cardsToDiscard = effect.cardsToDiscard;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,8 +75,8 @@ public class DrawDiscardControllerEffect extends OneShotEffect<DrawDiscardContro
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
player.drawCards(1, game);
|
||||
player.discard(1, source, game);
|
||||
player.drawCards(cardsToDraw, game);
|
||||
player.discard(cardsToDiscard, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright 2011 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.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class DrawDiscardTargetEffect extends OneShotEffect<DrawDiscardTargetEffect> {
|
||||
|
||||
private int cardsToDraw;
|
||||
private int cardsToDiscard;
|
||||
|
||||
public DrawDiscardTargetEffect() {
|
||||
this(1,1);
|
||||
}
|
||||
|
||||
public DrawDiscardTargetEffect(int cardsToDraw, int cardsToDiscard) {
|
||||
super(Outcome.DrawCard);
|
||||
this.cardsToDraw = cardsToDraw;
|
||||
this.cardsToDiscard = cardsToDiscard;
|
||||
staticText = new StringBuilder("Target player draws ")
|
||||
.append(cardsToDraw == 1?"a": CardUtil.numberToText(cardsToDraw))
|
||||
.append(" card").append(cardsToDraw == 1?" ": "s")
|
||||
.append(", then discard ")
|
||||
.append(cardsToDiscard == 1?"a": CardUtil.numberToText(cardsToDiscard))
|
||||
.append(" card").append(cardsToDiscard == 1?" ": "s").toString();
|
||||
}
|
||||
|
||||
public DrawDiscardTargetEffect(final DrawDiscardTargetEffect effect) {
|
||||
super(effect);
|
||||
this.cardsToDraw = effect.cardsToDraw;
|
||||
this.cardsToDiscard = effect.cardsToDiscard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DrawDiscardTargetEffect copy() {
|
||||
return new DrawDiscardTargetEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (player != null) {
|
||||
player.drawCards(cardsToDraw, game);
|
||||
player.discard(cardsToDiscard, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -75,7 +75,7 @@ public class SacrificeTargetEffect extends OneShotEffect<SacrificeTargetEffect>
|
|||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
if ("".equals(staticText) && !mode.getTargets().isEmpty()) {
|
||||
if (staticText.isEmpty() && !mode.getTargets().isEmpty()) {
|
||||
if (mode.getTargets().get(0).getNumberOfTargets() == 1) {
|
||||
return "The controller of target " + mode.getTargets().get(0).getTargetName() + " sacrifices it";
|
||||
} else {
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
|
||||
package mage.abilities.effects.common.continious;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
|
@ -73,7 +73,7 @@ public class GainAbilitySourceEffect extends ContinuousEffectImpl<GainAbilitySou
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
permanent.addAbility(ability, game);
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
111
Mage/src/mage/abilities/keyword/DelveAbility.java
Normal file
111
Mage/src/mage/abilities/keyword/DelveAbility.java
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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.abilities.keyword;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.AdjustingSourceCosts;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
|
||||
/**
|
||||
* 702.64. Delve
|
||||
*
|
||||
* 702.64a Delve is a static ability that functions while the spell that has delve is on
|
||||
* the stack. "Delve" means "As an additional cost to cast this spell, you may exile any
|
||||
* number of cards from your graveyard. Each card exiled this way reduces the cost to cast
|
||||
* this spell by {1}." Using the delve ability follows the rules for paying additional
|
||||
* costs in rules 601.2b and 601.2e-g. #
|
||||
*
|
||||
* 702.64b Multiple instances of delve on the same spell are redundant.
|
||||
*
|
||||
* @author LevelX2
|
||||
*
|
||||
*/
|
||||
|
||||
public class DelveAbility extends SimpleStaticAbility implements AdjustingSourceCosts {
|
||||
|
||||
public DelveAbility() {
|
||||
super(Zone.STACK, null);
|
||||
this.setRuleAtTheTop(true);
|
||||
}
|
||||
|
||||
public DelveAbility(final DelveAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DelveAbility copy() {
|
||||
return new DelveAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player == null || !(ability instanceof SpellAbility)) {
|
||||
return;
|
||||
}
|
||||
Target target = new TargetCardInYourGraveyard(1, Integer.MAX_VALUE, new FilterCard());
|
||||
target.setTargetName("cards to delve from your graveyard");
|
||||
if (!target.canChoose(sourceId, controllerId, game)) {
|
||||
return;
|
||||
}
|
||||
if (player.chooseUse(Outcome.Detriment, "Delve cards from your graveyard?", game)) {
|
||||
player.chooseTarget(Outcome.Detriment, target, ability, game);
|
||||
if (target.getTargets().size() > 0) {
|
||||
int adjCost = 0;
|
||||
for (UUID cardId: target.getTargets()) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card == null) {
|
||||
continue;
|
||||
}
|
||||
card.moveToExile(null, null, this.getSourceId(), game);
|
||||
++adjCost;
|
||||
}
|
||||
game.informPlayers(new StringBuilder(player.getName()).append(" delved ")
|
||||
.append(adjCost).append(" creature").append(adjCost != 1?"s":"").append(" from his or her graveyard").toString());
|
||||
CardUtil.adjustCost((SpellAbility)ability, adjCost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Delve <i>(You may exile any number of cards from your graveyard as you cast this spell. It costs {1} less to cast for each card exiled this way.)</i>";
|
||||
}
|
||||
}
|
|
@ -75,7 +75,7 @@ public class InfectAbility extends StaticAbility<InfectAbility> implements MageS
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Infect";
|
||||
return "Infect <i>(This creature deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters.)</i>";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,10 +28,6 @@
|
|||
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
|
@ -39,8 +35,12 @@ import mage.abilities.costs.mana.ManaCosts;
|
|||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||
import mage.abilities.effects.common.ExileSourceEffect;
|
||||
import mage.abilities.effects.common.continious.GainAbilitySourceEffect;
|
||||
import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
|
||||
import mage.abilities.effects.common.continious.GainAbilitySourceEffect;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
|
@ -49,11 +49,19 @@ import mage.game.events.ZoneChangeEvent;
|
|||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*
|
||||
*
|
||||
* 702.82. Unearth
|
||||
*
|
||||
* 702.82a Unearth is an activated ability that functions while the card with unearth
|
||||
* is in a graveyard. "Unearth [cost]" means "[Cost]: Return this card from your graveyard
|
||||
* to the battlefield. It gains haste. Exile it at the beginning of the next end step.
|
||||
* If it would leave the battlefield, exile it instead of putting it anywhere else.
|
||||
* Activate this ability only any time you could cast a sorcery."
|
||||
*
|
||||
*/
|
||||
public class UnearthAbility extends ActivatedAbilityImpl<UnearthAbility> {
|
||||
|
||||
protected boolean unearthed;
|
||||
|
||||
public UnearthAbility(ManaCosts costs) {
|
||||
super(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(), costs);
|
||||
this.timing = TimingRule.SORCERY;
|
||||
|
@ -64,7 +72,6 @@ public class UnearthAbility extends ActivatedAbilityImpl<UnearthAbility> {
|
|||
|
||||
public UnearthAbility(final UnearthAbility ability) {
|
||||
super(ability);
|
||||
this.unearthed = ability.unearthed;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,13 +79,12 @@ public class UnearthAbility extends ActivatedAbilityImpl<UnearthAbility> {
|
|||
return new UnearthAbility(this);
|
||||
}
|
||||
|
||||
public boolean isUnearthed() {
|
||||
return unearthed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Unearth " + super.getRule();
|
||||
StringBuilder sb = new StringBuilder("Unearth ").append(this.getManaCosts().getText());
|
||||
sb.append(" <i>(").append(this.getManaCosts().getText());
|
||||
sb.append(": Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a sorcery.)");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -133,8 +139,9 @@ class UnearthLeavesBattlefieldEffect extends ReplacementEffectImpl<UnearthLeaves
|
|||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(source.getSourceId())) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent)event;
|
||||
if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() != Zone.EXILED)
|
||||
if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() != Zone.EXILED) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -149,5 +156,4 @@ class UnearthLeavesBattlefieldEffect extends ReplacementEffectImpl<UnearthLeaves
|
|||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
return apply(game, source);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,9 +30,11 @@ package mage.cards.repository;
|
|||
import com.j256.ormlite.field.DataType;
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.ObjectColor;
|
||||
|
@ -84,7 +86,17 @@ public class CardInfo {
|
|||
@DatabaseField
|
||||
protected boolean white;
|
||||
@DatabaseField
|
||||
protected boolean splitCard;
|
||||
@DatabaseField
|
||||
protected boolean flipCard;
|
||||
@DatabaseField
|
||||
protected boolean doubleFaced;
|
||||
@DatabaseField
|
||||
protected boolean nightCard;
|
||||
@DatabaseField
|
||||
protected String flipCardName;
|
||||
@DatabaseField
|
||||
protected String secondSideName;
|
||||
|
||||
public CardInfo() {
|
||||
}
|
||||
|
@ -98,7 +110,17 @@ public class CardInfo {
|
|||
this.toughness = card.getToughness().toString();
|
||||
this.convertedManaCost = card.getManaCost().convertedManaCost();
|
||||
this.rarity = card.getRarity();
|
||||
this.splitCard = card.isSplitCard();
|
||||
|
||||
this.flipCard = card.isFlipCard();
|
||||
this.flipCardName = card.getFlipCardName();
|
||||
|
||||
this.doubleFaced = card.canTransform();
|
||||
this.nightCard = card.isNightCard();
|
||||
Card secondSide = card.getSecondCardFace();
|
||||
if (secondSide != null) {
|
||||
this.secondSideName = secondSide.getName();
|
||||
}
|
||||
|
||||
this.blue = card.getColor().isBlue();
|
||||
this.black = card.getColor().isBlack();
|
||||
|
@ -144,7 +166,7 @@ public class CardInfo {
|
|||
for (String type : this.types.split(SEPARATOR)) {
|
||||
try {
|
||||
list.add(CardType.valueOf(type));
|
||||
} catch (Exception e) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
@ -217,4 +239,32 @@ public class CardInfo {
|
|||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public int getCardNumber() {
|
||||
return cardNumber;
|
||||
}
|
||||
|
||||
public boolean isSplitCard() {
|
||||
return splitCard;
|
||||
}
|
||||
|
||||
public boolean isFlipCard() {
|
||||
return flipCard;
|
||||
}
|
||||
|
||||
public String getFlipCardName() {
|
||||
return flipCardName;
|
||||
}
|
||||
|
||||
public boolean isDoubleFaced() {
|
||||
return doubleFaced;
|
||||
}
|
||||
|
||||
public boolean isNightCard() {
|
||||
return nightCard;
|
||||
}
|
||||
|
||||
public String getSecondSideName() {
|
||||
return secondSideName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public enum CardRepository {
|
|||
instance;
|
||||
|
||||
private static final String JDBC_URL = "jdbc:sqlite:db/cards.db";
|
||||
private static final long DB_VERSION = 6;
|
||||
private static final long DB_VERSION = 7;
|
||||
|
||||
private Random random = new Random();
|
||||
private Dao<CardInfo, Object> cardDao;
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
|
||||
package mage.game;
|
||||
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageItem;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -44,6 +41,10 @@ import mage.cards.Card;
|
|||
import mage.cards.Cards;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.choices.Choice;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.combat.Combat;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.events.GameEvent;
|
||||
|
@ -65,7 +66,6 @@ import mage.util.functions.ApplyToPermanent;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import mage.constants.Duration;
|
||||
|
||||
public interface Game extends MageItem, Serializable {
|
||||
|
||||
|
@ -225,4 +225,9 @@ public interface Game extends MageItem, Serializable {
|
|||
// controlling the behaviour of replacement effects
|
||||
void setScopeRelevant(boolean scopeRelevant);
|
||||
public boolean getScopeRelevant();
|
||||
|
||||
// players' timers
|
||||
void initTimer(UUID playerId);
|
||||
void resumeTimer(UUID playerId);
|
||||
void pauseTimer(UUID playerId);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
package mage.game;
|
||||
|
||||
import mage.Constants;
|
||||
import mage.constants.CardType;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
|
@ -49,12 +48,14 @@ import mage.actions.impl.MageAction;
|
|||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.choices.Choice;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterPlaneswalkerPermanent;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
|
@ -89,8 +90,6 @@ import java.io.IOException;
|
|||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
|
||||
|
||||
public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializable {
|
||||
|
@ -590,6 +589,7 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
|
|||
protected void init(UUID choosingPlayerId, GameOptions gameOptions) {
|
||||
for (Player player: state.getPlayers().values()) {
|
||||
player.beginTurn(this);
|
||||
initTimer(player.getId());
|
||||
}
|
||||
if (startMessage == null || startMessage.isEmpty()) {
|
||||
startMessage = "Game has started";
|
||||
|
@ -1946,4 +1946,20 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
|
|||
public void setStartMessage(String startMessage) {
|
||||
this.startMessage = startMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initTimer(UUID playerId) {
|
||||
tableEventSource.fireTableEvent(EventType.INIT_TIMER, playerId, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeTimer(UUID playerId) {
|
||||
tableEventSource.fireTableEvent(EventType.RESUME_TIMER, playerId, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseTimer(UUID playerId) {
|
||||
tableEventSource.fireTableEvent(EventType.PAUSE_TIMER, playerId, null, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@ import java.util.UUID;
|
|||
public class TableEvent extends EventObject implements ExternalEvent, Serializable {
|
||||
|
||||
public enum EventType {
|
||||
UPDATE, INFO, STATUS, REVEAL, LOOK, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, ERROR
|
||||
UPDATE, INFO, STATUS, REVEAL, LOOK, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, ERROR,
|
||||
INIT_TIMER, RESUME_TIMER, PAUSE_TIMER
|
||||
}
|
||||
|
||||
private Game game;
|
||||
|
|
|
@ -299,4 +299,18 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
*
|
||||
*/
|
||||
void revealFaceDownCard(Card card, Game game);
|
||||
|
||||
/**
|
||||
* Set seconds left to play the game.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
void setPriorityTimeLeft(int timeLeft);
|
||||
|
||||
/**
|
||||
* Returns seconds left to play the game.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int getPriorityTimeLeft();
|
||||
}
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
|
||||
package mage.players;
|
||||
|
||||
import mage.constants.*;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.*;
|
||||
|
@ -46,10 +44,13 @@ import mage.actions.MageDrawAction;
|
|||
import mage.cards.Card;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.constants.*;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.counters.Counters;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterCreatureForCombat;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
|
@ -59,11 +60,13 @@ import mage.game.events.DamagedPlayerEvent;
|
|||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.net.UserData;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetAmount;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.target.common.TargetDiscard;
|
||||
import mage.watchers.common.BloodthirstWatcher;
|
||||
|
@ -72,11 +75,6 @@ import org.apache.log4j.Logger;
|
|||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
import mage.cards.SplitCard;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.target.TargetCard;
|
||||
|
||||
|
||||
public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Serializable {
|
||||
|
||||
|
@ -108,6 +106,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
|
|||
protected boolean passedTurn;
|
||||
protected int turns;
|
||||
protected int storedBookmark = -1;
|
||||
protected int priorityTimeLeft;
|
||||
|
||||
/**
|
||||
* This indicates that player passed all turns until his own turn starts.
|
||||
|
@ -1793,4 +1792,14 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
|
|||
this.revealCards(name, cards, game);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPriorityTimeLeft(int timeLeft) {
|
||||
priorityTimeLeft = timeLeft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriorityTimeLeft() {
|
||||
return priorityTimeLeft;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
package mage.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -43,6 +44,7 @@ import mage.abilities.costs.mana.ManaCostsImpl;
|
|||
import mage.abilities.costs.mana.VariableManaCost;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.CardType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.util.functions.CopyFunction;
|
||||
import mage.util.functions.CopyTokenFunction;
|
||||
|
@ -365,4 +367,25 @@ public class CardUtil {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and saves a (card + zoneChangeCounter) specific exileId.
|
||||
*
|
||||
*
|
||||
* @param game
|
||||
* @param source - source ability
|
||||
* @return - the specific UUID
|
||||
*/
|
||||
public static UUID getCardExileZoneId(Game game, Ability source) {
|
||||
UUID exileId = null;
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card != null) {
|
||||
exileId = (UUID) game.getState().getValue(new StringBuilder("SourceExileZone").append(source.getSourceId()).append(card.getZoneChangeCounter()).toString());
|
||||
if (exileId == null) {
|
||||
exileId = UUID.randomUUID();
|
||||
game.getState().setValue(new StringBuilder("SourceExileZone").append(source.getSourceId()).append(card.getZoneChangeCounter()).toString(), exileId);
|
||||
}
|
||||
}
|
||||
return exileId;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue