mirror of
https://github.com/correl/mage.git
synced 2024-12-27 03:00:13 +00:00
Merge pull request #1 from magefree/master
Merge https://github.com/magefree/mage/
This commit is contained in:
commit
a4c6790f93
423 changed files with 15282 additions and 3325 deletions
|
@ -44,8 +44,6 @@ import javax.swing.event.PopupMenuEvent;
|
||||||
import javax.swing.event.PopupMenuListener;
|
import javax.swing.event.PopupMenuListener;
|
||||||
import mage.cards.action.ActionCallback;
|
import mage.cards.action.ActionCallback;
|
||||||
import mage.cards.decks.Deck;
|
import mage.cards.decks.Deck;
|
||||||
import mage.cards.repository.CardCriteria;
|
|
||||||
import mage.cards.repository.CardInfo;
|
|
||||||
import mage.cards.repository.CardRepository;
|
import mage.cards.repository.CardRepository;
|
||||||
import mage.client.cards.BigCard;
|
import mage.client.cards.BigCard;
|
||||||
import mage.client.chat.ChatPanelBasic;
|
import mage.client.chat.ChatPanelBasic;
|
||||||
|
@ -134,8 +132,6 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
||||||
|
|
||||||
private final BalloonTip balloonTip;
|
private final BalloonTip balloonTip;
|
||||||
|
|
||||||
private java.util.List<CardInfo> missingCards;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the session
|
* @return the session
|
||||||
*/
|
*/
|
||||||
|
@ -513,18 +509,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForNewImages() {
|
private void checkForNewImages() {
|
||||||
long beforeCall = System.currentTimeMillis();
|
// Removed TODO: Remove related pref code
|
||||||
missingCards = CardRepository.instance.findCards(new CardCriteria());
|
|
||||||
LOGGER.info("Card pool load time: " + ((System.currentTimeMillis() - beforeCall) / 1000 + " seconds"));
|
|
||||||
beforeCall = System.currentTimeMillis();
|
|
||||||
if (DownloadPictures.checkForMissingCardImages(missingCards)) {
|
|
||||||
LOGGER.info("Card images checking time: " + ((System.currentTimeMillis() - beforeCall) / 1000 + " seconds"));
|
|
||||||
UserRequestMessage message = new UserRequestMessage("New images available", "Card images are missing (" + missingCards.size() + "). Do you want to download the images?"
|
|
||||||
+ "<br><br><i>You can deactivate the image download check on application start in the preferences.</i>");
|
|
||||||
message.setButton1("No", null);
|
|
||||||
message.setButton2("Yes", PlayerAction.CLIENT_DOWNLOAD_CARD_IMAGES);
|
|
||||||
showUserRequestDialog(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setActive(MagePane frame) {
|
public static void setActive(MagePane frame) {
|
||||||
|
@ -978,8 +963,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
||||||
}//GEN-LAST:event_btnImagesActionPerformed
|
}//GEN-LAST:event_btnImagesActionPerformed
|
||||||
|
|
||||||
public void downloadImages() {
|
public void downloadImages() {
|
||||||
java.util.List<CardInfo> cards = CardRepository.instance.findCards(new CardCriteria());
|
DownloadPictures.startDownload();
|
||||||
DownloadPictures.startDownload(null, cards);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exitApp() {
|
public void exitApp() {
|
||||||
|
@ -1317,7 +1301,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
||||||
Plugins.instance.downloadSymbols();
|
Plugins.instance.downloadSymbols();
|
||||||
break;
|
break;
|
||||||
case CLIENT_DOWNLOAD_CARD_IMAGES:
|
case CLIENT_DOWNLOAD_CARD_IMAGES:
|
||||||
DownloadPictures.startDownload(null, missingCards);
|
DownloadPictures.startDownload();
|
||||||
break;
|
break;
|
||||||
case CLIENT_DISCONNECT:
|
case CLIENT_DISCONNECT:
|
||||||
if (SessionHandler.isConnected()) {
|
if (SessionHandler.isConnected()) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.mage.plugins.card.dl.sources;
|
package org.mage.plugins.card.dl.sources;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import org.mage.plugins.card.images.CardDownloadData;
|
import org.mage.plugins.card.images.CardDownloadData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,12 +10,38 @@ import org.mage.plugins.card.images.CardDownloadData;
|
||||||
public interface CardImageSource {
|
public interface CardImageSource {
|
||||||
|
|
||||||
String generateURL(CardDownloadData card) throws Exception;
|
String generateURL(CardDownloadData card) throws Exception;
|
||||||
|
|
||||||
String generateTokenUrl(CardDownloadData card) throws Exception;
|
String generateTokenUrl(CardDownloadData card) throws Exception;
|
||||||
|
|
||||||
String getNextHttpImageUrl();
|
String getNextHttpImageUrl();
|
||||||
|
|
||||||
String getFileForHttpImage(String httpImageUrl);
|
String getFileForHttpImage(String httpImageUrl);
|
||||||
|
|
||||||
String getSourceName();
|
String getSourceName();
|
||||||
|
|
||||||
float getAverageSize();
|
float getAverageSize();
|
||||||
|
|
||||||
int getTotalImages();
|
int getTotalImages();
|
||||||
boolean isTokenSource();
|
|
||||||
|
default int getTokenImages() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isTokenSource() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void doPause(String httpImageUrl);
|
void doPause(String httpImageUrl);
|
||||||
|
|
||||||
|
default ArrayList<String> getSupportedSets() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isSetSupportedComplete(String setCode) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isImageProvided(String setCode, String cardName) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,10 @@
|
||||||
package org.mage.plugins.card.dl.sources;
|
package org.mage.plugins.card.dl.sources;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import mage.client.dialog.PreferencesDialog;
|
import mage.client.dialog.PreferencesDialog;
|
||||||
import org.mage.plugins.card.images.CardDownloadData;
|
import org.mage.plugins.card.images.CardDownloadData;
|
||||||
import org.mage.plugins.card.utils.CardImageUtils;
|
import org.mage.plugins.card.utils.CardImageUtils;
|
||||||
|
@ -13,6 +16,202 @@ import org.mage.plugins.card.utils.CardImageUtils;
|
||||||
public enum MagicCardsImageSource implements CardImageSource {
|
public enum MagicCardsImageSource implements CardImageSource {
|
||||||
|
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
|
private static final Set<String> supportedSets = new LinkedHashSet<String>() {
|
||||||
|
{
|
||||||
|
// add("PTC"); // Prerelease Events
|
||||||
|
add("LEA");
|
||||||
|
add("LEB");
|
||||||
|
add("2ED");
|
||||||
|
add("ARN");
|
||||||
|
add("ATQ");
|
||||||
|
add("3ED");
|
||||||
|
add("LEG");
|
||||||
|
add("DRK");
|
||||||
|
add("FEM");
|
||||||
|
add("4ED");
|
||||||
|
add("ICE");
|
||||||
|
add("CHR");
|
||||||
|
add("HML");
|
||||||
|
add("ALL");
|
||||||
|
add("MIR");
|
||||||
|
add("VIS");
|
||||||
|
add("5ED");
|
||||||
|
add("POR");
|
||||||
|
add("WTH");
|
||||||
|
add("TMP");
|
||||||
|
add("STH");
|
||||||
|
add("EXO");
|
||||||
|
add("P02");
|
||||||
|
add("UGL");
|
||||||
|
add("USG");
|
||||||
|
add("DD3DVD");
|
||||||
|
add("DD3EVG");
|
||||||
|
add("DD3GVL");
|
||||||
|
add("DD3JVC");
|
||||||
|
|
||||||
|
add("ULG");
|
||||||
|
add("6ED");
|
||||||
|
add("UDS");
|
||||||
|
add("PTK");
|
||||||
|
add("S99");
|
||||||
|
add("MMQ");
|
||||||
|
// add("BRB");Battle Royale Box Set
|
||||||
|
add("NEM");
|
||||||
|
add("S00");
|
||||||
|
add("PCY");
|
||||||
|
add("INV");
|
||||||
|
// add("BTD"); // Beatdown Boxset
|
||||||
|
add("PLS");
|
||||||
|
add("7ED");
|
||||||
|
add("APC");
|
||||||
|
add("ODY");
|
||||||
|
// add("DKM"); // Deckmasters 2001
|
||||||
|
add("TOR");
|
||||||
|
add("JUD");
|
||||||
|
add("ONS");
|
||||||
|
add("LGN");
|
||||||
|
add("SCG");
|
||||||
|
add("8ED");
|
||||||
|
add("MRD");
|
||||||
|
add("DST");
|
||||||
|
add("5DN");
|
||||||
|
add("CHK");
|
||||||
|
add("UNH");
|
||||||
|
add("BOK");
|
||||||
|
add("SOK");
|
||||||
|
add("9ED");
|
||||||
|
add("RAV");
|
||||||
|
add("GPT");
|
||||||
|
add("DIS");
|
||||||
|
add("CSP");
|
||||||
|
add("TSP");
|
||||||
|
add("TSB");
|
||||||
|
add("PLC");
|
||||||
|
add("FUT");
|
||||||
|
add("10E");
|
||||||
|
add("MED");
|
||||||
|
add("LRW");
|
||||||
|
add("EVG");
|
||||||
|
add("MOR");
|
||||||
|
add("SHM");
|
||||||
|
add("EVE");
|
||||||
|
add("DRB");
|
||||||
|
add("ME2");
|
||||||
|
add("ALA");
|
||||||
|
add("DD2");
|
||||||
|
add("CON");
|
||||||
|
add("DDC");
|
||||||
|
add("ARB");
|
||||||
|
add("M10");
|
||||||
|
// add("TD0"); // Magic Online Deck Series
|
||||||
|
add("V09");
|
||||||
|
add("HOP");
|
||||||
|
add("ME3");
|
||||||
|
add("ZEN");
|
||||||
|
add("DDD");
|
||||||
|
add("H09");
|
||||||
|
add("WWK");
|
||||||
|
add("DDE");
|
||||||
|
add("ROE");
|
||||||
|
add("DPA");
|
||||||
|
add("ARC");
|
||||||
|
add("M11");
|
||||||
|
add("V10");
|
||||||
|
add("DDF");
|
||||||
|
add("SOM");
|
||||||
|
// add("TD0"); // Commander Theme Decks
|
||||||
|
add("PD2");
|
||||||
|
add("ME4");
|
||||||
|
add("MBS");
|
||||||
|
add("DDG");
|
||||||
|
add("NPH");
|
||||||
|
add("CMD");
|
||||||
|
add("M12");
|
||||||
|
add("V11");
|
||||||
|
add("DDH");
|
||||||
|
add("ISD");
|
||||||
|
add("PD3");
|
||||||
|
add("DKA");
|
||||||
|
add("DDI");
|
||||||
|
add("AVR");
|
||||||
|
add("PC2");
|
||||||
|
add("M13");
|
||||||
|
add("V12");
|
||||||
|
add("DDJ");
|
||||||
|
add("RTR");
|
||||||
|
add("CM1");
|
||||||
|
// add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia
|
||||||
|
add("GTC");
|
||||||
|
add("DDK");
|
||||||
|
add("DGM");
|
||||||
|
add("MMA");
|
||||||
|
add("M14");
|
||||||
|
add("V13");
|
||||||
|
add("DDL");
|
||||||
|
add("THS");
|
||||||
|
add("C13");
|
||||||
|
add("BNG");
|
||||||
|
add("DDM");
|
||||||
|
add("JOU");
|
||||||
|
// add("MD1"); // Modern Event Deck
|
||||||
|
add("CNS");
|
||||||
|
add("VMA");
|
||||||
|
add("M15");
|
||||||
|
add("V14");
|
||||||
|
add("DDN");
|
||||||
|
add("KTK");
|
||||||
|
add("C14");
|
||||||
|
// add("DD3"); // Duel Decks Anthology
|
||||||
|
add("FRF");
|
||||||
|
add("DDO");
|
||||||
|
add("DTK");
|
||||||
|
add("TPR");
|
||||||
|
add("MM2");
|
||||||
|
add("ORI");
|
||||||
|
add("V15");
|
||||||
|
add("DDP");
|
||||||
|
add("BFZ");
|
||||||
|
add("EXP");
|
||||||
|
add("C15");
|
||||||
|
// add("PZ1"); // Legendary Cube
|
||||||
|
add("OGW");
|
||||||
|
add("DDQ");
|
||||||
|
add("W16");
|
||||||
|
add("SOI");
|
||||||
|
add("EMA");
|
||||||
|
add("EMN");
|
||||||
|
add("V16");
|
||||||
|
add("CN2");
|
||||||
|
add("DDR");
|
||||||
|
add("KLD");
|
||||||
|
add("MPS");
|
||||||
|
// add("PZ2"); // Treasure Chests
|
||||||
|
add("C16");
|
||||||
|
add("PCA");
|
||||||
|
add("AER");
|
||||||
|
add("MM3");
|
||||||
|
add("DDS");
|
||||||
|
add("W17");
|
||||||
|
add("AKH");
|
||||||
|
add("MPS");
|
||||||
|
add("CMA");
|
||||||
|
add("E01");
|
||||||
|
add("HOU");
|
||||||
|
add("C17");
|
||||||
|
// add("XLN");
|
||||||
|
// add("DDT");
|
||||||
|
// add("IMA");
|
||||||
|
// add("E02");
|
||||||
|
// add("V17");
|
||||||
|
// add("UST");
|
||||||
|
// add("RIX");
|
||||||
|
// add("A25");
|
||||||
|
// add("DOM");
|
||||||
|
// add("M19");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private static final Map<String, String> setNameTokenReplacement = new HashMap<String, String>() {
|
private static final Map<String, String> setNameTokenReplacement = new HashMap<String, String>() {
|
||||||
{
|
{
|
||||||
put("10E", "tenth-edition");
|
put("10E", "tenth-edition");
|
||||||
|
@ -146,7 +345,6 @@ public enum MagicCardsImageSource implements CardImageSource {
|
||||||
return "magiccards.info";
|
return "magiccards.info";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNextHttpImageUrl() {
|
public String getNextHttpImageUrl() {
|
||||||
return null;
|
return null;
|
||||||
|
@ -221,7 +419,15 @@ public enum MagicCardsImageSource implements CardImageSource {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> getSupportedSets() {
|
||||||
|
ArrayList<String> supportedSetsCopy = new ArrayList<>();
|
||||||
|
supportedSetsCopy.addAll(supportedSets);
|
||||||
|
return supportedSetsCopy;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doPause(String httpImageUrl) {
|
public void doPause(String httpImageUrl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,21 +24,222 @@
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.mage.plugins.card.dl.sources;
|
package org.mage.plugins.card.dl.sources;
|
||||||
|
|
||||||
import org.mage.plugins.card.images.CardDownloadData;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.mage.plugins.card.images.CardDownloadData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Pete Rossi
|
* @author Pete Rossi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public enum MagidexImageSource implements CardImageSource {
|
public enum MagidexImageSource implements CardImageSource {
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
|
private final Set<String> supportedSets;
|
||||||
|
|
||||||
|
MagidexImageSource() {
|
||||||
|
supportedSets = new LinkedHashSet<>();
|
||||||
|
// supportedSets.add("PTC"); // Prerelease Events
|
||||||
|
// supportedSets.add("FNMP");
|
||||||
|
supportedSets.add("JR");
|
||||||
|
supportedSets.add("LEA");
|
||||||
|
supportedSets.add("LEB");
|
||||||
|
supportedSets.add("2ED");
|
||||||
|
supportedSets.add("ARN");
|
||||||
|
supportedSets.add("ATQ");
|
||||||
|
supportedSets.add("3ED");
|
||||||
|
supportedSets.add("LEG");
|
||||||
|
supportedSets.add("DRK");
|
||||||
|
supportedSets.add("FEM");
|
||||||
|
supportedSets.add("4ED");
|
||||||
|
supportedSets.add("ICE");
|
||||||
|
supportedSets.add("CHR");
|
||||||
|
supportedSets.add("HML");
|
||||||
|
supportedSets.add("ALL");
|
||||||
|
supportedSets.add("MIR");
|
||||||
|
supportedSets.add("VIS");
|
||||||
|
supportedSets.add("5ED");
|
||||||
|
supportedSets.add("POR");
|
||||||
|
supportedSets.add("WTH");
|
||||||
|
supportedSets.add("TMP");
|
||||||
|
supportedSets.add("STH");
|
||||||
|
supportedSets.add("EXO");
|
||||||
|
supportedSets.add("P02");
|
||||||
|
supportedSets.add("UGL");
|
||||||
|
supportedSets.add("USG");
|
||||||
|
supportedSets.add("DD3DVD");
|
||||||
|
supportedSets.add("DD3EVG");
|
||||||
|
supportedSets.add("DD3GVL");
|
||||||
|
supportedSets.add("DD3JVC");
|
||||||
|
|
||||||
|
supportedSets.add("ULG");
|
||||||
|
supportedSets.add("6ED");
|
||||||
|
supportedSets.add("UDS");
|
||||||
|
supportedSets.add("PTK");
|
||||||
|
supportedSets.add("S99");
|
||||||
|
supportedSets.add("MMQ");
|
||||||
|
// supportedSets.add("BRB");Battle Royale Box Set
|
||||||
|
supportedSets.add("NEM");
|
||||||
|
supportedSets.add("S00");
|
||||||
|
supportedSets.add("PCY");
|
||||||
|
supportedSets.add("INV");
|
||||||
|
// supportedSets.add("BTD"); // Beatdown Boxset
|
||||||
|
supportedSets.add("PLS");
|
||||||
|
supportedSets.add("7ED");
|
||||||
|
supportedSets.add("APC");
|
||||||
|
supportedSets.add("ODY");
|
||||||
|
// supportedSets.add("DKM"); // Deckmasters 2001
|
||||||
|
supportedSets.add("TOR");
|
||||||
|
supportedSets.add("JUD");
|
||||||
|
supportedSets.add("ONS");
|
||||||
|
supportedSets.add("LGN");
|
||||||
|
supportedSets.add("SCG");
|
||||||
|
supportedSets.add("8ED");
|
||||||
|
supportedSets.add("MRD");
|
||||||
|
supportedSets.add("DST");
|
||||||
|
supportedSets.add("5DN");
|
||||||
|
supportedSets.add("CHK");
|
||||||
|
supportedSets.add("UNH");
|
||||||
|
supportedSets.add("BOK");
|
||||||
|
supportedSets.add("SOK");
|
||||||
|
supportedSets.add("9ED");
|
||||||
|
supportedSets.add("RAV");
|
||||||
|
supportedSets.add("GPT");
|
||||||
|
supportedSets.add("DIS");
|
||||||
|
supportedSets.add("CSP");
|
||||||
|
supportedSets.add("TSP");
|
||||||
|
supportedSets.add("TSB");
|
||||||
|
supportedSets.add("PLC");
|
||||||
|
supportedSets.add("FUT");
|
||||||
|
supportedSets.add("10E");
|
||||||
|
supportedSets.add("MED");
|
||||||
|
supportedSets.add("LRW");
|
||||||
|
supportedSets.add("EVG");
|
||||||
|
supportedSets.add("MOR");
|
||||||
|
supportedSets.add("SHM");
|
||||||
|
supportedSets.add("EVE");
|
||||||
|
supportedSets.add("DRB");
|
||||||
|
supportedSets.add("ME2");
|
||||||
|
supportedSets.add("ALA");
|
||||||
|
supportedSets.add("DD2");
|
||||||
|
supportedSets.add("CON");
|
||||||
|
supportedSets.add("DDC");
|
||||||
|
supportedSets.add("ARB");
|
||||||
|
supportedSets.add("M10");
|
||||||
|
// supportedSets.add("TD0"); // Magic Online Deck Series
|
||||||
|
supportedSets.add("V09");
|
||||||
|
supportedSets.add("HOP");
|
||||||
|
supportedSets.add("ME3");
|
||||||
|
supportedSets.add("ZEN");
|
||||||
|
supportedSets.add("DDD");
|
||||||
|
supportedSets.add("H09");
|
||||||
|
supportedSets.add("WWK");
|
||||||
|
supportedSets.add("DDE");
|
||||||
|
supportedSets.add("ROE");
|
||||||
|
supportedSets.add("DPA");
|
||||||
|
supportedSets.add("ARC");
|
||||||
|
supportedSets.add("M11");
|
||||||
|
supportedSets.add("V10");
|
||||||
|
supportedSets.add("DDF");
|
||||||
|
supportedSets.add("SOM");
|
||||||
|
// supportedSets.add("TD0"); // Commander Theme Decks
|
||||||
|
supportedSets.add("PD2");
|
||||||
|
supportedSets.add("ME4");
|
||||||
|
supportedSets.add("MBS");
|
||||||
|
supportedSets.add("DDG");
|
||||||
|
supportedSets.add("NPH");
|
||||||
|
supportedSets.add("CMD");
|
||||||
|
supportedSets.add("M12");
|
||||||
|
supportedSets.add("V11");
|
||||||
|
supportedSets.add("DDH");
|
||||||
|
supportedSets.add("ISD");
|
||||||
|
supportedSets.add("PD3");
|
||||||
|
supportedSets.add("DKA");
|
||||||
|
supportedSets.add("DDI");
|
||||||
|
supportedSets.add("AVR");
|
||||||
|
supportedSets.add("PC2");
|
||||||
|
supportedSets.add("M13");
|
||||||
|
supportedSets.add("V12");
|
||||||
|
supportedSets.add("DDJ");
|
||||||
|
supportedSets.add("RTR");
|
||||||
|
supportedSets.add("CM1");
|
||||||
|
// supportedSets.add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia
|
||||||
|
supportedSets.add("GTC");
|
||||||
|
supportedSets.add("DDK");
|
||||||
|
supportedSets.add("DGM");
|
||||||
|
supportedSets.add("MMA");
|
||||||
|
supportedSets.add("M14");
|
||||||
|
supportedSets.add("V13");
|
||||||
|
supportedSets.add("DDL");
|
||||||
|
supportedSets.add("THS");
|
||||||
|
supportedSets.add("C13");
|
||||||
|
supportedSets.add("BNG");
|
||||||
|
supportedSets.add("DDM");
|
||||||
|
supportedSets.add("JOU");
|
||||||
|
// supportedSets.add("MD1"); // Modern Event Deck
|
||||||
|
supportedSets.add("CNS");
|
||||||
|
supportedSets.add("VMA");
|
||||||
|
supportedSets.add("M15");
|
||||||
|
supportedSets.add("V14");
|
||||||
|
supportedSets.add("DDN");
|
||||||
|
supportedSets.add("KTK");
|
||||||
|
supportedSets.add("C14");
|
||||||
|
// supportedSets.add("DD3"); // Duel Decks Anthology
|
||||||
|
supportedSets.add("FRF");
|
||||||
|
supportedSets.add("DDO");
|
||||||
|
supportedSets.add("DTK");
|
||||||
|
supportedSets.add("TPR");
|
||||||
|
supportedSets.add("MM2");
|
||||||
|
supportedSets.add("ORI");
|
||||||
|
supportedSets.add("V15");
|
||||||
|
supportedSets.add("DDP");
|
||||||
|
supportedSets.add("BFZ");
|
||||||
|
supportedSets.add("EXP");
|
||||||
|
supportedSets.add("C15");
|
||||||
|
// supportedSets.add("PZ1"); // Legendary Cube
|
||||||
|
supportedSets.add("OGW");
|
||||||
|
supportedSets.add("DDQ");
|
||||||
|
supportedSets.add("W16");
|
||||||
|
supportedSets.add("SOI");
|
||||||
|
supportedSets.add("EMA");
|
||||||
|
supportedSets.add("EMN");
|
||||||
|
supportedSets.add("V16");
|
||||||
|
supportedSets.add("CN2");
|
||||||
|
supportedSets.add("DDR");
|
||||||
|
supportedSets.add("KLD");
|
||||||
|
supportedSets.add("MPS");
|
||||||
|
// supportedSets.add("PZ2"); // Treasure Chests
|
||||||
|
supportedSets.add("C16");
|
||||||
|
supportedSets.add("PCA");
|
||||||
|
supportedSets.add("AER");
|
||||||
|
supportedSets.add("MM3");
|
||||||
|
supportedSets.add("DDS");
|
||||||
|
supportedSets.add("W17");
|
||||||
|
supportedSets.add("AKH");
|
||||||
|
supportedSets.add("MPS");
|
||||||
|
supportedSets.add("CMA");
|
||||||
|
supportedSets.add("E01");
|
||||||
|
supportedSets.add("HOU");
|
||||||
|
supportedSets.add("C17");
|
||||||
|
// supportedSets.add("XLN");
|
||||||
|
// supportedSets.add("DDT");
|
||||||
|
// supportedSets.add("IMA");
|
||||||
|
// supportedSets.add("E02");
|
||||||
|
// supportedSets.add("V17");
|
||||||
|
// supportedSets.add("UST");
|
||||||
|
// supportedSets.add("RIX");
|
||||||
|
// supportedSets.add("A25");
|
||||||
|
// supportedSets.add("DOM");
|
||||||
|
// supportedSets.add("M19");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSourceName() {
|
public String getSourceName() {
|
||||||
return "magidex.com";
|
return "magidex.com";
|
||||||
|
@ -68,10 +269,23 @@ public enum MagidexImageSource implements CardImageSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will properly escape the url
|
// This will properly escape the url
|
||||||
URI uri = new URI("http", "magidex.com", "/extstatic/card/" + cardSet + '/' + cardDownloadName + ".jpg", null, null);
|
URI uri = new URI("http", "magidex.com", "/extstatic/card/" + formatSetName(cardSet) + '/' + cardDownloadName + ".jpg", null, null);
|
||||||
return uri.toASCIIString();
|
return uri.toASCIIString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String formatSetName(String setName) {
|
||||||
|
if (setNameReplacement.containsKey(setName)) {
|
||||||
|
setName = setNameReplacement.get(setName);
|
||||||
|
}
|
||||||
|
return setName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Map<String, String> setNameReplacement = new HashMap<String, String>() {
|
||||||
|
{
|
||||||
|
put("JR", "pJGP");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String generateTokenUrl(CardDownloadData card) {
|
public String generateTokenUrl(CardDownloadData card) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -95,4 +309,11 @@ public enum MagidexImageSource implements CardImageSource {
|
||||||
@Override
|
@Override
|
||||||
public void doPause(String httpImageUrl) {
|
public void doPause(String httpImageUrl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> getSupportedSets() {
|
||||||
|
ArrayList<String> supportedSetsCopy = new ArrayList<>();
|
||||||
|
supportedSetsCopy.addAll(supportedSets);
|
||||||
|
return supportedSetsCopy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,10 @@
|
||||||
*/
|
*/
|
||||||
package org.mage.plugins.card.dl.sources;
|
package org.mage.plugins.card.dl.sources;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.mage.plugins.card.images.CardDownloadData;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.mage.plugins.card.images.CardDownloadData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -377,4 +376,10 @@ public enum MtgOnlTokensImageSource implements CardImageSource {
|
||||||
@Override
|
@Override
|
||||||
public void doPause(String httpImageUrl) {
|
public void doPause(String httpImageUrl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isImageProvided(String setCode, String cardName) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,11 @@ import java.net.InetSocketAddress;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.prefs.Preferences;
|
import java.util.prefs.Preferences;
|
||||||
|
@ -57,10 +59,12 @@ import org.mage.plugins.card.images.CardDownloadData;
|
||||||
public enum MythicspoilerComSource implements CardImageSource {
|
public enum MythicspoilerComSource implements CardImageSource {
|
||||||
|
|
||||||
instance;
|
instance;
|
||||||
private Map<String, String> setsAliases;
|
private final Map<String, String> setsAliases;
|
||||||
private Map<String, String> cardNameAliases;
|
private final Map<String, String> cardNameAliases;
|
||||||
private Map<String, Set<String>> cardNameAliasesStart;
|
private final Map<String, Set<String>> cardNameAliasesStart;
|
||||||
private final Map<String, Map<String, String>> sets;
|
private final Map<String, Map<String, String>> sets;
|
||||||
|
private final Set<String> supportedSets;
|
||||||
|
private final Map<String, Map<String, String>> manualLinks;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSourceName() {
|
public String getSourceName() {
|
||||||
|
@ -68,6 +72,188 @@ public enum MythicspoilerComSource implements CardImageSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
MythicspoilerComSource() {
|
MythicspoilerComSource() {
|
||||||
|
supportedSets = new LinkedHashSet<>();
|
||||||
|
// supportedSets.add("LEA");
|
||||||
|
supportedSets.add("LEB");
|
||||||
|
// supportedSets.add("2ED");
|
||||||
|
supportedSets.add("ARN");
|
||||||
|
supportedSets.add("ATQ");
|
||||||
|
supportedSets.add("3ED");
|
||||||
|
supportedSets.add("LEG");
|
||||||
|
supportedSets.add("DRK");
|
||||||
|
supportedSets.add("FEM");
|
||||||
|
// supportedSets.add("4ED");
|
||||||
|
supportedSets.add("ICE");
|
||||||
|
supportedSets.add("CHR");
|
||||||
|
supportedSets.add("HML");
|
||||||
|
supportedSets.add("ALL");
|
||||||
|
supportedSets.add("MIR");
|
||||||
|
supportedSets.add("VIS");
|
||||||
|
// supportedSets.add("5ED");
|
||||||
|
// supportedSets.add("POR");
|
||||||
|
supportedSets.add("WTH");
|
||||||
|
supportedSets.add("TMP");
|
||||||
|
supportedSets.add("STH");
|
||||||
|
supportedSets.add("EXO");
|
||||||
|
// supportedSets.add("P02");
|
||||||
|
// supportedSets.add("UGL");
|
||||||
|
supportedSets.add("USG");
|
||||||
|
// supportedSets.add("DD3DVD");
|
||||||
|
// supportedSets.add("DD3EVG");
|
||||||
|
// supportedSets.add("DD3GVL");
|
||||||
|
// supportedSets.add("DD3JVC");
|
||||||
|
|
||||||
|
// supportedSets.add("ULG");
|
||||||
|
// supportedSets.add("6ED");
|
||||||
|
supportedSets.add("UDS");
|
||||||
|
supportedSets.add("PTK");
|
||||||
|
// supportedSets.add("S99");
|
||||||
|
supportedSets.add("MMQ");
|
||||||
|
// supportedSets.add("BRB");Battle Royale Box Set
|
||||||
|
supportedSets.add("NEM");
|
||||||
|
// supportedSets.add("S00");
|
||||||
|
supportedSets.add("PCY");
|
||||||
|
supportedSets.add("INV");
|
||||||
|
// supportedSets.add("BTD"); // Beatdown Boxset
|
||||||
|
supportedSets.add("PLS");
|
||||||
|
supportedSets.add("7ED");
|
||||||
|
supportedSets.add("APC");
|
||||||
|
supportedSets.add("ODY");
|
||||||
|
// supportedSets.add("DKM"); // Deckmasters 2001
|
||||||
|
supportedSets.add("TOR");
|
||||||
|
supportedSets.add("JUD");
|
||||||
|
supportedSets.add("ONS");
|
||||||
|
supportedSets.add("LGN");
|
||||||
|
supportedSets.add("SCG");
|
||||||
|
supportedSets.add("8ED");
|
||||||
|
supportedSets.add("MRD");
|
||||||
|
supportedSets.add("DST");
|
||||||
|
supportedSets.add("5DN");
|
||||||
|
supportedSets.add("CHK");
|
||||||
|
supportedSets.add("UNH");
|
||||||
|
supportedSets.add("BOK");
|
||||||
|
supportedSets.add("SOK");
|
||||||
|
supportedSets.add("9ED");
|
||||||
|
supportedSets.add("RAV");
|
||||||
|
supportedSets.add("GPT");
|
||||||
|
supportedSets.add("DIS");
|
||||||
|
supportedSets.add("CSP");
|
||||||
|
supportedSets.add("TSP");
|
||||||
|
supportedSets.add("TSB");
|
||||||
|
supportedSets.add("PLC");
|
||||||
|
supportedSets.add("FUT");
|
||||||
|
supportedSets.add("10E");
|
||||||
|
supportedSets.add("MED");
|
||||||
|
supportedSets.add("LRW");
|
||||||
|
supportedSets.add("EVG");
|
||||||
|
supportedSets.add("MOR");
|
||||||
|
supportedSets.add("SHM");
|
||||||
|
supportedSets.add("EVE");
|
||||||
|
supportedSets.add("DRB");
|
||||||
|
// supportedSets.add("ME2");
|
||||||
|
supportedSets.add("ALA");
|
||||||
|
// supportedSets.add("DD2");
|
||||||
|
supportedSets.add("CON");
|
||||||
|
// supportedSets.add("DDC");
|
||||||
|
supportedSets.add("ARB");
|
||||||
|
supportedSets.add("M10");
|
||||||
|
// supportedSets.add("TD0"); // Magic Online Deck Series
|
||||||
|
// supportedSets.add("V09");
|
||||||
|
supportedSets.add("HOP");
|
||||||
|
// supportedSets.add("ME3");
|
||||||
|
supportedSets.add("ZEN");
|
||||||
|
// supportedSets.add("DDD");
|
||||||
|
supportedSets.add("H09");
|
||||||
|
supportedSets.add("WWK");
|
||||||
|
// supportedSets.add("DDE");
|
||||||
|
supportedSets.add("ROE");
|
||||||
|
supportedSets.add("DPA");
|
||||||
|
supportedSets.add("ARC");
|
||||||
|
supportedSets.add("M11");
|
||||||
|
// supportedSets.add("V10");
|
||||||
|
// supportedSets.add("DDF");
|
||||||
|
supportedSets.add("SOM");
|
||||||
|
// supportedSets.add("TD0"); // Commander Theme Decks
|
||||||
|
// supportedSets.add("PD2");
|
||||||
|
// supportedSets.add("ME4");
|
||||||
|
supportedSets.add("MBS");
|
||||||
|
// supportedSets.add("DDG");
|
||||||
|
supportedSets.add("NPH");
|
||||||
|
supportedSets.add("CMD");
|
||||||
|
supportedSets.add("M12");
|
||||||
|
supportedSets.add("V11");
|
||||||
|
// supportedSets.add("DDH");
|
||||||
|
supportedSets.add("ISD");
|
||||||
|
supportedSets.add("PD3");
|
||||||
|
supportedSets.add("DKA");
|
||||||
|
// supportedSets.add("DDI");
|
||||||
|
supportedSets.add("AVR");
|
||||||
|
// supportedSets.add("PC2");
|
||||||
|
supportedSets.add("M13");
|
||||||
|
// supportedSets.add("V12");
|
||||||
|
// supportedSets.add("DDJ");
|
||||||
|
supportedSets.add("RTR");
|
||||||
|
// supportedSets.add("CM1");
|
||||||
|
// supportedSets.add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia
|
||||||
|
supportedSets.add("GTC");
|
||||||
|
// supportedSets.add("DDK");
|
||||||
|
supportedSets.add("DGM");
|
||||||
|
// supportedSets.add("MMA");
|
||||||
|
supportedSets.add("M14");
|
||||||
|
supportedSets.add("V13");
|
||||||
|
// supportedSets.add("DDL");
|
||||||
|
supportedSets.add("THS");
|
||||||
|
supportedSets.add("C13");
|
||||||
|
supportedSets.add("BNG");
|
||||||
|
// supportedSets.add("DDM");
|
||||||
|
supportedSets.add("JOU");
|
||||||
|
// supportedSets.add("MD1"); // Modern Event Deck
|
||||||
|
// supportedSets.add("CNS");
|
||||||
|
// supportedSets.add("VMA");
|
||||||
|
supportedSets.add("M15");
|
||||||
|
supportedSets.add("V14");
|
||||||
|
supportedSets.add("DDN");
|
||||||
|
supportedSets.add("KTK");
|
||||||
|
supportedSets.add("C14");
|
||||||
|
// supportedSets.add("DD3"); // Duel Decks Anthology
|
||||||
|
supportedSets.add("FRF");
|
||||||
|
// supportedSets.add("DDO");
|
||||||
|
// supportedSets.add("DTK");
|
||||||
|
// supportedSets.add("TPR");
|
||||||
|
supportedSets.add("MM2");
|
||||||
|
supportedSets.add("ORI");
|
||||||
|
// supportedSets.add("V15");
|
||||||
|
// supportedSets.add("DDP");
|
||||||
|
supportedSets.add("BFZ");
|
||||||
|
// supportedSets.add("EXP");
|
||||||
|
supportedSets.add("C15");
|
||||||
|
// supportedSets.add("PZ1"); // Legendary Cube
|
||||||
|
supportedSets.add("OGW");
|
||||||
|
// supportedSets.add("DDQ");
|
||||||
|
// supportedSets.add("W16");
|
||||||
|
supportedSets.add("SOI");
|
||||||
|
supportedSets.add("EMA");
|
||||||
|
supportedSets.add("EMN");
|
||||||
|
// supportedSets.add("V16");
|
||||||
|
supportedSets.add("CN2");
|
||||||
|
// supportedSets.add("DDR");
|
||||||
|
supportedSets.add("KLD");
|
||||||
|
// supportedSets.add("MPS");
|
||||||
|
// supportedSets.add("PZ2");
|
||||||
|
supportedSets.add("C16");
|
||||||
|
// supportedSets.add("PCA");
|
||||||
|
supportedSets.add("AER");
|
||||||
|
supportedSets.add("MM3");
|
||||||
|
// supportedSets.add("W17");
|
||||||
|
supportedSets.add("AKH");
|
||||||
|
supportedSets.add("MPS");
|
||||||
|
supportedSets.add("CMA");
|
||||||
|
supportedSets.add("E01");
|
||||||
|
supportedSets.add("HOU");
|
||||||
|
supportedSets.add("C17");
|
||||||
|
supportedSets.add("IMA");
|
||||||
|
supportedSets.add("XLN");
|
||||||
|
|
||||||
sets = new LinkedHashMap<>();
|
sets = new LinkedHashMap<>();
|
||||||
setsAliases = new HashMap<>();
|
setsAliases = new HashMap<>();
|
||||||
setsAliases.put("exp", "bfz");
|
setsAliases.put("exp", "bfz");
|
||||||
|
@ -88,6 +274,25 @@ public enum MythicspoilerComSource implements CardImageSource {
|
||||||
cardNameAliases.put("AKH-reducerumble", "reducerubble");
|
cardNameAliases.put("AKH-reducerumble", "reducerubble");
|
||||||
cardNameAliases.put("AKH-forsakethewordly", "forsaketheworldly");
|
cardNameAliases.put("AKH-forsakethewordly", "forsaketheworldly");
|
||||||
cardNameAliases.put("AKH-kefnatsmonument", "kefnetsmonument");
|
cardNameAliases.put("AKH-kefnatsmonument", "kefnetsmonument");
|
||||||
|
cardNameAliases.put("XLN-kinjaliscaller", "kinjalliscaller");
|
||||||
|
cardNameAliases.put("XLN-lookoutsdecision", "lookoutsdispersal");
|
||||||
|
cardNameAliases.put("XLN-infuriatedgladiodon", "ragingswordtooth");
|
||||||
|
cardNameAliases.put("XLN-redoubledvolley", "repeatingbarrage");
|
||||||
|
|
||||||
|
// <card name, card link>
|
||||||
|
manualLinks = new HashMap<>();
|
||||||
|
HashMap<String, String> links = new HashMap<>();
|
||||||
|
links.put("templeofaclazotz", "templeofaclazotz");
|
||||||
|
links.put("conquerorsfoothold", "conquerorsfoothold");
|
||||||
|
links.put("primalwellspring", "primalwellspring");
|
||||||
|
links.put("azcantathesunkenruin", "azcantathesunkenruin");
|
||||||
|
links.put("spiresoforazca", "spiresoforazca");
|
||||||
|
links.put("treasurecove", "treasurecove");
|
||||||
|
links.put("itlimoccradleofthesun", "itlimoccradleofthesun");
|
||||||
|
links.put("lostvale", "lostvale");
|
||||||
|
links.put("adantothefirstfort", "adantothefirstport");
|
||||||
|
links.put("spitfirebastion", "spitfirebastion");
|
||||||
|
manualLinks.put("XLN", links);
|
||||||
|
|
||||||
cardNameAliasesStart = new HashMap<>();
|
cardNameAliasesStart = new HashMap<>();
|
||||||
HashSet<String> names = new HashSet<>();
|
HashSet<String> names = new HashSet<>();
|
||||||
|
@ -184,7 +389,12 @@ public enum MythicspoilerComSource implements CardImageSource {
|
||||||
pageLinks.put(cardName, baseUrl + cardLink);
|
pageLinks.put(cardName, baseUrl + cardLink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Map<String, String> linksToAdd = manualLinks.get(cardSet);
|
||||||
|
if (linksToAdd != null) {
|
||||||
|
for (Map.Entry<String, String> link : linksToAdd.entrySet()) {
|
||||||
|
pageLinks.put(link.getKey(), baseUrl + "cards/" + link.getValue() + ".jpg");
|
||||||
|
}
|
||||||
|
}
|
||||||
return pageLinks;
|
return pageLinks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,4 +453,12 @@ public enum MythicspoilerComSource implements CardImageSource {
|
||||||
@Override
|
@Override
|
||||||
public void doPause(String httpImageUrl) {
|
public void doPause(String httpImageUrl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> getSupportedSets() {
|
||||||
|
ArrayList<String> supportedSetsCopy = new ArrayList<>();
|
||||||
|
supportedSetsCopy.addAll(supportedSets);
|
||||||
|
return supportedSetsCopy;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package org.mage.plugins.card.dl.sources;
|
package org.mage.plugins.card.dl.sources;
|
||||||
|
|
||||||
import org.mage.plugins.card.images.CardDownloadData;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.mage.plugins.card.images.CardDownloadData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Quercitron
|
* @author Quercitron
|
||||||
|
@ -13,9 +15,209 @@ public enum ScryfallImageSource implements CardImageSource {
|
||||||
|
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
|
private final Set<String> supportedSets;
|
||||||
|
|
||||||
|
ScryfallImageSource() {
|
||||||
|
supportedSets = new LinkedHashSet<>();
|
||||||
|
// supportedSets.add("PTC"); //
|
||||||
|
supportedSets.add("LEA");
|
||||||
|
supportedSets.add("LEB");
|
||||||
|
supportedSets.add("2ED");
|
||||||
|
supportedSets.add("ARN");
|
||||||
|
supportedSets.add("ATQ");
|
||||||
|
supportedSets.add("3ED");
|
||||||
|
supportedSets.add("LEG");
|
||||||
|
supportedSets.add("DRK");
|
||||||
|
supportedSets.add("FEM");
|
||||||
|
supportedSets.add("4ED");
|
||||||
|
supportedSets.add("ICE");
|
||||||
|
supportedSets.add("CHR");
|
||||||
|
supportedSets.add("HML");
|
||||||
|
supportedSets.add("ALL");
|
||||||
|
supportedSets.add("MIR");
|
||||||
|
supportedSets.add("VIS");
|
||||||
|
supportedSets.add("5ED");
|
||||||
|
supportedSets.add("POR");
|
||||||
|
supportedSets.add("WTH");
|
||||||
|
supportedSets.add("TMP");
|
||||||
|
supportedSets.add("STH");
|
||||||
|
supportedSets.add("EXO");
|
||||||
|
supportedSets.add("P02");
|
||||||
|
supportedSets.add("UGL");
|
||||||
|
supportedSets.add("USG");
|
||||||
|
supportedSets.add("DD3DVD");
|
||||||
|
supportedSets.add("DD3EVG");
|
||||||
|
supportedSets.add("DD3GVL");
|
||||||
|
supportedSets.add("DD3JVC");
|
||||||
|
|
||||||
|
supportedSets.add("ULG");
|
||||||
|
supportedSets.add("6ED");
|
||||||
|
supportedSets.add("UDS");
|
||||||
|
supportedSets.add("PTK");
|
||||||
|
supportedSets.add("S99");
|
||||||
|
supportedSets.add("MMQ");
|
||||||
|
// supportedSets.add("BRB");Battle Royale Box Set
|
||||||
|
supportedSets.add("NEM");
|
||||||
|
supportedSets.add("S00");
|
||||||
|
supportedSets.add("PCY");
|
||||||
|
supportedSets.add("INV");
|
||||||
|
// supportedSets.add("BTD"); // Beatdown Boxset
|
||||||
|
supportedSets.add("PLS");
|
||||||
|
supportedSets.add("7ED");
|
||||||
|
supportedSets.add("APC");
|
||||||
|
supportedSets.add("ODY");
|
||||||
|
// supportedSets.add("DKM"); // Deckmasters 2001
|
||||||
|
supportedSets.add("TOR");
|
||||||
|
supportedSets.add("JUD");
|
||||||
|
supportedSets.add("ONS");
|
||||||
|
supportedSets.add("LGN");
|
||||||
|
supportedSets.add("SCG");
|
||||||
|
supportedSets.add("8ED");
|
||||||
|
supportedSets.add("MRD");
|
||||||
|
supportedSets.add("DST");
|
||||||
|
supportedSets.add("5DN");
|
||||||
|
supportedSets.add("CHK");
|
||||||
|
supportedSets.add("UNH");
|
||||||
|
supportedSets.add("BOK");
|
||||||
|
supportedSets.add("SOK");
|
||||||
|
supportedSets.add("9ED");
|
||||||
|
supportedSets.add("RAV");
|
||||||
|
supportedSets.add("GPT");
|
||||||
|
supportedSets.add("DIS");
|
||||||
|
supportedSets.add("CSP");
|
||||||
|
supportedSets.add("TSP");
|
||||||
|
supportedSets.add("TSB");
|
||||||
|
supportedSets.add("PLC");
|
||||||
|
supportedSets.add("FUT");
|
||||||
|
supportedSets.add("10E");
|
||||||
|
supportedSets.add("MED");
|
||||||
|
supportedSets.add("LRW");
|
||||||
|
supportedSets.add("EVG");
|
||||||
|
supportedSets.add("MOR");
|
||||||
|
supportedSets.add("SHM");
|
||||||
|
supportedSets.add("EVE");
|
||||||
|
supportedSets.add("DRB");
|
||||||
|
supportedSets.add("ME2");
|
||||||
|
supportedSets.add("ALA");
|
||||||
|
supportedSets.add("DD2");
|
||||||
|
supportedSets.add("CON");
|
||||||
|
supportedSets.add("DDC");
|
||||||
|
supportedSets.add("ARB");
|
||||||
|
supportedSets.add("M10");
|
||||||
|
// supportedSets.add("TD0"); // Magic Online Deck Series
|
||||||
|
supportedSets.add("V09");
|
||||||
|
supportedSets.add("HOP");
|
||||||
|
supportedSets.add("ME3");
|
||||||
|
supportedSets.add("ZEN");
|
||||||
|
supportedSets.add("DDD");
|
||||||
|
supportedSets.add("H09");
|
||||||
|
supportedSets.add("WWK");
|
||||||
|
supportedSets.add("DDE");
|
||||||
|
supportedSets.add("ROE");
|
||||||
|
supportedSets.add("DPA");
|
||||||
|
supportedSets.add("ARC");
|
||||||
|
supportedSets.add("M11");
|
||||||
|
supportedSets.add("V10");
|
||||||
|
supportedSets.add("DDF");
|
||||||
|
supportedSets.add("SOM");
|
||||||
|
// supportedSets.add("TD0"); // Commander Theme Decks
|
||||||
|
supportedSets.add("PD2");
|
||||||
|
supportedSets.add("ME4");
|
||||||
|
supportedSets.add("MBS");
|
||||||
|
supportedSets.add("DDG");
|
||||||
|
supportedSets.add("NPH");
|
||||||
|
supportedSets.add("CMD");
|
||||||
|
supportedSets.add("M12");
|
||||||
|
supportedSets.add("V11");
|
||||||
|
supportedSets.add("DDH");
|
||||||
|
supportedSets.add("ISD");
|
||||||
|
supportedSets.add("PD3");
|
||||||
|
supportedSets.add("DKA");
|
||||||
|
supportedSets.add("DDI");
|
||||||
|
supportedSets.add("AVR");
|
||||||
|
supportedSets.add("PC2");
|
||||||
|
supportedSets.add("M13");
|
||||||
|
supportedSets.add("V12");
|
||||||
|
supportedSets.add("DDJ");
|
||||||
|
supportedSets.add("RTR");
|
||||||
|
supportedSets.add("CM1");
|
||||||
|
// supportedSets.add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia
|
||||||
|
supportedSets.add("GTC");
|
||||||
|
supportedSets.add("DDK");
|
||||||
|
supportedSets.add("DGM");
|
||||||
|
supportedSets.add("MMA");
|
||||||
|
supportedSets.add("M14");
|
||||||
|
supportedSets.add("V13");
|
||||||
|
supportedSets.add("DDL");
|
||||||
|
supportedSets.add("THS");
|
||||||
|
supportedSets.add("C13");
|
||||||
|
supportedSets.add("BNG");
|
||||||
|
supportedSets.add("DDM");
|
||||||
|
supportedSets.add("JOU");
|
||||||
|
// supportedSets.add("MD1"); // Modern Event Deck
|
||||||
|
supportedSets.add("CNS");
|
||||||
|
supportedSets.add("VMA");
|
||||||
|
supportedSets.add("M15");
|
||||||
|
supportedSets.add("V14");
|
||||||
|
supportedSets.add("DDN");
|
||||||
|
supportedSets.add("KTK");
|
||||||
|
supportedSets.add("C14");
|
||||||
|
// supportedSets.add("DD3"); // Duel Decks Anthology
|
||||||
|
supportedSets.add("FRF");
|
||||||
|
supportedSets.add("DDO");
|
||||||
|
supportedSets.add("DTK");
|
||||||
|
supportedSets.add("TPR");
|
||||||
|
supportedSets.add("MM2");
|
||||||
|
supportedSets.add("ORI");
|
||||||
|
supportedSets.add("V15");
|
||||||
|
supportedSets.add("DDP");
|
||||||
|
supportedSets.add("BFZ");
|
||||||
|
supportedSets.add("EXP");
|
||||||
|
supportedSets.add("C15");
|
||||||
|
// supportedSets.add("PZ1"); // Legendary Cube
|
||||||
|
supportedSets.add("OGW");
|
||||||
|
supportedSets.add("DDQ");
|
||||||
|
supportedSets.add("W16");
|
||||||
|
supportedSets.add("SOI");
|
||||||
|
supportedSets.add("EMA");
|
||||||
|
supportedSets.add("EMN");
|
||||||
|
supportedSets.add("V16");
|
||||||
|
supportedSets.add("CN2");
|
||||||
|
supportedSets.add("DDR");
|
||||||
|
supportedSets.add("KLD");
|
||||||
|
supportedSets.add("MPS");
|
||||||
|
// supportedSets.add("PZ2");
|
||||||
|
supportedSets.add("C16");
|
||||||
|
supportedSets.add("PCA");
|
||||||
|
supportedSets.add("AER");
|
||||||
|
supportedSets.add("MM3");
|
||||||
|
supportedSets.add("DDS");
|
||||||
|
supportedSets.add("W17");
|
||||||
|
supportedSets.add("AKH");
|
||||||
|
supportedSets.add("MPS");
|
||||||
|
supportedSets.add("CMA");
|
||||||
|
supportedSets.add("E01");
|
||||||
|
supportedSets.add("HOU");
|
||||||
|
supportedSets.add("C17");
|
||||||
|
supportedSets.add("XLN");
|
||||||
|
// supportedSets.add("DDT");
|
||||||
|
supportedSets.add("IMA");
|
||||||
|
// supportedSets.add("E02");
|
||||||
|
// supportedSets.add("V17");
|
||||||
|
// supportedSets.add("UST");
|
||||||
|
// supportedSets.add("RIX");
|
||||||
|
// supportedSets.add("A25");
|
||||||
|
// supportedSets.add("DOM");
|
||||||
|
// supportedSets.add("M19");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String generateURL(CardDownloadData card) throws Exception {
|
public String generateURL(CardDownloadData card) throws Exception {
|
||||||
return "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/" + card.getCollectorId() + "?format=image";
|
return "https://api.scryfall.com/cards/" + formatSetName(card.getSet()) + "/"
|
||||||
|
+ card.getCollectorId()
|
||||||
|
+ (card.isSecondSide() ? "b" : "")
|
||||||
|
+ "?format=image";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -40,7 +242,7 @@ public enum ScryfallImageSource implements CardImageSource {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getAverageSize() {
|
public float getAverageSize() {
|
||||||
return 240;
|
return 90;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -75,4 +277,11 @@ public enum ScryfallImageSource implements CardImageSource {
|
||||||
put("MBP", "pmei");
|
put("MBP", "pmei");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> getSupportedSets() {
|
||||||
|
ArrayList<String> supportedSetsCopy = new ArrayList<>();
|
||||||
|
supportedSetsCopy.addAll(supportedSets);
|
||||||
|
return supportedSetsCopy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,6 @@
|
||||||
*/
|
*/
|
||||||
package org.mage.plugins.card.dl.sources;
|
package org.mage.plugins.card.dl.sources;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.mage.plugins.card.images.CardDownloadData;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -37,8 +34,14 @@ import java.io.InputStreamReader;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.mage.plugins.card.images.CardDownloadData;
|
||||||
|
import org.mage.plugins.card.images.DownloadPictures;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -49,8 +52,9 @@ public enum TokensMtgImageSource implements CardImageSource {
|
||||||
instance;
|
instance;
|
||||||
private static final Logger logger = Logger.getLogger(TokensMtgImageSource.class);
|
private static final Logger logger = Logger.getLogger(TokensMtgImageSource.class);
|
||||||
|
|
||||||
|
// [[EXP/Name, TokenData>
|
||||||
private List<TokenData> tokensData;
|
private HashMap<String, ArrayList<TokenData>> tokensData;
|
||||||
|
private static final Set<String> supportedSets = new LinkedHashSet<String>();
|
||||||
|
|
||||||
private final Object tokensDataSync = new Object();
|
private final Object tokensDataSync = new Object();
|
||||||
|
|
||||||
|
@ -100,7 +104,12 @@ public enum TokensMtgImageSource implements CardImageSource {
|
||||||
"Sorin",
|
"Sorin",
|
||||||
"Tamiyo",
|
"Tamiyo",
|
||||||
"Teferi",
|
"Teferi",
|
||||||
"Venser",};
|
"Venser",
|
||||||
|
// Custom Emblems
|
||||||
|
"Yoda",
|
||||||
|
"Obi-Wan Kenobi",
|
||||||
|
"Aurra Sing"
|
||||||
|
};
|
||||||
|
|
||||||
private static final Map<String, String> SET_NAMES_REPLACEMENT = new HashMap<String, String>() {
|
private static final Map<String, String> SET_NAMES_REPLACEMENT = new HashMap<String, String>() {
|
||||||
{
|
{
|
||||||
|
@ -134,36 +143,31 @@ public enum TokensMtgImageSource implements CardImageSource {
|
||||||
// e.g. http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg -- token number 010
|
// e.g. http://tokens.mtg.onl/tokens/ORI_010-Thopter.jpg -- token number 010
|
||||||
// We don't know these numbers, but we can take them from a file
|
// We don't know these numbers, but we can take them from a file
|
||||||
// with tokens information that can be downloaded from the site.
|
// with tokens information that can be downloaded from the site.
|
||||||
List<TokenData> newTokensData = getTokensData();
|
if (tokensData.isEmpty()) {
|
||||||
|
logger.info("Source " + getSourceName() + " provides no token data.");
|
||||||
if (newTokensData.isEmpty()) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TokenData> matchedTokens = new ArrayList<>();
|
String key = set + "/" + name;
|
||||||
for (TokenData token : newTokensData) {
|
List<TokenData> list = tokensData.get(key);
|
||||||
if (name.equalsIgnoreCase(token.getName()) && set.equalsIgnoreCase(token.getExpansionSetCode())) {
|
if (list == null) {
|
||||||
matchedTokens.add(token);
|
logger.info("Could not find data for token " + name + ", set " + set + ".");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
//
|
|
||||||
// if (matchedTokens.isEmpty()) {
|
|
||||||
// logger.info("Could not find data for token " + name + ", set " + set + ".");
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
TokenData tokenData;
|
TokenData tokenData;
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
if (matchedTokens.size() > 1) {
|
if (list.size() > 1) {
|
||||||
logger.info("Multiple images were found for token " + name + ", set " + set + '.');
|
logger.info("Multiple images were found for token " + name + ", set " + set + '.');
|
||||||
}
|
}
|
||||||
tokenData = matchedTokens.get(0);
|
logger.info("Token found: " + name + ", set " + set + '.');
|
||||||
|
tokenData = list.get(0);
|
||||||
} else {
|
} else {
|
||||||
if (type > matchedTokens.size()) {
|
if (type > list.size()) {
|
||||||
logger.warn("Not enough images for token with type " + type + ", name " + name + ", set " + set + '.');
|
logger.warn("Not enough images for token with type " + type + ", name " + name + ", set " + set + '.');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
tokenData = matchedTokens.get(card.getType() - 1);
|
tokenData = list.get(card.getType() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
String url = "http://tokens.mtg.onl/tokens/" + tokenData.getExpansionSetCode().trim() + '_'
|
String url = "http://tokens.mtg.onl/tokens/" + tokenData.getExpansionSetCode().trim() + '_'
|
||||||
|
@ -172,15 +176,26 @@ public enum TokensMtgImageSource implements CardImageSource {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TokenData> getTokensData() throws IOException {
|
private HashMap<String, ArrayList<TokenData>> getTokensData() throws IOException {
|
||||||
synchronized (tokensDataSync) {
|
synchronized (tokensDataSync) {
|
||||||
if (tokensData == null) {
|
if (tokensData == null) {
|
||||||
tokensData = new ArrayList<>();
|
DownloadPictures.getInstance().updateAndViewMessage("Creating token data...");
|
||||||
|
tokensData = new HashMap<>();
|
||||||
|
|
||||||
// get tokens data from resource file
|
// get tokens data from resource file
|
||||||
try(InputStream inputStream = this.getClass().getResourceAsStream("/tokens-mtg-onl-list.csv")) {
|
try (InputStream inputStream = this.getClass().getResourceAsStream("/tokens-mtg-onl-list.csv")) {
|
||||||
List<TokenData> fileTokensData = parseTokensData(inputStream);
|
List<TokenData> fileTokensData = parseTokensData(inputStream);
|
||||||
tokensData.addAll(fileTokensData);
|
for (TokenData tokenData : fileTokensData) {
|
||||||
|
String key = tokenData.getExpansionSetCode() + "/" + tokenData.getName();
|
||||||
|
ArrayList<TokenData> list = tokensData.get(key);
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList<>();
|
||||||
|
tokensData.put(key, list);
|
||||||
|
supportedSets.add(tokenData.getExpansionSetCode());
|
||||||
|
logger.info("Added key: " + key);
|
||||||
|
}
|
||||||
|
list.add(tokenData);
|
||||||
|
}
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
logger.warn("Failed to get tokens description from resource file tokens-mtg-onl-list.csv", exception);
|
logger.warn("Failed to get tokens description from resource file tokens-mtg-onl-list.csv", exception);
|
||||||
}
|
}
|
||||||
|
@ -188,27 +203,33 @@ public enum TokensMtgImageSource implements CardImageSource {
|
||||||
// description on site may contain new information
|
// description on site may contain new information
|
||||||
// try to add it
|
// try to add it
|
||||||
URL url = new URL("http://tokens.mtg.onl/data/SetsWithTokens.csv");
|
URL url = new URL("http://tokens.mtg.onl/data/SetsWithTokens.csv");
|
||||||
try(InputStream inputStream = url.openStream()) {
|
try (InputStream inputStream = url.openStream()) {
|
||||||
List<TokenData> siteTokensData = parseTokensData(inputStream);
|
List<TokenData> siteTokensData = parseTokensData(inputStream);
|
||||||
List<TokenData> newTokensData = new ArrayList<>();
|
|
||||||
for (TokenData siteData : siteTokensData) {
|
for (TokenData siteData : siteTokensData) {
|
||||||
boolean isNew = true;
|
String key = siteData.getExpansionSetCode() + "/" + siteData.getName();
|
||||||
for (TokenData fileData : tokensData) {
|
supportedSets.add(siteData.getExpansionSetCode());
|
||||||
if (siteData.getName().equalsIgnoreCase(fileData.getName())
|
ArrayList<TokenData> list = tokensData.get(key);
|
||||||
&& siteData.getNumber().equalsIgnoreCase(fileData.getNumber())
|
if (list == null) {
|
||||||
&& siteData.getExpansionSetCode().equalsIgnoreCase(fileData.getExpansionSetCode())) {
|
list = new ArrayList<>();
|
||||||
isNew = false;
|
tokensData.put(key, list);
|
||||||
|
list.add(siteData);
|
||||||
|
} else {
|
||||||
|
boolean newToken = true;
|
||||||
|
for (TokenData tokenData : list) {
|
||||||
|
if (siteData.getNumber().equals(tokenData.number)) {
|
||||||
|
newToken = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isNew) {
|
if (newToken) {
|
||||||
newTokensData.add(siteData);
|
list.add(siteData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tokensData.addAll(newTokensData);
|
DownloadPictures.getInstance().updateAndViewMessage("");
|
||||||
} catch (Exception exception) {
|
} catch (Exception ex) {
|
||||||
logger.warn("Failed to get tokens description from tokens.mtg.onl", exception);
|
logger.warn("Failed to get tokens description from tokens.mtg.onl", ex);
|
||||||
|
DownloadPictures.getInstance().updateAndViewMessage(ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,7 +240,7 @@ public enum TokensMtgImageSource implements CardImageSource {
|
||||||
private List<TokenData> parseTokensData(InputStream inputStream) throws IOException {
|
private List<TokenData> parseTokensData(InputStream inputStream) throws IOException {
|
||||||
List<TokenData> newTokensData = new ArrayList<>();
|
List<TokenData> newTokensData = new ArrayList<>();
|
||||||
|
|
||||||
try(InputStreamReader inputReader = new InputStreamReader(inputStream, "Cp1252");
|
try (InputStreamReader inputReader = new InputStreamReader(inputStream, "Cp1252");
|
||||||
BufferedReader reader = new BufferedReader(inputReader)) {
|
BufferedReader reader = new BufferedReader(inputReader)) {
|
||||||
// we have to specify encoding to read special comma
|
// we have to specify encoding to read special comma
|
||||||
|
|
||||||
|
@ -285,7 +306,17 @@ public enum TokensMtgImageSource implements CardImageSource {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTotalImages() {
|
public int getTotalImages() {
|
||||||
return -1;
|
return getTokenImages();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTokenImages() {
|
||||||
|
try {
|
||||||
|
getTokensData();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.error(getSourceName() + ": Loading available data failed. " + ex.getMessage());
|
||||||
|
}
|
||||||
|
return tokensData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -296,4 +327,28 @@ public enum TokensMtgImageSource implements CardImageSource {
|
||||||
@Override
|
@Override
|
||||||
public void doPause(String httpImageUrl) {
|
public void doPause(String httpImageUrl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> getSupportedSets() {
|
||||||
|
ArrayList<String> supportedSetsCopy = new ArrayList<>();
|
||||||
|
supportedSetsCopy.addAll(supportedSets);
|
||||||
|
return supportedSetsCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isImageProvided(String setCode, String cardName) {
|
||||||
|
try {
|
||||||
|
getTokensData();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
java.util.logging.Logger.getLogger(TokensMtgImageSource.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
String key = setCode + "/" + cardName;
|
||||||
|
return (tokensData.containsKey(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSetSupportedComplete(String setCode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,13 @@ import java.net.HttpURLConnection;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLEncoder;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -46,6 +49,7 @@ import mage.client.MageFrame;
|
||||||
import mage.client.dialog.PreferencesDialog;
|
import mage.client.dialog.PreferencesDialog;
|
||||||
import mage.remote.Connection;
|
import mage.remote.Connection;
|
||||||
import mage.remote.Connection.ProxyType;
|
import mage.remote.Connection.ProxyType;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.jsoup.nodes.Element;
|
import org.jsoup.nodes.Element;
|
||||||
|
@ -58,10 +62,13 @@ import org.mage.plugins.card.images.CardDownloadData;
|
||||||
public enum WizardCardsImageSource implements CardImageSource {
|
public enum WizardCardsImageSource implements CardImageSource {
|
||||||
|
|
||||||
instance;
|
instance;
|
||||||
private Map<String, String> setsAliases;
|
|
||||||
private Map<String, String> languageAliases;
|
|
||||||
private final Map<String, Map<String, String>> sets;
|
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(WizardCardsImageSource.class);
|
||||||
|
|
||||||
|
private final Map<String, String> setsAliases;
|
||||||
|
private final Map<String, String> languageAliases;
|
||||||
|
private final Map<String, Map<String, String>> sets;
|
||||||
|
private final Set<String> supportedSets;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSourceName() {
|
public String getSourceName() {
|
||||||
|
@ -69,6 +76,198 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
WizardCardsImageSource() {
|
WizardCardsImageSource() {
|
||||||
|
supportedSets = new LinkedHashSet<>();
|
||||||
|
// supportedSets.add("PTC"); // Prerelease Events
|
||||||
|
supportedSets.add("LEA");
|
||||||
|
supportedSets.add("LEB");
|
||||||
|
supportedSets.add("2ED");
|
||||||
|
supportedSets.add("ARN");
|
||||||
|
supportedSets.add("ATQ");
|
||||||
|
supportedSets.add("3ED");
|
||||||
|
supportedSets.add("LEG");
|
||||||
|
supportedSets.add("DRK");
|
||||||
|
supportedSets.add("FEM");
|
||||||
|
supportedSets.add("4ED");
|
||||||
|
supportedSets.add("ICE");
|
||||||
|
supportedSets.add("CHR");
|
||||||
|
supportedSets.add("HML");
|
||||||
|
supportedSets.add("ALL");
|
||||||
|
supportedSets.add("MIR");
|
||||||
|
supportedSets.add("VIS");
|
||||||
|
supportedSets.add("5ED");
|
||||||
|
supportedSets.add("POR");
|
||||||
|
supportedSets.add("WTH");
|
||||||
|
supportedSets.add("TMP");
|
||||||
|
supportedSets.add("STH");
|
||||||
|
supportedSets.add("EXO");
|
||||||
|
supportedSets.add("P02");
|
||||||
|
supportedSets.add("UGL");
|
||||||
|
supportedSets.add("USG");
|
||||||
|
supportedSets.add("DD3DVD");
|
||||||
|
supportedSets.add("DD3EVG");
|
||||||
|
supportedSets.add("DD3GVL");
|
||||||
|
supportedSets.add("DD3JVC");
|
||||||
|
|
||||||
|
supportedSets.add("ULG");
|
||||||
|
supportedSets.add("6ED");
|
||||||
|
supportedSets.add("UDS");
|
||||||
|
supportedSets.add("PTK");
|
||||||
|
supportedSets.add("S99");
|
||||||
|
supportedSets.add("MMQ");
|
||||||
|
// supportedSets.add("BRB");Battle Royale Box Set
|
||||||
|
supportedSets.add("NEM");
|
||||||
|
supportedSets.add("S00");
|
||||||
|
supportedSets.add("PCY");
|
||||||
|
supportedSets.add("INV");
|
||||||
|
// supportedSets.add("BTD"); // Beatdown Boxset
|
||||||
|
supportedSets.add("PLS");
|
||||||
|
supportedSets.add("7ED");
|
||||||
|
supportedSets.add("APC");
|
||||||
|
supportedSets.add("ODY");
|
||||||
|
// supportedSets.add("DKM"); // Deckmasters 2001
|
||||||
|
supportedSets.add("TOR");
|
||||||
|
supportedSets.add("JUD");
|
||||||
|
supportedSets.add("ONS");
|
||||||
|
supportedSets.add("LGN");
|
||||||
|
supportedSets.add("SCG");
|
||||||
|
supportedSets.add("8ED");
|
||||||
|
supportedSets.add("MRD");
|
||||||
|
supportedSets.add("DST");
|
||||||
|
supportedSets.add("5DN");
|
||||||
|
supportedSets.add("CHK");
|
||||||
|
supportedSets.add("UNH");
|
||||||
|
supportedSets.add("BOK");
|
||||||
|
supportedSets.add("SOK");
|
||||||
|
supportedSets.add("9ED");
|
||||||
|
supportedSets.add("RAV");
|
||||||
|
supportedSets.add("GPT");
|
||||||
|
supportedSets.add("DIS");
|
||||||
|
supportedSets.add("CSP");
|
||||||
|
supportedSets.add("TSP");
|
||||||
|
supportedSets.add("TSB");
|
||||||
|
supportedSets.add("PLC");
|
||||||
|
supportedSets.add("FUT");
|
||||||
|
supportedSets.add("10E");
|
||||||
|
supportedSets.add("MED");
|
||||||
|
supportedSets.add("LRW");
|
||||||
|
supportedSets.add("EVG");
|
||||||
|
supportedSets.add("MOR");
|
||||||
|
supportedSets.add("SHM");
|
||||||
|
supportedSets.add("EVE");
|
||||||
|
supportedSets.add("DRB");
|
||||||
|
supportedSets.add("ME2");
|
||||||
|
supportedSets.add("ALA");
|
||||||
|
supportedSets.add("DD2");
|
||||||
|
supportedSets.add("CON");
|
||||||
|
supportedSets.add("DDC");
|
||||||
|
supportedSets.add("ARB");
|
||||||
|
supportedSets.add("M10");
|
||||||
|
// supportedSets.add("TD0"); // Magic Online Deck Series
|
||||||
|
supportedSets.add("V09");
|
||||||
|
supportedSets.add("HOP");
|
||||||
|
supportedSets.add("ME3");
|
||||||
|
supportedSets.add("ZEN");
|
||||||
|
supportedSets.add("DDD");
|
||||||
|
supportedSets.add("H09");
|
||||||
|
supportedSets.add("WWK");
|
||||||
|
supportedSets.add("DDE");
|
||||||
|
supportedSets.add("ROE");
|
||||||
|
supportedSets.add("DPA");
|
||||||
|
supportedSets.add("ARC");
|
||||||
|
supportedSets.add("M11");
|
||||||
|
supportedSets.add("V10");
|
||||||
|
supportedSets.add("DDF");
|
||||||
|
supportedSets.add("SOM");
|
||||||
|
// supportedSets.add("TD0"); // Commander Theme Decks
|
||||||
|
supportedSets.add("PD2");
|
||||||
|
supportedSets.add("ME4");
|
||||||
|
supportedSets.add("MBS");
|
||||||
|
supportedSets.add("DDG");
|
||||||
|
supportedSets.add("NPH");
|
||||||
|
supportedSets.add("CMD");
|
||||||
|
supportedSets.add("M12");
|
||||||
|
supportedSets.add("V11");
|
||||||
|
supportedSets.add("DDH");
|
||||||
|
supportedSets.add("ISD");
|
||||||
|
supportedSets.add("PD3");
|
||||||
|
supportedSets.add("DKA");
|
||||||
|
supportedSets.add("DDI");
|
||||||
|
supportedSets.add("AVR");
|
||||||
|
supportedSets.add("PC2");
|
||||||
|
supportedSets.add("M13");
|
||||||
|
supportedSets.add("V12");
|
||||||
|
supportedSets.add("DDJ");
|
||||||
|
supportedSets.add("RTR");
|
||||||
|
supportedSets.add("CM1");
|
||||||
|
// supportedSets.add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia
|
||||||
|
supportedSets.add("GTC");
|
||||||
|
supportedSets.add("DDK");
|
||||||
|
supportedSets.add("DGM");
|
||||||
|
supportedSets.add("MMA");
|
||||||
|
supportedSets.add("M14");
|
||||||
|
supportedSets.add("V13");
|
||||||
|
supportedSets.add("DDL");
|
||||||
|
supportedSets.add("THS");
|
||||||
|
supportedSets.add("C13");
|
||||||
|
supportedSets.add("BNG");
|
||||||
|
supportedSets.add("DDM");
|
||||||
|
supportedSets.add("JOU");
|
||||||
|
// supportedSets.add("MD1"); // Modern Event Deck
|
||||||
|
supportedSets.add("CNS");
|
||||||
|
supportedSets.add("VMA");
|
||||||
|
supportedSets.add("M15");
|
||||||
|
supportedSets.add("V14");
|
||||||
|
supportedSets.add("DDN");
|
||||||
|
supportedSets.add("KTK");
|
||||||
|
supportedSets.add("C14");
|
||||||
|
// supportedSets.add("DD3"); // Duel Decks Anthology
|
||||||
|
supportedSets.add("FRF");
|
||||||
|
supportedSets.add("DDO");
|
||||||
|
supportedSets.add("DTK");
|
||||||
|
supportedSets.add("TPR");
|
||||||
|
supportedSets.add("MM2");
|
||||||
|
supportedSets.add("ORI");
|
||||||
|
supportedSets.add("V15");
|
||||||
|
supportedSets.add("DDP");
|
||||||
|
supportedSets.add("BFZ");
|
||||||
|
supportedSets.add("EXP");
|
||||||
|
supportedSets.add("C15");
|
||||||
|
// supportedSets.add("PZ1"); // Legendary Cube
|
||||||
|
supportedSets.add("OGW");
|
||||||
|
supportedSets.add("DDQ");
|
||||||
|
supportedSets.add("W16");
|
||||||
|
supportedSets.add("SOI");
|
||||||
|
supportedSets.add("EMA");
|
||||||
|
supportedSets.add("EMN");
|
||||||
|
supportedSets.add("V16");
|
||||||
|
supportedSets.add("CN2");
|
||||||
|
supportedSets.add("DDR");
|
||||||
|
supportedSets.add("KLD");
|
||||||
|
supportedSets.add("MPS");
|
||||||
|
// supportedSets.add("PZ2"); // Treasure Chests
|
||||||
|
supportedSets.add("C16");
|
||||||
|
supportedSets.add("PCA");
|
||||||
|
supportedSets.add("AER");
|
||||||
|
supportedSets.add("MM3");
|
||||||
|
supportedSets.add("DDS");
|
||||||
|
supportedSets.add("W17");
|
||||||
|
supportedSets.add("AKH");
|
||||||
|
supportedSets.add("MPS");
|
||||||
|
supportedSets.add("CMA");
|
||||||
|
supportedSets.add("E01");
|
||||||
|
supportedSets.add("HOU");
|
||||||
|
supportedSets.add("C17");
|
||||||
|
// supportedSets.add("XLN");
|
||||||
|
// supportedSets.add("DDT");
|
||||||
|
// supportedSets.add("IMA");
|
||||||
|
// supportedSets.add("E02");
|
||||||
|
// supportedSets.add("V17");
|
||||||
|
// supportedSets.add("UST");
|
||||||
|
// supportedSets.add("RIX");
|
||||||
|
// supportedSets.add("A25");
|
||||||
|
// supportedSets.add("DOM");
|
||||||
|
// supportedSets.add("M19");
|
||||||
|
|
||||||
sets = new HashMap<>();
|
sets = new HashMap<>();
|
||||||
setsAliases = new HashMap<>();
|
setsAliases = new HashMap<>();
|
||||||
setsAliases.put("2ED", "Unlimited Edition");
|
setsAliases.put("2ED", "Unlimited Edition");
|
||||||
|
@ -102,6 +301,7 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
setsAliases.put("C14", "Commander 2014");
|
setsAliases.put("C14", "Commander 2014");
|
||||||
setsAliases.put("C15", "Commander 2015");
|
setsAliases.put("C15", "Commander 2015");
|
||||||
setsAliases.put("C16", "Commander 2016");
|
setsAliases.put("C16", "Commander 2016");
|
||||||
|
setsAliases.put("C17", "Commander 2017");
|
||||||
setsAliases.put("CMA", "Commander Anthology");
|
setsAliases.put("CMA", "Commander Anthology");
|
||||||
setsAliases.put("CHK", "Champions of Kamigawa");
|
setsAliases.put("CHK", "Champions of Kamigawa");
|
||||||
setsAliases.put("CHR", "Chronicles");
|
setsAliases.put("CHR", "Chronicles");
|
||||||
|
@ -140,6 +340,7 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
setsAliases.put("DRK", "The Dark");
|
setsAliases.put("DRK", "The Dark");
|
||||||
setsAliases.put("DST", "Darksteel");
|
setsAliases.put("DST", "Darksteel");
|
||||||
setsAliases.put("DTK", "Dragons of Tarkir");
|
setsAliases.put("DTK", "Dragons of Tarkir");
|
||||||
|
setsAliases.put("E01", "Archenemy: Nicol Bolas");
|
||||||
setsAliases.put("EMN", "Eldritch Moon");
|
setsAliases.put("EMN", "Eldritch Moon");
|
||||||
setsAliases.put("EMA", "Eternal Masters");
|
setsAliases.put("EMA", "Eternal Masters");
|
||||||
setsAliases.put("EVE", "Eventide");
|
setsAliases.put("EVE", "Eventide");
|
||||||
|
@ -272,18 +473,20 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> getSetLinks(String cardSet) {
|
private Map<String, String> getSetLinks(String cardSet) {
|
||||||
ConcurrentHashMap<String, String> setLinks = new ConcurrentHashMap<>();
|
LinkedHashMap<String, String> setLinks = new LinkedHashMap<>();
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(10);
|
ExecutorService executor = Executors.newFixedThreadPool(10);
|
||||||
try {
|
try {
|
||||||
String setNames = setsAliases.get(cardSet);
|
String setNames = setsAliases.get(cardSet);
|
||||||
String preferedLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en");
|
String preferedLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en");
|
||||||
for (String setName : setNames.split("\\^")) {
|
for (String setName : setNames.split("\\^")) {
|
||||||
String URLSetName = URLEncoder.encode(setName, "UTF-8");
|
// String URLSetName = URLEncoder.encode(setName, "UTF-8");
|
||||||
|
String URLSetName = setName.replaceAll(" ", "%20");
|
||||||
int page = 0;
|
int page = 0;
|
||||||
int firstMultiverseIdLastPage = 0;
|
int firstMultiverseIdLastPage = 0;
|
||||||
Pages:
|
Pages:
|
||||||
while (page < 999) {
|
while (page < 999) {
|
||||||
String searchUrl = "http://gatherer.wizards.com/Pages/Search/Default.aspx?page=" + page + "&output=spoiler&method=visual&action=advanced&set=+[%22" + URLSetName + "%22]";
|
String searchUrl = "http://gatherer.wizards.com/Pages/Search/Default.aspx?sort=cn+&page=" + page + "&action=advanced&output=spoiler&method=visual&set=+%5B%22" + URLSetName + "%22%5D";
|
||||||
|
logger.debug("URL: " + searchUrl);
|
||||||
Document doc = getDocument(searchUrl);
|
Document doc = getDocument(searchUrl);
|
||||||
Elements cardsImages = doc.select("img[src^=../../Handlers/]");
|
Elements cardsImages = doc.select("img[src^=../../Handlers/]");
|
||||||
if (cardsImages.isEmpty()) {
|
if (cardsImages.isEmpty()) {
|
||||||
|
@ -307,7 +510,7 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
System.out.println("Exception when parsing the wizards page: " + ex.getMessage());
|
logger.error("Exception when parsing the wizards page: " + ex.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
executor.shutdown();
|
executor.shutdown();
|
||||||
|
@ -327,14 +530,15 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
Connection.ProxyType proxyType = Connection.ProxyType.valueByText(prefs.get("proxyType", "None"));
|
Connection.ProxyType proxyType = Connection.ProxyType.valueByText(prefs.get("proxyType", "None"));
|
||||||
Document doc;
|
Document doc;
|
||||||
if (proxyType == ProxyType.NONE) {
|
if (proxyType == ProxyType.NONE) {
|
||||||
doc = Jsoup.connect(urlString).get();
|
doc = Jsoup.connect(urlString).timeout(60 * 1000).get();
|
||||||
} else {
|
} else {
|
||||||
String proxyServer = prefs.get("proxyAddress", "");
|
String proxyServer = prefs.get("proxyAddress", "");
|
||||||
int proxyPort = Integer.parseInt(prefs.get("proxyPort", "0"));
|
int proxyPort = Integer.parseInt(prefs.get("proxyPort", "0"));
|
||||||
URL url = new URL(urlString);
|
URL url = new URL(urlString);
|
||||||
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyServer, proxyPort));
|
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyServer, proxyPort));
|
||||||
HttpURLConnection uc = (HttpURLConnection) url.openConnection(proxy);
|
HttpURLConnection uc = (HttpURLConnection) url.openConnection(proxy);
|
||||||
|
uc.setConnectTimeout(10000);
|
||||||
|
uc.setReadTimeout(60000);
|
||||||
uc.connect();
|
uc.connect();
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
|
@ -356,7 +560,7 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
if (!variations.isEmpty()) {
|
if (!variations.isEmpty()) {
|
||||||
int landNumber = 1;
|
int landNumber = 1;
|
||||||
for (Element variation : variations) {
|
for (Element variation : variations) {
|
||||||
Integer landMultiverseId = Integer.parseInt(variation.attr("onclick").replaceAll("[^\\d]", ""));
|
Integer landMultiverseId = Integer.parseInt(variation.attr("href").replaceAll("[^\\d]", ""));
|
||||||
links.put((cardName + landNumber).toLowerCase(), generateLink(landMultiverseId));
|
links.put((cardName + landNumber).toLowerCase(), generateLink(landMultiverseId));
|
||||||
landNumber++;
|
landNumber++;
|
||||||
}
|
}
|
||||||
|
@ -435,6 +639,9 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
String setNames = setsAliases.get(cardSet);
|
String setNames = setsAliases.get(cardSet);
|
||||||
if (setNames != null) {
|
if (setNames != null) {
|
||||||
Map<String, String> setLinks = sets.computeIfAbsent(cardSet, k -> getSetLinks(cardSet));
|
Map<String, String> setLinks = sets.computeIfAbsent(cardSet, k -> getSetLinks(cardSet));
|
||||||
|
if (setLinks == null || setLinks.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
String link = setLinks.get(card.getDownloadName().toLowerCase());
|
String link = setLinks.get(card.getDownloadName().toLowerCase());
|
||||||
if (link == null) {
|
if (link == null) {
|
||||||
int length = collectorId.length();
|
int length = collectorId.length();
|
||||||
|
@ -444,11 +651,11 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
int number = Integer.parseInt(collectorId.substring(0, length));
|
int number = Integer.parseInt(collectorId.substring(0, length));
|
||||||
|
List<String> l = new ArrayList<>(setLinks.values());
|
||||||
if (setLinks.size() >= number) {
|
if (l.size() >= number) {
|
||||||
link = setLinks.get(Integer.toString(number - 1));
|
link = l.get(number - 1);
|
||||||
} else {
|
} else {;
|
||||||
link = setLinks.get(Integer.toString(number - 21));
|
link = l.get(number - 21);
|
||||||
if (link != null) {
|
if (link != null) {
|
||||||
link = link.replace(Integer.toString(number - 20), (Integer.toString(number - 20) + 'a'));
|
link = link.replace(Integer.toString(number - 20), (Integer.toString(number - 20) + 'a'));
|
||||||
}
|
}
|
||||||
|
@ -460,6 +667,7 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -474,16 +682,24 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
|
|
||||||
private final class GetImageLinkTask implements Runnable {
|
private final class GetImageLinkTask implements Runnable {
|
||||||
|
|
||||||
private final int multiverseId;
|
private int multiverseId;
|
||||||
private final String cardName;
|
private String cardName;
|
||||||
private final String preferedLanguage;
|
private String preferedLanguage;
|
||||||
private final ConcurrentHashMap setLinks;
|
private LinkedHashMap setLinks;
|
||||||
|
|
||||||
public GetImageLinkTask(int multiverseId, String cardName, String preferedLanguage, ConcurrentHashMap setLinks) {
|
public GetImageLinkTask(int multiverseId, String cardName, String preferedLanguage, LinkedHashMap setLinks) {
|
||||||
|
try {
|
||||||
this.multiverseId = multiverseId;
|
this.multiverseId = multiverseId;
|
||||||
this.cardName = cardName;
|
this.cardName = cardName;
|
||||||
this.preferedLanguage = preferedLanguage;
|
this.preferedLanguage = preferedLanguage;
|
||||||
this.setLinks = setLinks;
|
this.setLinks = setLinks;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error(ex.getMessage());
|
||||||
|
logger.error("multiverseId: " + multiverseId);
|
||||||
|
logger.error("cardName: " + cardName);
|
||||||
|
logger.error("preferedLanguage: " + preferedLanguage);
|
||||||
|
logger.error("setLinks: " + setLinks.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -496,7 +712,7 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
setLinks.put(cardName.toLowerCase(), generateLink(preferedMultiverseId));
|
setLinks.put(cardName.toLowerCase(), generateLink(preferedMultiverseId));
|
||||||
}
|
}
|
||||||
} catch (IOException | NumberFormatException ex) {
|
} catch (IOException | NumberFormatException ex) {
|
||||||
System.out.println("Exception when parsing the wizards page: " + ex.getMessage());
|
logger.error("Exception when parsing the wizards page: " + ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,4 +731,12 @@ public enum WizardCardsImageSource implements CardImageSource {
|
||||||
@Override
|
@Override
|
||||||
public void doPause(String httpImageUrl) {
|
public void doPause(String httpImageUrl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<String> getSupportedSets() {
|
||||||
|
ArrayList<String> supportedSetsCopy = new ArrayList<>();
|
||||||
|
supportedSetsCopy.addAll(supportedSets);
|
||||||
|
return supportedSetsCopy;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class CardDownloadData {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide) {
|
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide) {
|
||||||
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, false, false, "");
|
this(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor, token, twoFacedCard, secondSide, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide, String tokenClassName) {
|
public CardDownloadData(String name, String set, String collectorId, boolean usesVariousArt, Integer type, String tokenSetCode, String tokenDescriptor, boolean token, boolean twoFacedCard, boolean secondSide, String tokenClassName) {
|
||||||
|
@ -72,7 +72,7 @@ public class CardDownloadData {
|
||||||
this.usesVariousArt = card.usesVariousArt;
|
this.usesVariousArt = card.usesVariousArt;
|
||||||
this.tokenSetCode = card.tokenSetCode;
|
this.tokenSetCode = card.tokenSetCode;
|
||||||
this.tokenDescriptor = card.tokenDescriptor;
|
this.tokenDescriptor = card.tokenDescriptor;
|
||||||
this.tokenClassName = tokenClassName;
|
this.tokenClassName = card.tokenClassName;
|
||||||
this.fileName = card.fileName;
|
this.fileName = card.fileName;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.mage.plugins.card.images;
|
package org.mage.plugins.card.images;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
|
@ -14,18 +15,25 @@ import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.IIOImage;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.ImageWriteParam;
|
import javax.imageio.ImageWriteParam;
|
||||||
import javax.imageio.ImageWriter;
|
import javax.imageio.ImageWriter;
|
||||||
import javax.imageio.stream.FileImageOutputStream;
|
import javax.imageio.stream.FileImageOutputStream;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import mage.cards.ExpansionSet;
|
||||||
|
import mage.cards.Sets;
|
||||||
|
import mage.cards.repository.CardCriteria;
|
||||||
import mage.cards.repository.CardInfo;
|
import mage.cards.repository.CardInfo;
|
||||||
|
import mage.cards.repository.CardRepository;
|
||||||
|
import mage.client.MageFrame;
|
||||||
import mage.client.constants.Constants;
|
import mage.client.constants.Constants;
|
||||||
import mage.client.dialog.PreferencesDialog;
|
import mage.client.dialog.PreferencesDialog;
|
||||||
import mage.client.util.sets.ConstructedFormats;
|
import mage.client.util.sets.ConstructedFormats;
|
||||||
import mage.remote.Connection;
|
import mage.remote.Connection;
|
||||||
|
import static mage.remote.Connection.ProxyType.HTTP;
|
||||||
|
import static mage.remote.Connection.ProxyType.NONE;
|
||||||
|
import static mage.remote.Connection.ProxyType.SOCKS;
|
||||||
import net.java.truevfs.access.TFile;
|
import net.java.truevfs.access.TFile;
|
||||||
import net.java.truevfs.access.TFileOutputStream;
|
import net.java.truevfs.access.TFileOutputStream;
|
||||||
import net.java.truevfs.access.TVFS;
|
import net.java.truevfs.access.TVFS;
|
||||||
|
@ -37,51 +45,97 @@ import org.mage.plugins.card.utils.CardImageUtils;
|
||||||
|
|
||||||
public class DownloadPictures extends DefaultBoundedRangeModel implements Runnable {
|
public class DownloadPictures extends DefaultBoundedRangeModel implements Runnable {
|
||||||
|
|
||||||
|
private static DownloadPictures instance;
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(DownloadPictures.class);
|
private static final Logger logger = Logger.getLogger(DownloadPictures.class);
|
||||||
|
|
||||||
|
public static final String ALL_IMAGES = "- All images from that source";
|
||||||
|
public static final String ALL_STANDARD_IMAGES = "- All images from standard from that source";
|
||||||
|
public static final String ALL_TOKENS = "- Only all token images from that source";
|
||||||
|
|
||||||
|
private JDialog dialog;
|
||||||
private final JProgressBar bar;
|
private final JProgressBar bar;
|
||||||
private final JOptionPane dlg;
|
private final JOptionPane dlg;
|
||||||
private boolean cancel;
|
private boolean cancel;
|
||||||
private final JButton closeButton;
|
private final JButton closeButton;
|
||||||
private final JButton startDownloadButton;
|
private final JButton startDownloadButton;
|
||||||
private int cardIndex;
|
private int cardIndex;
|
||||||
private List<CardDownloadData> cards;
|
private List<CardDownloadData> allCardsMissingImage;
|
||||||
private List<CardDownloadData> type2cards;
|
private List<CardDownloadData> cardsToDownload;
|
||||||
private final JComboBox jComboBox1;
|
|
||||||
private final JLabel jLabel1;
|
private int missingCards = 0;
|
||||||
private static boolean offlineMode = false;
|
private int missingTokens = 0;
|
||||||
private JCheckBox checkBox;
|
|
||||||
|
List<String> selectedSetCodes = new ArrayList<>();
|
||||||
|
|
||||||
|
private final JComboBox jComboBoxServer;
|
||||||
|
private final JLabel jLabelMessage;
|
||||||
|
private final JLabel jLabelAllMissing;
|
||||||
|
private final JLabel jLabelServer;
|
||||||
|
|
||||||
|
private final JComboBox jComboBoxSet;
|
||||||
|
private final JLabel jLabelSet;
|
||||||
|
|
||||||
private final Object sync = new Object();
|
private final Object sync = new Object();
|
||||||
|
|
||||||
private static CardImageSource cardImageSource;
|
private static CardImageSource cardImageSource;
|
||||||
|
|
||||||
private Proxy p = Proxy.NO_PROXY;
|
private Proxy p = Proxy.NO_PROXY;
|
||||||
|
|
||||||
// private ExecutorService executor = Executors.newFixedThreadPool(10);
|
enum DownloadSources {
|
||||||
public static void main(String[] args) {
|
WIZARDS("wizards.com", WizardCardsImageSource.instance),
|
||||||
startDownload(null, null);
|
MYTHICSPOILER("mythicspoiler.com", MythicspoilerComSource.instance),
|
||||||
|
TOKENS("tokens.mtg.onl", TokensMtgImageSource.instance),
|
||||||
|
// MTG_ONL("mtg.onl", MtgOnlTokensImageSource.instance), Not working correctly yet
|
||||||
|
ALTERNATIVE("alternative.mtg.onl", AltMtgOnlTokensImageSource.instance),
|
||||||
|
GRAB_BAG("GrabBag", GrabbagImageSource.instance),
|
||||||
|
MAGIDEX("magidex.com", MagidexImageSource.instance),
|
||||||
|
SCRYFALL("scryfall.com", ScryfallImageSource.instance);
|
||||||
|
// MAGICCARDS("magiccards.info", MagicCardsImageSource.instance)
|
||||||
|
|
||||||
|
private final String text;
|
||||||
|
private final CardImageSource source;
|
||||||
|
|
||||||
|
DownloadSources(String text, CardImageSource sourceInstance) {
|
||||||
|
this.text = text;
|
||||||
|
this.source = sourceInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startDownload(JFrame frame, List<CardInfo> allCards) {
|
public CardImageSource getSource() {
|
||||||
List<CardDownloadData> cards = getNeededCards(allCards);
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DownloadPictures getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
startDownload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startDownload() {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if (cards == null || cards.isEmpty()) {
|
* if (cards == null || cards.isEmpty()) {
|
||||||
* JOptionPane.showMessageDialog(null,
|
* JOptionPane.showMessageDialog(null,
|
||||||
* "All card pictures have been downloaded."); return; }
|
* "All card pictures have been downloaded."); return; }
|
||||||
*/
|
*/
|
||||||
DownloadPictures download = new DownloadPictures(cards);
|
instance = new DownloadPictures(MageFrame.getInstance());
|
||||||
JDialog dlg = download.getDlg(frame);
|
Thread t1 = new Thread(new LoadMissingCardData(instance));
|
||||||
dlg.setVisible(true);
|
t1.start();
|
||||||
dlg.dispose();
|
instance.getDlg().setVisible(true);
|
||||||
download.cancel = true;
|
instance.getDlg().dispose();
|
||||||
|
instance.cancel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JDialog getDlg(JFrame frame) {
|
public JDialog getDlg() {
|
||||||
String title = "Downloading";
|
|
||||||
|
|
||||||
final JDialog dialog = this.dlg.createDialog(frame, title);
|
|
||||||
closeButton.addActionListener(e -> dialog.setVisible(false));
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,75 +143,77 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
this.cancel = cancel;
|
this.cancel = cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownloadPictures(List<CardDownloadData> cards) {
|
static int WIDTH = 400;
|
||||||
this.cards = cards;
|
|
||||||
|
|
||||||
bar = new JProgressBar(this);
|
public DownloadPictures(JFrame frame) {
|
||||||
|
|
||||||
|
cardsToDownload = new ArrayList<>();
|
||||||
|
|
||||||
JPanel p0 = new JPanel();
|
JPanel p0 = new JPanel();
|
||||||
p0.setLayout(new BoxLayout(p0, BoxLayout.Y_AXIS));
|
p0.setLayout(new BoxLayout(p0, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
p0.add(Box.createVerticalStrut(5));
|
p0.add(Box.createVerticalStrut(5));
|
||||||
jLabel1 = new JLabel();
|
|
||||||
jLabel1.setText("Please select server:");
|
|
||||||
|
|
||||||
jLabel1.setAlignmentX(Component.LEFT_ALIGNMENT);
|
jLabelMessage = new JLabel();
|
||||||
|
jLabelMessage.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||||
p0.add(jLabel1);
|
jLabelMessage.setText("Initializing image download...");
|
||||||
|
p0.add(jLabelMessage);
|
||||||
p0.add(Box.createVerticalStrut(5));
|
p0.add(Box.createVerticalStrut(5));
|
||||||
ComboBoxModel jComboBox1Model = new DefaultComboBoxModel(new String[]{
|
|
||||||
// "magiccards.info",
|
|
||||||
"wizards.com",
|
|
||||||
"mythicspoiler.com",
|
|
||||||
"tokens.mtg.onl", //"mtgimage.com (HQ)",
|
|
||||||
"mtg.onl",
|
|
||||||
"alternative.mtg.onl",
|
|
||||||
"GrabBag",
|
|
||||||
"magidex.com",
|
|
||||||
"scryfall.com", //"mtgathering.ru HQ",
|
|
||||||
//"mtgathering.ru MQ",
|
|
||||||
//"mtgathering.ru LQ",
|
|
||||||
});
|
|
||||||
jComboBox1 = new JComboBox();
|
|
||||||
|
|
||||||
cardImageSource = MagicCardsImageSource.instance;
|
jLabelAllMissing = new JLabel();
|
||||||
|
|
||||||
jComboBox1.setModel(jComboBox1Model);
|
jLabelAllMissing.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
jComboBox1.setAlignmentX(Component.LEFT_ALIGNMENT);
|
// jLabelAllMissing.setText("Computing number of missing images...");
|
||||||
jComboBox1.addActionListener(e -> {
|
p0.add(jLabelAllMissing);
|
||||||
JComboBox cb = (JComboBox) e.getSource();
|
p0.add(Box.createVerticalStrut(5));
|
||||||
switch (cb.getSelectedIndex() + 1) {
|
|
||||||
case 0:
|
jLabelServer = new JLabel();
|
||||||
cardImageSource = MagicCardsImageSource.instance;
|
jLabelServer.setText("Please select image source:");
|
||||||
break;
|
jLabelServer.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
case 1:
|
jLabelServer.setVisible(false);
|
||||||
cardImageSource = WizardCardsImageSource.instance;
|
p0.add(jLabelServer);
|
||||||
break;
|
|
||||||
case 2:
|
p0.add(Box.createVerticalStrut(5));
|
||||||
cardImageSource = MythicspoilerComSource.instance;
|
|
||||||
break;
|
jComboBoxServer = new JComboBox();
|
||||||
case 3:
|
jComboBoxServer.setModel(new DefaultComboBoxModel(DownloadSources.values()));
|
||||||
cardImageSource = TokensMtgImageSource.instance;
|
jComboBoxServer.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
break;
|
jComboBoxServer.setAlignmentY(Component.LEFT_ALIGNMENT);
|
||||||
case 4:
|
jComboBoxServer.addItemListener((ItemEvent event) -> {
|
||||||
cardImageSource = MtgOnlTokensImageSource.instance;
|
if (event.getStateChange() == ItemEvent.SELECTED) {
|
||||||
break;
|
comboBoxServerItemSelected(event);
|
||||||
case 5:
|
|
||||||
cardImageSource = AltMtgOnlTokensImageSource.instance;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
cardImageSource = GrabbagImageSource.instance;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
cardImageSource = MagidexImageSource.instance;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
cardImageSource = ScryfallImageSource.instance;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
updateCardsToDownload();
|
|
||||||
});
|
});
|
||||||
p0.add(jComboBox1);
|
Dimension d = jComboBoxServer.getPreferredSize();
|
||||||
|
d.width = WIDTH;
|
||||||
|
jComboBoxServer.setPreferredSize(d);
|
||||||
|
p0.add(jComboBoxServer);
|
||||||
|
jComboBoxServer.setVisible(false);
|
||||||
|
|
||||||
|
// set the first source as default
|
||||||
|
cardImageSource = WizardCardsImageSource.instance;
|
||||||
|
|
||||||
|
p0.add(Box.createVerticalStrut(5));
|
||||||
|
|
||||||
|
// Set selection ---------------------------------
|
||||||
|
jLabelSet = new JLabel();
|
||||||
|
jLabelSet.setText("Please select sets to download the images for:");
|
||||||
|
jLabelSet.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
jLabelSet.setVisible(false);
|
||||||
|
p0.add(jLabelSet);
|
||||||
|
|
||||||
|
jComboBoxSet = new JComboBox();
|
||||||
|
// jComboBoxSet.setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource()));
|
||||||
|
jComboBoxSet.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
|
jComboBoxSet.addItemListener((ItemEvent event) -> {
|
||||||
|
if (event.getStateChange() == ItemEvent.SELECTED) {
|
||||||
|
comboBoxSetItemSelected(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
p0.add(jComboBoxSet);
|
||||||
|
jComboBoxSet.setVisible(false);
|
||||||
|
|
||||||
p0.add(Box.createVerticalStrut(5));
|
p0.add(Box.createVerticalStrut(5));
|
||||||
|
|
||||||
// Start
|
// Start
|
||||||
|
@ -165,78 +221,168 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
startDownloadButton.addActionListener(e -> {
|
startDownloadButton.addActionListener(e -> {
|
||||||
new Thread(DownloadPictures.this).start();
|
new Thread(DownloadPictures.this).start();
|
||||||
startDownloadButton.setEnabled(false);
|
startDownloadButton.setEnabled(false);
|
||||||
checkBox.setEnabled(false);
|
|
||||||
});
|
});
|
||||||
p0.add(Box.createVerticalStrut(5));
|
p0.add(Box.createVerticalStrut(5));
|
||||||
|
|
||||||
// Progress
|
// Progress
|
||||||
|
bar = new JProgressBar(this);
|
||||||
p0.add(bar);
|
p0.add(bar);
|
||||||
bar.setStringPainted(true);
|
bar.setStringPainted(true);
|
||||||
int count = cards.size();
|
|
||||||
float mb = (count * cardImageSource.getAverageSize()) / 1024;
|
d = bar.getPreferredSize();
|
||||||
bar.setString(String.format(cardIndex == cards.size() ? "%d of %d cards finished! Please close!"
|
d.width = WIDTH;
|
||||||
: "%d of %d cards finished! Please wait! [%.1f Mb]", 0, cards.size(), mb));
|
|
||||||
Dimension d = bar.getPreferredSize();
|
|
||||||
d.width = 300;
|
|
||||||
bar.setPreferredSize(d);
|
bar.setPreferredSize(d);
|
||||||
|
bar.setVisible(false);
|
||||||
p0.add(Box.createVerticalStrut(5));
|
|
||||||
checkBox = new JCheckBox("Download images for Standard (Type2) only");
|
|
||||||
p0.add(checkBox);
|
|
||||||
p0.add(Box.createVerticalStrut(5));
|
|
||||||
|
|
||||||
checkBox.addActionListener(e -> updateCardsToDownload());
|
|
||||||
|
|
||||||
// JOptionPane
|
// JOptionPane
|
||||||
Object[] options = {startDownloadButton, closeButton = new JButton("Cancel")};
|
Object[] options = {startDownloadButton, closeButton = new JButton("Cancel")};
|
||||||
|
startDownloadButton.setVisible(false);
|
||||||
|
closeButton.addActionListener(e -> dialog.setVisible(false));
|
||||||
|
closeButton.setVisible(false);
|
||||||
|
|
||||||
dlg = new JOptionPane(p0, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, options, options[1]);
|
dlg = new JOptionPane(p0, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, options, options[1]);
|
||||||
|
dialog = this.dlg.createDialog(frame, "Downloading images");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean checkForMissingCardImages(List<CardInfo> allCards) {
|
public void setAllMissingCards() {
|
||||||
AtomicBoolean missedCardTFiles = new AtomicBoolean();
|
updateAndViewMessage("Get all available cards from the repository...");
|
||||||
allCards.parallelStream().forEach(card -> {
|
List<CardInfo> cards = CardRepository.instance.findCards(new CardCriteria());
|
||||||
if (!missedCardTFiles.get()) {
|
updateAndViewMessage("Check which images are missing ...");
|
||||||
if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()) {
|
this.allCardsMissingImage = getNeededCards(cards);
|
||||||
CardDownloadData url = new CardDownloadData(card.getName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(),
|
updateAndViewMessage("Check which images the current source is providing ...");
|
||||||
0, "", "", false, card.isDoubleFaced(), card.isNightCard());
|
jComboBoxSet.setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource()));
|
||||||
TFile file = new TFile(CardImageUtils.generateImagePath(url));
|
|
||||||
if (!file.exists()) {
|
updateCardsToDownload(jComboBoxSet.getSelectedItem().toString());
|
||||||
missedCardTFiles.set(true);
|
|
||||||
}
|
jComboBoxServer.setVisible(true);
|
||||||
}
|
jLabelServer.setVisible(true);
|
||||||
}
|
jComboBoxSet.setVisible(true);
|
||||||
});
|
jLabelSet.setVisible(true);
|
||||||
return missedCardTFiles.get();
|
bar.setVisible(true);
|
||||||
|
startDownloadButton.setVisible(true);
|
||||||
|
closeButton.setVisible(true);
|
||||||
|
|
||||||
|
updateAndViewMessage("");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCardsToDownload() {
|
private void comboBoxServerItemSelected(ItemEvent evt) {
|
||||||
List<CardDownloadData> cardsToDownload = cards;
|
if (jComboBoxServer.isEnabled()) {
|
||||||
if (type2cardsOnly()) {
|
cardImageSource = ((DownloadSources) evt.getItem()).getSource();
|
||||||
selectType2andTokenCardsIfNotYetDone();
|
// update the available sets / token comboBox
|
||||||
cardsToDownload = type2cards;
|
jComboBoxSet.setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource()));
|
||||||
}
|
updateCardsToDownload(jComboBoxSet.getSelectedItem().toString());
|
||||||
updateProgressText(cardsToDownload.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean type2cardsOnly() {
|
|
||||||
return checkBox.isSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void selectType2andTokenCardsIfNotYetDone() {
|
|
||||||
if (type2cards == null) {
|
|
||||||
type2cards = new ArrayList<>();
|
|
||||||
for (CardDownloadData data : cards) {
|
|
||||||
if (data.isType2() || data.isToken()) {
|
|
||||||
type2cards.add(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateProgressText(int cardCount) {
|
public void updateAndViewMessage(String text) {
|
||||||
float mb = (cardCount * cardImageSource.getAverageSize()) / 1024;
|
jLabelMessage.setText(text);
|
||||||
bar.setString(String.format(cardIndex == cardCount ? "%d of %d cards finished! Please close!"
|
if (dialog != null) {
|
||||||
: "%d of %d cards finished! Please wait! [%.1f Mb]", 0, cardCount, mb));
|
dialog.pack();
|
||||||
|
dialog.validate();
|
||||||
|
dialog.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object[] getSetsForCurrentImageSource() {
|
||||||
|
// Set the available sets to the combo box
|
||||||
|
ArrayList<String> supportedSets = cardImageSource.getSupportedSets();
|
||||||
|
List<String> setNames = new ArrayList<>();
|
||||||
|
if (supportedSets != null) {
|
||||||
|
setNames.add(ALL_IMAGES);
|
||||||
|
setNames.add(ALL_STANDARD_IMAGES);
|
||||||
|
}
|
||||||
|
if (cardImageSource.isTokenSource()) {
|
||||||
|
setNames.add(ALL_TOKENS);
|
||||||
|
}
|
||||||
|
if (supportedSets != null) {
|
||||||
|
for (String setCode : supportedSets) {
|
||||||
|
ExpansionSet expansionSet = Sets.findSet(setCode);
|
||||||
|
if (expansionSet != null) {
|
||||||
|
setNames.add(expansionSet.getName());
|
||||||
|
} else {
|
||||||
|
logger.error(cardImageSource.getSourceName() + ": Expansion set for code " + setCode + " not found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (setNames.isEmpty()) {
|
||||||
|
logger.error("Source " + cardImageSource.getSourceName() + " creates no selectable items.");
|
||||||
|
setNames.add("not avalable");
|
||||||
|
}
|
||||||
|
return setNames.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCardsToDownload(String itemText) {
|
||||||
|
selectedSetCodes.clear();
|
||||||
|
switch (itemText) {
|
||||||
|
case ALL_IMAGES:
|
||||||
|
if (cardImageSource.getSupportedSets() == null) {
|
||||||
|
selectedSetCodes = cardImageSource.getSupportedSets();
|
||||||
|
} else {
|
||||||
|
selectedSetCodes.addAll(cardImageSource.getSupportedSets());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ALL_STANDARD_IMAGES:
|
||||||
|
List<String> standardSets = ConstructedFormats.getSetsByFormat(ConstructedFormats.STANDARD);
|
||||||
|
for (String setCode : cardImageSource.getSupportedSets()) {
|
||||||
|
if (standardSets.contains(setCode)) {
|
||||||
|
selectedSetCodes.add(setCode);
|
||||||
|
} else {
|
||||||
|
logger.debug("Set code " + setCode + " from download source " + cardImageSource.getSourceName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ALL_TOKENS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
int nonSetEntries = 0;
|
||||||
|
if (cardImageSource.getSupportedSets() != null) {
|
||||||
|
nonSetEntries = 2;
|
||||||
|
}
|
||||||
|
if (cardImageSource.isTokenSource()) {
|
||||||
|
nonSetEntries++;
|
||||||
|
}
|
||||||
|
selectedSetCodes.add(cardImageSource.getSupportedSets().get(jComboBoxSet.getSelectedIndex() - nonSetEntries));
|
||||||
|
}
|
||||||
|
cardsToDownload.clear();
|
||||||
|
int numberTokenImagesAvailable = 0;
|
||||||
|
int numberCardImagesAvailable = 0;
|
||||||
|
for (CardDownloadData data : allCardsMissingImage) {
|
||||||
|
if (data.isToken()) {
|
||||||
|
if (cardImageSource.isTokenSource() && cardImageSource.isImageProvided(data.getSet(), data.getName())) {
|
||||||
|
numberTokenImagesAvailable++;
|
||||||
|
cardsToDownload.add(data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (selectedSetCodes != null && selectedSetCodes.contains(data.getSet())) {
|
||||||
|
if (cardImageSource.isSetSupportedComplete(data.getSet()) || cardImageSource.isImageProvided(data.getSet(), data.getName())) {
|
||||||
|
numberCardImagesAvailable++;
|
||||||
|
cardsToDownload.add(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateProgressText(numberCardImagesAvailable, numberTokenImagesAvailable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void comboBoxSetItemSelected(ItemEvent event) {
|
||||||
|
// Update the cards to download related to the selected set
|
||||||
|
updateCardsToDownload(event.getItem().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgressText(int cardCount, int tokenCount) {
|
||||||
|
missingTokens = 0;
|
||||||
|
for (CardDownloadData card : allCardsMissingImage) {
|
||||||
|
if (card.isToken()) {
|
||||||
|
missingTokens++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
missingCards = allCardsMissingImage.size() - missingTokens;
|
||||||
|
jLabelAllMissing.setText("Missing: " + missingCards + " card images / " + missingTokens + " token images");
|
||||||
|
int imageSum = cardCount + tokenCount;
|
||||||
|
float mb = (imageSum * cardImageSource.getAverageSize()) / 1024;
|
||||||
|
bar.setString(String.format(cardIndex == imageSum ? "%d of %d (%d cards/%d tokens) image downloads finished! Please close!"
|
||||||
|
: "%d of %d (%d cards/%d tokens) image downloads finished! Please wait! [%.1f Mb]", 0, imageSum, cardCount, tokenCount, mb));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String createDownloadName(CardInfo card) {
|
private static String createDownloadName(CardInfo card) {
|
||||||
|
@ -262,11 +408,8 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
logger.warn("No formats defined. Try connecting to a server first!");
|
logger.warn("No formats defined. Try connecting to a server first!");
|
||||||
}
|
}
|
||||||
|
|
||||||
int numberCardImages = allCards.size();
|
|
||||||
int numberWithoutTokens = 0;
|
|
||||||
List<CardDownloadData> allCardsUrls = Collections.synchronizedList(new ArrayList<>());
|
List<CardDownloadData> allCardsUrls = Collections.synchronizedList(new ArrayList<>());
|
||||||
try {
|
try {
|
||||||
offlineMode = true;
|
|
||||||
allCards.parallelStream().forEach(card -> {
|
allCards.parallelStream().forEach(card -> {
|
||||||
if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()
|
if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty()
|
||||||
&& !ignoreUrls.contains(card.getSetCode())) {
|
&& !ignoreUrls.contains(card.getSetCode())) {
|
||||||
|
@ -286,6 +429,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
if (card.getSecondSideName() == null || card.getSecondSideName().trim().isEmpty()) {
|
if (card.getSecondSideName() == null || card.getSecondSideName().trim().isEmpty()) {
|
||||||
throw new IllegalStateException("Second side card can't have empty name.");
|
throw new IllegalStateException("Second side card can't have empty name.");
|
||||||
}
|
}
|
||||||
|
|
||||||
url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), true);
|
url = new CardDownloadData(card.getSecondSideName(), card.getSetCode(), card.getCardNumber(), card.usesVariousArt(), 0, "", "", false, card.isDoubleFaced(), true);
|
||||||
url.setType2(isType2);
|
url.setType2(isType2);
|
||||||
allCardsUrls.add(url);
|
allCardsUrls.add(url);
|
||||||
|
@ -301,21 +445,18 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
allCardsUrls.add(cardDownloadData);
|
allCardsUrls.add(cardDownloadData);
|
||||||
}
|
}
|
||||||
} else if (card.getCardNumber().isEmpty() || "0".equals(card.getCardNumber())) {
|
} else if (card.getCardNumber().isEmpty() || "0".equals(card.getCardNumber())) {
|
||||||
System.err.println("There was a critical error!");
|
|
||||||
logger.error("Card has no collector ID and won't be sent to client: " + card.getName());
|
logger.error("Card has no collector ID and won't be sent to client: " + card.getName());
|
||||||
} else if (card.getSetCode().isEmpty()) {
|
} else if (card.getSetCode().isEmpty()) {
|
||||||
System.err.println("There was a critical error!");
|
|
||||||
logger.error("Card has no set name and won't be sent to client:" + card.getName());
|
logger.error("Card has no set name and won't be sent to client:" + card.getName());
|
||||||
|
} else {
|
||||||
|
logger.info("Card was not selected: " + card.getName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
numberWithoutTokens = allCards.size();
|
|
||||||
allCardsUrls.addAll(getTokenCardUrls());
|
allCardsUrls.addAll(getTokenCardUrls());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
int numberAllTokenImages = allCardsUrls.size() - numberWithoutTokens;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check to see which cards we already have
|
* check to see which cards we already have
|
||||||
*/
|
*/
|
||||||
|
@ -329,22 +470,13 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
int tokenImages = 0;
|
|
||||||
for (CardDownloadData card : cardsToDownload) {
|
|
||||||
logger.debug((card.isToken() ? "Token" : "Card") + " image to download: " + card.getName() + " (" + card.getSet() + ')');
|
|
||||||
if (card.isToken()) {
|
|
||||||
tokenImages++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.info("Check download images (total card images: " + numberCardImages + ", total token images: " + numberAllTokenImages + ')');
|
|
||||||
logger.info(" => Missing card images: " + (cardsToDownload.size() - tokenImages));
|
|
||||||
logger.info(" => Missing token images: " + tokenImages);
|
|
||||||
return new ArrayList<>(cardsToDownload);
|
return new ArrayList<>(cardsToDownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayList<CardDownloadData> getTokenCardUrls() throws RuntimeException {
|
public static ArrayList<CardDownloadData> getTokenCardUrls() throws RuntimeException {
|
||||||
ArrayList<CardDownloadData> list = new ArrayList<>();
|
ArrayList<CardDownloadData> list = new ArrayList<>();
|
||||||
InputStream in = DownloadPictures.class.getClassLoader().getResourceAsStream("card-pictures-tok.txt");
|
InputStream in = DownloadPictures.class
|
||||||
|
.getClassLoader().getResourceAsStream("card-pictures-tok.txt");
|
||||||
|
|
||||||
if (in == null) {
|
if (in == null) {
|
||||||
logger.error("resources input stream is null");
|
logger.error("resources input stream is null");
|
||||||
|
@ -446,9 +578,8 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
if (p != null) {
|
if (p != null) {
|
||||||
HashSet<String> ignoreUrls = SettingsManager.getIntance().getIgnoreUrls();
|
HashSet<String> ignoreUrls = SettingsManager.getIntance().getIgnoreUrls();
|
||||||
|
|
||||||
List<CardDownloadData> cardsToDownload = this.checkBox.isSelected() ? type2cards : cards;
|
|
||||||
|
|
||||||
update(0, cardsToDownload.size());
|
update(0, cardsToDownload.size());
|
||||||
|
logger.info("Started download of " + cardsToDownload.size() + " images from source: " + cardImageSource.getSourceName());
|
||||||
|
|
||||||
int numberOfThreads = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_THREADS, "10"));
|
int numberOfThreads = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_THREADS, "10"));
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
|
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
|
||||||
|
@ -457,7 +588,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
|
|
||||||
CardDownloadData card = cardsToDownload.get(i);
|
CardDownloadData card = cardsToDownload.get(i);
|
||||||
|
|
||||||
logger.debug("Downloading card: " + card.getName() + " (" + card.getSet() + ')');
|
logger.debug("Downloading image: " + card.getName() + " (" + card.getSet() + ')');
|
||||||
|
|
||||||
String url;
|
String url;
|
||||||
if (ignoreUrls.contains(card.getSet()) || card.isToken()) {
|
if (ignoreUrls.contains(card.getSet()) || card.isToken()) {
|
||||||
|
@ -482,7 +613,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
}
|
}
|
||||||
} else if (cardImageSource.getTotalImages() == -1) {
|
} else if (cardImageSource.getTotalImages() == -1) {
|
||||||
logger.info("Card not available on " + cardImageSource.getSourceName() + ": " + card.getName() + " (" + card.getSet() + ')');
|
logger.info("Image not available on " + cardImageSource.getSourceName() + ": " + card.getName() + " (" + card.getSet() + ')');
|
||||||
synchronized (sync) {
|
synchronized (sync) {
|
||||||
update(cardIndex + 1, cardsToDownload.size());
|
update(cardIndex + 1, cardsToDownload.size());
|
||||||
}
|
}
|
||||||
|
@ -513,6 +644,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
System.gc();
|
System.gc();
|
||||||
}
|
}
|
||||||
closeButton.setText("Close");
|
closeButton.setText("Close");
|
||||||
|
updateCardsToDownload(jComboBoxSet.getSelectedItem().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
static String convertStreamToString(java.io.InputStream is) {
|
static String convertStreamToString(java.io.InputStream is) {
|
||||||
|
@ -604,6 +736,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
if (temporaryFile != null && temporaryFile.length() > 100) {
|
if (temporaryFile != null && temporaryFile.length() > 100) {
|
||||||
useTempFile = true;
|
useTempFile = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
cardImageSource.doPause(url.getPath());
|
cardImageSource.doPause(url.getPath());
|
||||||
httpConn = url.openConnection(p);
|
httpConn = url.openConnection(p);
|
||||||
httpConn.connect();
|
httpConn.connect();
|
||||||
|
@ -708,29 +841,52 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
||||||
|
|
||||||
if (cardIndex < count) {
|
if (cardIndex < count) {
|
||||||
float mb = ((count - card) * cardImageSource.getAverageSize()) / 1024;
|
float mb = ((count - card) * cardImageSource.getAverageSize()) / 1024;
|
||||||
bar.setString(String.format("%d of %d cards finished! Please wait! [%.1f Mb]",
|
bar.setString(String.format("%d of %d image downloads finished! Please wait! [%.1f Mb]",
|
||||||
card, count, mb));
|
card, count, mb));
|
||||||
} else {
|
} else {
|
||||||
List<CardDownloadData> remainingCards = Collections.synchronizedList(new ArrayList<>());
|
List<CardDownloadData> remainingCards = Collections.synchronizedList(new ArrayList<>());
|
||||||
DownloadPictures.this.cards.parallelStream().forEach(cardDownloadData -> {
|
DownloadPictures.this.allCardsMissingImage.parallelStream().forEach(cardDownloadData -> {
|
||||||
TFile file = new TFile(CardImageUtils.generateImagePath(cardDownloadData));
|
TFile file = new TFile(CardImageUtils.generateImagePath(cardDownloadData));
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
remainingCards.add(cardDownloadData);
|
remainingCards.add(cardDownloadData);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
DownloadPictures.this.cards = new ArrayList<>(remainingCards);
|
// remove the cards not downloaded to get the siccessfull downloaded cards
|
||||||
|
DownloadPictures.this.cardsToDownload.removeAll(remainingCards);
|
||||||
|
DownloadPictures.this.allCardsMissingImage.removeAll(DownloadPictures.this.cardsToDownload);
|
||||||
|
|
||||||
count = DownloadPictures.this.cards.size();
|
count = remainingCards.size();
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
bar.setString("0 cards remaining! Please close!");
|
bar.setString("0 images remaining! Please close!");
|
||||||
} else {
|
} else {
|
||||||
bar.setString(String.format("%d cards remaining! Please choose another source!", count));
|
// bar.setString(String.format("%d cards remaining! Please choose another source!", count));
|
||||||
startDownloadButton.setEnabled(true);
|
startDownloadButton.setEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadMissingCardData implements Runnable {
|
||||||
|
|
||||||
|
private static DownloadPictures downloadPictures;
|
||||||
|
|
||||||
|
public LoadMissingCardData(DownloadPictures downloadPictures) {
|
||||||
|
LoadMissingCardData.downloadPictures = downloadPictures;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
downloadPictures.setAllMissingCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main() {
|
||||||
|
|
||||||
|
(new Thread(new LoadMissingCardData(downloadPictures))).start();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1096,6 +1096,16 @@
|
||||||
|Generate|TOK:WWK|Snake|||SnakeToken|
|
|Generate|TOK:WWK|Snake|||SnakeToken|
|
||||||
|Generate|TOK:WWK|Soldier Ally|||JoinTheRanksSoldierToken|
|
|Generate|TOK:WWK|Soldier Ally|||JoinTheRanksSoldierToken|
|
||||||
|Generate|TOK:WWK|Wolf|||WolfToken|
|
|Generate|TOK:WWK|Wolf|||WolfToken|
|
||||||
|
|Generate|TOK:XLN|Dinosaur|||DinosaurToken|
|
||||||
|
|Generate|TOK:XLN|Illusion|||JaceCunningCastawayIllusionToken|
|
||||||
|
|Generate|TOK:XLN|Merfolk|||MerfolkHexproofToken|
|
||||||
|
|Generate|TOK:XLN|Pirate|||PirateToken|
|
||||||
|
|Generate|TOK:XLN|Plant|||DefenderPlantToken|
|
||||||
|
|Generate|TOK:XLN|Treasure|1||TreasureToken|
|
||||||
|
|Generate|TOK:XLN|Treasure|2||TreasureToken|
|
||||||
|
|Generate|TOK:XLN|Treasure|3||TreasureToken|
|
||||||
|
|Generate|TOK:XLN|Treasure|4||TreasureToken|
|
||||||
|
|Generate|TOK:XLN|Vampire|||IxalanVampireToken|
|
||||||
|Generate|TOK:ZEN|Angel|||AngelToken|
|
|Generate|TOK:ZEN|Angel|||AngelToken|
|
||||||
|Generate|TOK:ZEN|Beast|||BeastToken2|
|
|Generate|TOK:ZEN|Beast|||BeastToken2|
|
||||||
|Generate|TOK:ZEN|Bird|||BirdToken|
|
|Generate|TOK:ZEN|Bird|||BirdToken|
|
||||||
|
|
|
@ -74,6 +74,6 @@ dd3evg=ddaevg
|
||||||
dd3gvl=ddagvl
|
dd3gvl=ddagvl
|
||||||
dd3jvc=ddajvc
|
dd3jvc=ddajvc
|
||||||
# Remove setname as soon as the images can be downloaded
|
# Remove setname as soon as the images can be downloaded
|
||||||
ignore.urls=TOK,DDT,V17,IMA,RIX,E02,M19,M25,DOM,UST,H17
|
ignore.urls=TOK,DDT,V17,RIX,E02,M19,M25,DOM,UST,H17
|
||||||
# sets ordered by release time (newest goes first)
|
# sets ordered by release time (newest goes first)
|
||||||
token.lookup.order=M19,M25,DOM,E02,RIX,UST,XLN,IMA,H17,C17,V17,E01,DDT,CMA,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,MPS,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC
|
token.lookup.order=M19,M25,DOM,E02,RIX,UST,XLN,IMA,H17,C17,V17,E01,DDT,CMA,HOU,MM3,DDS,AKH,DD3DVD,DD3EVG,DD3GVL,DD3JVC,H09,AER,PCA,C16,V16,MPS,KLD,DDR,CN2,EMN,EMA,SOI,DDQ,CP,CMA,ARENA,SUS,APAC,EURO,UGIN,C15,OGW,EXP,DDP,BFZ,DRB,V09,V10,V11,V12,V13,V14,V15,TPR,MPRP,DD3,DDO,ORI,MM2,PTC,DTK,FRF,KTK,M15,VMA,CNS,JOU,BNG,THS,DDL,M14,MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,DDE,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK,GRC
|
|
@ -222,7 +222,7 @@ Eldrazi Spawn, 1a, -, -, -, Creature - Eldrazi Spawn, Aleksi Briclot, Sacrifice
|
||||||
Eldrazi Spawn, 1b, -, -, -, Creature - Eldrazi Spawn, Mark Tedin, Sacrifice this creature: Add {1} to your mana pool.
|
Eldrazi Spawn, 1b, -, -, -, Creature - Eldrazi Spawn, Mark Tedin, Sacrifice this creature: Add {1} to your mana pool.
|
||||||
Eldrazi Spawn, 1c, -, -, -, Creature - Eldrazi Spawn, Veronique Meignaud, Sacrifice this creature: Add {1} to your mana pool.
|
Eldrazi Spawn, 1c, -, -, -, Creature - Eldrazi Spawn, Veronique Meignaud, Sacrifice this creature: Add {1} to your mana pool.
|
||||||
Elemental, 2, R, *|*, -, Creature - Elemental, Jung Park, -
|
Elemental, 2, R, *|*, -, Creature - Elemental, Jung Park, -
|
||||||
Hellion, 3, R, 4|4, -, Creature - Hellion, Anthony Francisco, -
|
Hellion, 1, R, 4|4, -, Creature - Hellion, Anthony Francisco, -
|
||||||
Ooze, 4, G, *|*, -, Creature - Ooze, Daniel Ljunggren, -
|
Ooze, 4, G, *|*, -, Creature - Ooze, Daniel Ljunggren, -
|
||||||
Tuktuk The Returned, 5, -, 5|5, -, Legendary Artifact Creature - Goblin Golem, Franz Vohwinkel, -
|
Tuktuk The Returned, 5, -, 5|5, -, Legendary Artifact Creature - Goblin Golem, Franz Vohwinkel, -
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ Soldier, 3, W, 1|1, -, Creature - Soldier, Greg Staples, -
|
||||||
Drake, 4, U, 2|2, -, Creature - Drake, Svetlin Velinov, Flying
|
Drake, 4, U, 2|2, -, Creature - Drake, Svetlin Velinov, Flying
|
||||||
Zombie, 5, B, 2|2, -, Creature - Zombie, Lucas Graciano, -
|
Zombie, 5, B, 2|2, -, Creature - Zombie, Lucas Graciano, -
|
||||||
Goblin, 6, R, 1|1, -, Creature - Goblin, Karl Kopinski, -
|
Goblin, 6, R, 1|1, -, Creature - Goblin, Karl Kopinski, -
|
||||||
Hellion, 7, R, 4|4, -, Creature - Hellion, Anthony Francisco, -
|
Hellion, 1, R, 4|4, -, Creature - Hellion, Anthony Francisco, -
|
||||||
Beast, 8, G, 3|3, -, Creature - Beast, John Donahue, -
|
Beast, 8, G, 3|3, -, Creature - Beast, John Donahue, -
|
||||||
Saproling, 9, G, 1|1, -, Creature - Saproling, Brad Rigney, -
|
Saproling, 9, G, 1|1, -, Creature - Saproling, Brad Rigney, -
|
||||||
Wurm, 10, G, 6|6, -, Creature - Wurm, Anthony Francisco, -
|
Wurm, 10, G, 6|6, -, Creature - Wurm, Anthony Francisco, -
|
||||||
|
@ -664,7 +664,7 @@ DDP - Duel Decks: Zendikar vs. Eldrazi (2015-08-28)
|
||||||
Eldrazi Spawn, 076, -, -, -, Creature - Eldrazi Spawn, Aleksi Briclot, Sacrifice this creature: Add {1} to your mana pool.
|
Eldrazi Spawn, 076, -, -, -, Creature - Eldrazi Spawn, Aleksi Briclot, Sacrifice this creature: Add {1} to your mana pool.
|
||||||
Eldrazi Spawn, 077, -, -, -, Creature - Eldrazi Spawn, Veronique Meignaud, Sacrifice this creature: Add {1} to your mana pool.
|
Eldrazi Spawn, 077, -, -, -, Creature - Eldrazi Spawn, Veronique Meignaud, Sacrifice this creature: Add {1} to your mana pool.
|
||||||
Eldrazi Spawn, 078, -, -, -, Creature - Eldrazi Spawn, Mark Tedin, Sacrifice this creature: Add {1} to your mana pool.
|
Eldrazi Spawn, 078, -, -, -, Creature - Eldrazi Spawn, Mark Tedin, Sacrifice this creature: Add {1} to your mana pool.
|
||||||
Hellion, 079, R, 4|4, -, Creature - Hellion, Anthony Francisco, -
|
Hellion, 1, R, 4|4, -, Creature - Hellion, Anthony Francisco, -
|
||||||
Plant, 080, G, -, -, Creature - Plant, Daren Bader, -
|
Plant, 080, G, -, -, Creature - Plant, Daren Bader, -
|
||||||
|
|
||||||
BFZ - Battle for Zendikar (2015-10-09)
|
BFZ - Battle for Zendikar (2015-10-09)
|
||||||
|
@ -745,3 +745,20 @@ Clue, 015, -, -, -, Artifact - Clue, James Paick, {2}‚ Sacrifice this Artifact
|
||||||
Clue, 016, -, -, -, Artifact - Clue, Franz Vohwinkel, {2}‚ Sacrifice this Artifact: Draw a card.
|
Clue, 016, -, -, -, Artifact - Clue, Franz Vohwinkel, {2}‚ Sacrifice this Artifact: Draw a card.
|
||||||
Jace Emblem, 017, -, -, -, Emblem - Jace, Tyler Jacobson, Whenever an opponent casts his or her first spell each turn<72> counter that spell.
|
Jace Emblem, 017, -, -, -, Emblem - Jace, Tyler Jacobson, Whenever an opponent casts his or her first spell each turn<72> counter that spell.
|
||||||
Arlinn Emblem, 018, -, -, -, Emblem - Arlinn, Winona Nelson, Creatures you control have haste and '{T}: This creature deals damage equal to its power to target creature or player.'
|
Arlinn Emblem, 018, -, -, -, Emblem - Arlinn, Winona Nelson, Creatures you control have haste and '{T}: This creature deals damage equal to its power to target creature or player.'
|
||||||
|
|
||||||
|
|
||||||
|
SWS - Star Wars Custom set
|
||||||
|
|
||||||
|
Rebel, 001, W, 1|1, -, Creature - Rebel, Alex Konstad, -
|
||||||
|
Trooper, 002, W, 1|1, -, Creature - Trooper, Darren Tan, -
|
||||||
|
Tusken Raider, 003, W, 1|1, -, Creature - Tusken Raider, William O'Connor, -
|
||||||
|
Ewok, 004, G, 1|1, -, Creature - Ewok, Chris NG, -
|
||||||
|
Hunter, 005, R, 4|4, -, Creature - Hunter, Steve Argyle, -
|
||||||
|
Royal Guard, 006, R, 2|2, -, Creature - Soldier, Aldo Katayanagi, First Strike
|
||||||
|
AT-AT, 007, -, 5|5, -, Artifact Creature - AT-AT, Prokhoda, When this creature dies<65> create two 1/1 white Trooper creature tokens.
|
||||||
|
B-Wing, 008, -, 1|1, -, Artifact Creature - Rebel Starship, Anthony Devine, Spaceflight
|
||||||
|
Droid, 009, -, 1|1, -, Artifact Creature - Droid, PeetuGee, -
|
||||||
|
TIE Fighter, 010, -, 1|1, -, Artifact Creature - Starship, Darren Tan, Spaceflight
|
||||||
|
Yoda Emblem, 011, -, -, -, Emblem - Yoda, Jerry Vanderstelt, Hexproof<6F> you and your creatures have.
|
||||||
|
Obi-Wan Kenobi Emblem, 012, -, -, -, Emblem - Obi-Wan Kenobi, Jerry Vanderstelt, Creatures you control get +1/+1 and have vigilance<63> first strike<6B> and lifelink.
|
||||||
|
Aurra Sing Emblem, 013, -, -, -, Emblem - Aurra Sing, Willman1701, Whenever a nontoken creature you control leaves the battlefield<6C> discard a card.
|
||||||
|
|
Can't render this file because it contains an unexpected character in line 549 and column 140.
|
|
@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
|
||||||
public final static int MAGE_VERSION_MAJOR = 1;
|
public final static int MAGE_VERSION_MAJOR = 1;
|
||||||
public final static int MAGE_VERSION_MINOR = 4;
|
public final static int MAGE_VERSION_MINOR = 4;
|
||||||
public final static int MAGE_VERSION_PATCH = 26;
|
public final static int MAGE_VERSION_PATCH = 26;
|
||||||
public final static String MAGE_VERSION_MINOR_PATCH = "V3";
|
public final static String MAGE_VERSION_MINOR_PATCH = "V5";
|
||||||
public final static String MAGE_VERSION_INFO = "";
|
public final static String MAGE_VERSION_INFO = "";
|
||||||
|
|
||||||
private final int major;
|
private final int major;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#Generated by Maven
|
#Generated by Maven
|
||||||
#Mon Aug 28 09:53:46 CEST 2017
|
#Fri Sep 15 22:14:29 CEST 2017
|
||||||
version=1.4.26
|
version=1.4.26
|
||||||
groupId=org.mage
|
groupId=org.mage
|
||||||
artifactId=mage-game-pennydreadfulcommanderfreeforall
|
artifactId=mage-game-pennydreadfulcommanderfreeforall
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
package mage.player.ai.ma;
|
package mage.player.ai.ma;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.keyword.HasteAbility;
|
import mage.abilities.keyword.HasteAbility;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.constants.SubType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ubeefx, nantuko
|
* @author ubeefx, nantuko
|
||||||
*/
|
*/
|
||||||
|
@ -104,7 +103,7 @@ public final class ArtificialScoringSystem {
|
||||||
}
|
}
|
||||||
score += equipments * 50 + enchantments * 100;
|
score += equipments * 50 + enchantments * 100;
|
||||||
|
|
||||||
if (!permanent.canAttack(game)) {
|
if (!permanent.canAttack(null, game)) {
|
||||||
score -= 100;
|
score -= 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,19 +25,17 @@
|
||||||
* authors and should not be interpreted as representing official policies, either expressed
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package mage.player.ai;
|
package mage.player.ai;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
import mage.abilities.keyword.DoubleStrikeAbility;
|
import mage.abilities.keyword.DoubleStrikeAbility;
|
||||||
import mage.abilities.keyword.FirstStrikeAbility;
|
import mage.abilities.keyword.FirstStrikeAbility;
|
||||||
import mage.abilities.keyword.TrampleAbility;
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
@ -50,15 +48,16 @@ public class CombatEvaluator {
|
||||||
public int evaluate(Permanent creature, Game game) {
|
public int evaluate(Permanent creature, Game game) {
|
||||||
if (!values.containsKey(creature.getId())) {
|
if (!values.containsKey(creature.getId())) {
|
||||||
int value = 0;
|
int value = 0;
|
||||||
if (creature.canAttack(game))
|
if (creature.canAttack(null, game)) {
|
||||||
value += 2;
|
value += 2;
|
||||||
|
}
|
||||||
value += creature.getPower().getValue();
|
value += creature.getPower().getValue();
|
||||||
value += creature.getToughness().getValue();
|
value += creature.getToughness().getValue();
|
||||||
value += creature.getAbilities().getEvasionAbilities().size();
|
value += creature.getAbilities().getEvasionAbilities().size();
|
||||||
value += creature.getAbilities().getProtectionAbilities().size();
|
value += creature.getAbilities().getProtectionAbilities().size();
|
||||||
value += creature.getAbilities().containsKey(FirstStrikeAbility.getInstance().getId())?1:0;
|
value += creature.getAbilities().containsKey(FirstStrikeAbility.getInstance().getId()) ? 1 : 0;
|
||||||
value += creature.getAbilities().containsKey(DoubleStrikeAbility.getInstance().getId())?2:0;
|
value += creature.getAbilities().containsKey(DoubleStrikeAbility.getInstance().getId()) ? 2 : 0;
|
||||||
value += creature.getAbilities().containsKey(TrampleAbility.getInstance().getId())?1:0;
|
value += creature.getAbilities().containsKey(TrampleAbility.getInstance().getId()) ? 1 : 0;
|
||||||
values.put(creature.getId(), value);
|
values.put(creature.getId(), value);
|
||||||
}
|
}
|
||||||
return values.get(creature.getId());
|
return values.get(creature.getId());
|
||||||
|
|
|
@ -1939,7 +1939,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
|
|
||||||
protected int combatPotential(Permanent creature, Game game) {
|
protected int combatPotential(Permanent creature, Game game) {
|
||||||
log.debug("combatPotential");
|
log.debug("combatPotential");
|
||||||
if (!creature.canAttack(game)) {
|
if (!creature.canAttack(null, game)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int potential = creature.getPower().getValue();
|
int potential = creature.getPower().getValue();
|
||||||
|
|
|
@ -46,6 +46,7 @@ import mage.choices.ChoiceImpl;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import static mage.constants.PlayerAction.REQUEST_AUTO_ANSWER_RESET_ALL;
|
import static mage.constants.PlayerAction.REQUEST_AUTO_ANSWER_RESET_ALL;
|
||||||
import static mage.constants.PlayerAction.TRIGGER_AUTO_ORDER_RESET_ALL;
|
import static mage.constants.PlayerAction.TRIGGER_AUTO_ORDER_RESET_ALL;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
import mage.filter.common.FilterAttackingCreature;
|
import mage.filter.common.FilterAttackingCreature;
|
||||||
import mage.filter.common.FilterBlockingCreature;
|
import mage.filter.common.FilterBlockingCreature;
|
||||||
import mage.filter.common.FilterCreatureForCombat;
|
import mage.filter.common.FilterCreatureForCombat;
|
||||||
|
@ -1055,6 +1056,7 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
updateGameStatePriority("selectAttackers", game);
|
updateGameStatePriority("selectAttackers", game);
|
||||||
FilterCreatureForCombat filter = filterCreatureForCombat.copy();
|
FilterCreatureForCombat filter = filterCreatureForCombat.copy();
|
||||||
filter.add(new ControllerIdPredicate(attackingPlayerId));
|
filter.add(new ControllerIdPredicate(attackingPlayerId));
|
||||||
|
|
||||||
while (!abort) {
|
while (!abort) {
|
||||||
if (passedAllTurns
|
if (passedAllTurns
|
||||||
|| passedUntilEndStepBeforeMyTurn
|
|| passedUntilEndStepBeforeMyTurn
|
||||||
|
@ -1063,13 +1065,15 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
|| passedTurnSkipStack
|
|| passedTurnSkipStack
|
||||||
|| passedUntilEndOfTurn
|
|| passedUntilEndOfTurn
|
||||||
|| passedUntilNextMain))) {
|
|| passedUntilNextMain))) {
|
||||||
|
if (checkIfAttackersValid(game)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Map<String, Serializable> options = new HashMap<>();
|
Map<String, Serializable> options = new HashMap<>();
|
||||||
|
|
||||||
List<UUID> possibleAttackers = new ArrayList<>();
|
List<UUID> possibleAttackers = new ArrayList<>();
|
||||||
for (Permanent possibleAttacker : game.getBattlefield().getActivePermanents(filter, attackingPlayerId, game)) {
|
for (Permanent possibleAttacker : game.getBattlefield().getActivePermanents(filter, attackingPlayerId, game)) {
|
||||||
if (possibleAttacker.canAttack(game)) {
|
if (possibleAttacker.canAttack(null, game)) {
|
||||||
possibleAttackers.add(possibleAttacker.getId());
|
possibleAttackers.add(possibleAttacker.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1108,8 +1112,28 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
// attack selected default defender
|
// attack selected default defender
|
||||||
declareAttacker(attacker.getId(), attackedDefender, game, false);
|
declareAttacker(attacker.getId(), attackedDefender, game, false);
|
||||||
}
|
}
|
||||||
} else if (response.getBoolean() != null) {
|
} else if (response.getInteger() != null) { // F-Key
|
||||||
// check if enough attackers are declared
|
if (checkIfAttackersValid(game)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (response.getBoolean() != null) { // ok button
|
||||||
|
if (checkIfAttackersValid(game)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (response.getUUID() != null) {
|
||||||
|
Permanent attacker = game.getPermanent(response.getUUID());
|
||||||
|
if (attacker != null) {
|
||||||
|
if (filterCreatureForCombat.match(attacker, null, playerId, game)) {
|
||||||
|
selectDefender(game.getCombat().getDefenders(), attacker.getId(), game);
|
||||||
|
} else if (filterAttack.match(attacker, null, playerId, game) && game.getStack().isEmpty()) {
|
||||||
|
removeAttackerIfPossible(game, attacker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkIfAttackersValid(Game game) {
|
||||||
if (!game.getCombat().getCreaturesForcedToAttack().isEmpty()) {
|
if (!game.getCombat().getCreaturesForcedToAttack().isEmpty()) {
|
||||||
if (!game.getCombat().getAttackers().containsAll(game.getCombat().getCreaturesForcedToAttack().keySet())) {
|
if (!game.getCombat().getAttackers().containsAll(game.getCombat().getCreaturesForcedToAttack().keySet())) {
|
||||||
int forcedAttackers = 0;
|
int forcedAttackers = 0;
|
||||||
|
@ -1141,28 +1165,63 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
game.informPlayer(this, sb.insert(0, message)
|
game.informPlayer(this, sb.insert(0, message)
|
||||||
.insert(0, requireToAttack)
|
.insert(0, requireToAttack)
|
||||||
.insert(0, "You have to attack with ").toString());
|
.insert(0, "You have to attack with ").toString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check if enough attackers are declared
|
||||||
|
// check if players have to be attacked
|
||||||
|
Set<UUID> playersToAttackIfAble = new HashSet<>();
|
||||||
|
for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(null, true, game).entrySet()) {
|
||||||
|
RequirementEffect effect = entry.getKey();
|
||||||
|
for (Ability ability : entry.getValue()) {
|
||||||
|
UUID playerToAttack = effect.playerMustBeAttackedIfAble(ability, game);
|
||||||
|
if (playerToAttack != null) {
|
||||||
|
playersToAttackIfAble.add(playerToAttack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!playersToAttackIfAble.isEmpty()) {
|
||||||
|
Set<UUID> checkPlayersToAttackIfAble = new HashSet<>(playersToAttackIfAble);
|
||||||
|
for (CombatGroup combatGroup : game.getCombat().getGroups()) {
|
||||||
|
checkPlayersToAttackIfAble.remove(combatGroup.getDefendingPlayerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UUID forcedToAttackId : checkPlayersToAttackIfAble) {
|
||||||
|
Player forcedToAttack = game.getPlayer(forcedToAttackId);
|
||||||
|
|
||||||
|
for (Permanent attacker : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, getId(), game)) {
|
||||||
|
|
||||||
|
if (game.getContinuousEffects().checkIfThereArePayCostToAttackBlockEffects(
|
||||||
|
GameEvent.getEvent(GameEvent.EventType.DECLARE_ATTACKER,
|
||||||
|
forcedToAttackId, attacker.getId(), attacker.getControllerId()), game)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// if attacker needs a specific defender to attack so select that one instead
|
||||||
|
if (game.getCombat().getCreaturesForcedToAttack().containsKey(attacker.getId())) {
|
||||||
|
Set<UUID> possibleDefenders = game.getCombat().getCreaturesForcedToAttack().get(attacker.getId());
|
||||||
|
if (!possibleDefenders.isEmpty() && !possibleDefenders.contains(forcedToAttackId)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(attacker.getId(), game);
|
||||||
|
if (playersToAttackIfAble.contains(defendingPlayerId)) {
|
||||||
|
// already attacks other player taht has to be attacked
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
return;
|
if (defendingPlayerId != null || attacker.canAttackInPrinciple(forcedToAttackId, game)) {
|
||||||
} else if (response.getInteger() != null) {
|
game.informPlayer(this, "You are forced to attack " + forcedToAttack.getName() + " or a controlled planeswalker e.g. with " + attacker.getIdName() + ".");
|
||||||
return;
|
return false;
|
||||||
} else if (response.getUUID() != null) {
|
|
||||||
Permanent attacker = game.getPermanent(response.getUUID());
|
|
||||||
if (attacker != null) {
|
|
||||||
if (filterCreatureForCombat.match(attacker, null, playerId, game)) {
|
|
||||||
selectDefender(game.getCombat().getDefenders(), attacker.getId(), game);
|
|
||||||
} else if (filterAttack.match(attacker, null, playerId, game) && game.getStack().isEmpty()) {
|
|
||||||
removeAttackerIfPossible(game, attacker);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void removeAttackerIfPossible(Game game, Permanent attacker) {
|
private void removeAttackerIfPossible(Game game, Permanent attacker) {
|
||||||
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(attacker, game).entrySet()) {
|
for (Map.Entry entry : game.getContinuousEffects().getApplicableRequirementEffects(attacker, false, game).entrySet()) {
|
||||||
RequirementEffect effect = (RequirementEffect) entry.getKey();
|
RequirementEffect effect = (RequirementEffect) entry.getKey();
|
||||||
if (effect.mustAttack(game)) {
|
if (effect.mustAttack(game)) {
|
||||||
if (game.getCombat().getMaxAttackers() >= game.getCombat().getCreaturesForcedToAttack().size()
|
if (game.getCombat().getMaxAttackers() >= game.getCombat().getCreaturesForcedToAttack().size()
|
||||||
|
|
|
@ -53,6 +53,7 @@ import mage.filter.predicate.Predicate;
|
||||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.game.events.DamagedPlayerEvent;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetNonlandPermanent;
|
import mage.target.common.TargetNonlandPermanent;
|
||||||
|
@ -86,7 +87,7 @@ public class AdmiralBeckettBrass extends CardImpl {
|
||||||
|
|
||||||
// At the beginning of your end step, gain control of target nonland permanent controlled by a player who was dealt combat damage by three or more Pirates this turn.
|
// At the beginning of your end step, gain control of target nonland permanent controlled by a player who was dealt combat damage by three or more Pirates this turn.
|
||||||
Ability ability = new BeginningOfEndStepTriggeredAbility(new GainControlTargetEffect(Duration.Custom), TargetController.YOU, false);
|
Ability ability = new BeginningOfEndStepTriggeredAbility(new GainControlTargetEffect(Duration.Custom), TargetController.YOU, false);
|
||||||
ability.addTarget(new TargetNonlandPermanent());
|
ability.addTarget(new TargetNonlandPermanent(new FilterNonlandPermanent("nonland permanent controlled by a player who was dealt combat damage by three or more Pirates this turn")));
|
||||||
originalId = ability.getOriginalId();
|
originalId = ability.getOriginalId();
|
||||||
this.addAbility(ability, new DamagedByPiratesWatcher());
|
this.addAbility(ability, new DamagedByPiratesWatcher());
|
||||||
}
|
}
|
||||||
|
@ -137,7 +138,8 @@ class DamagedByPiratesWatcher extends Watcher {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void watch(GameEvent event, Game game) {
|
public void watch(GameEvent event, Game game) {
|
||||||
if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER && event.getFlag()) {
|
if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) {
|
||||||
|
if (((DamagedPlayerEvent) event).isCombatDamage()) {
|
||||||
Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId());
|
Permanent creature = game.getPermanentOrLKIBattlefield(event.getSourceId());
|
||||||
if (creature != null && creature.getSubtype(game).contains(SubType.PIRATE)) {
|
if (creature != null && creature.getSubtype(game).contains(SubType.PIRATE)) {
|
||||||
if (damageSourceIds.keySet().contains(event.getTargetId())) {
|
if (damageSourceIds.keySet().contains(event.getTargetId())) {
|
||||||
|
@ -150,6 +152,7 @@ class DamagedByPiratesWatcher extends Watcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean damagedByEnoughPirates(UUID sourceId, Game game) {
|
public boolean damagedByEnoughPirates(UUID sourceId, Game game) {
|
||||||
return damageSourceIds.keySet().contains(sourceId) && damageSourceIds.get(sourceId).size() > 2;
|
return damageSourceIds.keySet().contains(sourceId) && damageSourceIds.get(sourceId).size() > 2;
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class AdroitHateflayer extends CardImpl {
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
// Whenever Adroit Hateflayer attacks, each opponent loses 2 life.
|
// Whenever Adroit Hateflayer attacks, each opponent loses 2 life.
|
||||||
this.addAbility(new AttacksTriggeredAbility(new LoseLifeOpponentsEffect(2), false));
|
this.addAbility(new AttacksTriggeredAbility(new LoseLifeOpponentsEffect(2), false));
|
||||||
|
|
|
@ -70,6 +70,7 @@ public class AlexiZephyrMage extends CardImpl {
|
||||||
this.power = new MageInt(3);
|
this.power = new MageInt(3);
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
//TODO: Make ability properly copiable
|
||||||
// {X}{U}, {tap}, Discard two cards: Return X target creatures to their owners' hands.
|
// {X}{U}, {tap}, Discard two cards: Return X target creatures to their owners' hands.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl("{X}{U}"));
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl("{X}{U}"));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class AlleyStrangler extends CardImpl {
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
}
|
}
|
||||||
|
|
||||||
public AlleyStrangler(final AlleyStrangler card) {
|
public AlleyStrangler(final AlleyStrangler card) {
|
||||||
|
|
110
Mage.Sets/src/mage/cards/a/AnZerrinRuins.java
Normal file
110
Mage.Sets/src/mage/cards/a/AnZerrinRuins.java
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.a;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.Mode;
|
||||||
|
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
|
||||||
|
import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.TargetController;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class AnZerrinRuins extends CardImpl {
|
||||||
|
|
||||||
|
public AnZerrinRuins(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}");
|
||||||
|
|
||||||
|
// As An-Zerrin Ruins enters the battlefield, choose a creature type.
|
||||||
|
this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.UnboostCreature)));
|
||||||
|
|
||||||
|
// Creatures of the chosen type don't untap during their controllers' untap steps.
|
||||||
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AnZerrinRuinsDontUntapEffect()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnZerrinRuins(final AnZerrinRuins card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnZerrinRuins copy() {
|
||||||
|
return new AnZerrinRuins(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnZerrinRuinsDontUntapEffect extends DontUntapInControllersUntapStepAllEffect {
|
||||||
|
|
||||||
|
public AnZerrinRuinsDontUntapEffect() {
|
||||||
|
super(Duration.WhileOnBattlefield, TargetController.ANY, new FilterCreaturePermanent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnZerrinRuinsDontUntapEffect(final AnZerrinRuinsDontUntapEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnZerrinRuinsDontUntapEffect copy() {
|
||||||
|
return new AnZerrinRuinsDontUntapEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
|
if (super.applies(event, source, game)) {
|
||||||
|
Permanent sourcePerm = game.getPermanent(source.getSourceId());
|
||||||
|
Permanent permanent = game.getPermanent(event.getTargetId());
|
||||||
|
if (permanent != null && sourcePerm != null) {
|
||||||
|
SubType subtype = (SubType) game.getState().getValue(sourcePerm.getId() + "_type");
|
||||||
|
if (permanent.getSubtype(game).contains(subtype)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText(Mode mode) {
|
||||||
|
return "Creatures of the chosen type don't untap during their controllers' untap steps.";
|
||||||
|
}
|
||||||
|
}
|
59
Mage.Sets/src/mage/cards/a/AncientBrontodon.java
Normal file
59
Mage.Sets/src/mage/cards/a/AncientBrontodon.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.a;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author caldover
|
||||||
|
*/
|
||||||
|
public class AncientBrontodon extends CardImpl {
|
||||||
|
|
||||||
|
public AncientBrontodon(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{G}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.DINOSAUR);
|
||||||
|
this.power = new MageInt(9);
|
||||||
|
this.toughness = new MageInt(9);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AncientBrontodon(final AncientBrontodon card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AncientBrontodon copy() {
|
||||||
|
return new AncientBrontodon(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,28 +25,24 @@
|
||||||
* authors and should not be interpreted as representing official policies, either expressed
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package mage.cards.a;
|
package mage.cards.a;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.ActivatedAbilityImpl;
|
import mage.abilities.condition.common.SourceAttackingCondition;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.costs.CostImpl;
|
import mage.abilities.decorator.ConditionalActivatedAbility;
|
||||||
import mage.abilities.costs.mana.ColoredManaCost;
|
|
||||||
import mage.abilities.effects.common.DamageTargetEffect;
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
import mage.abilities.keyword.FlyingAbility;
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.ColoredManaSymbol;
|
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,19 +51,38 @@ import mage.target.common.TargetCreaturePermanent;
|
||||||
*/
|
*/
|
||||||
public class AncientHellkite extends CardImpl {
|
public class AncientHellkite extends CardImpl {
|
||||||
|
|
||||||
|
private final UUID originalId;
|
||||||
|
|
||||||
public AncientHellkite(UUID ownerId, CardSetInfo setInfo) {
|
public AncientHellkite(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}{R}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}{R}");
|
||||||
this.subtype.add(SubType.DRAGON);
|
this.subtype.add(SubType.DRAGON);
|
||||||
|
|
||||||
this.power = new MageInt(6);
|
this.power = new MageInt(6);
|
||||||
this.toughness = new MageInt(6);
|
this.toughness = new MageInt(6);
|
||||||
|
|
||||||
|
//TODO: Make ability properly copiable
|
||||||
this.addAbility(FlyingAbility.getInstance());
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
this.addAbility(new AncientHellkiteAbility());
|
Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{R}"), SourceAttackingCondition.instance);
|
||||||
|
ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls")));
|
||||||
|
originalId = ability.getOriginalId();
|
||||||
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AncientHellkite(final AncientHellkite card) {
|
public AncientHellkite(final AncientHellkite card) {
|
||||||
super(card);
|
super(card);
|
||||||
|
this.originalId = card.originalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void adjustTargets(Ability ability, Game game) {
|
||||||
|
if (ability.getOriginalId().equals(originalId)) {
|
||||||
|
ability.getTargets().clear();
|
||||||
|
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls");
|
||||||
|
UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId());
|
||||||
|
filter.add(new ControllerIdPredicate(defenderId));
|
||||||
|
TargetCreaturePermanent target = new TargetCreaturePermanent(filter);
|
||||||
|
ability.addTarget(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -76,71 +91,3 @@ public class AncientHellkite extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AncientHellkiteAbility extends ActivatedAbilityImpl {
|
|
||||||
|
|
||||||
private static final FilterCreaturePermanent filterTemplate = new FilterCreaturePermanent("creature defending player controls");
|
|
||||||
|
|
||||||
public AncientHellkiteAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new DamageTargetEffect(1));
|
|
||||||
addCost(new AncientHellkiteCost());
|
|
||||||
addManaCost(new ColoredManaCost(ColoredManaSymbol.R));
|
|
||||||
addTarget(new TargetCreaturePermanent(filterTemplate));
|
|
||||||
}
|
|
||||||
|
|
||||||
public AncientHellkiteAbility(final AncientHellkiteAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AncientHellkiteAbility copy() {
|
|
||||||
return new AncientHellkiteAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean activate(Game game, boolean noMana) {
|
|
||||||
UUID defenderId = game.getCombat().getDefenderId(sourceId);
|
|
||||||
if (defenderId != null) {
|
|
||||||
FilterCreaturePermanent filter = filterTemplate.copy();
|
|
||||||
filter.add(new ControllerIdPredicate(defenderId));
|
|
||||||
|
|
||||||
this.getTargets().clear();
|
|
||||||
TargetCreaturePermanent target = new TargetCreaturePermanent(filter);
|
|
||||||
this.addTarget(target);
|
|
||||||
return super.activate(game, noMana);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AncientHellkiteCost extends CostImpl {
|
|
||||||
|
|
||||||
public AncientHellkiteCost() {
|
|
||||||
this.text = "Activate this ability only if Ancient Hellkite is attacking";
|
|
||||||
}
|
|
||||||
|
|
||||||
public AncientHellkiteCost(final AncientHellkiteCost cost) {
|
|
||||||
super(cost);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AncientHellkiteCost copy() {
|
|
||||||
return new AncientHellkiteCost(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
|
||||||
Permanent permanent = game.getPermanent(sourceId);
|
|
||||||
if (permanent != null && permanent.isAttacking()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
|
|
||||||
this.paid = true;
|
|
||||||
return paid;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -69,6 +69,7 @@ public class AngrathsMarauders extends CardImpl {
|
||||||
return new AngrathsMarauders(this);
|
return new AngrathsMarauders(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AngrathsMaraudersEffect extends ReplacementEffectImpl {
|
class AngrathsMaraudersEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
public AngrathsMaraudersEffect() {
|
public AngrathsMaraudersEffect() {
|
||||||
|
@ -100,7 +101,7 @@ class AngrathsMaraudersEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
return event.getSourceId().equals(source.getControllerId());
|
return game.getControllerId(event.getSourceId()).equals(source.getControllerId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
78
Mage.Sets/src/mage/cards/a/AnointedDeacon.java
Normal file
78
Mage.Sets/src/mage/cards/a/AnointedDeacon.java
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.a;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author caldover
|
||||||
|
*/
|
||||||
|
public class AnointedDeacon extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Vampire");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new SubtypePredicate(SubType.VAMPIRE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnointedDeacon(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.VAMPIRE);
|
||||||
|
this.subtype.add(SubType.CLERIC);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
// At the beginning of combat on your turn, you may have target Vampire get +2/+0 until end of turn.
|
||||||
|
Ability ability = new BeginningOfCombatTriggeredAbility(Zone.BATTLEFIELD,
|
||||||
|
new BoostTargetEffect(2, 0, Duration.EndOfTurn).setText("you may have target Vampire get +2/+0 until end of turn"),
|
||||||
|
TargetController.YOU, true, false);
|
||||||
|
ability.addTarget(new TargetCreaturePermanent(filter));
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnointedDeacon(final AnointedDeacon card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnointedDeacon copy() {
|
||||||
|
return new AnointedDeacon(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,7 +49,7 @@ public class AradaraExpress extends CardImpl {
|
||||||
this.toughness = new MageInt(6);
|
this.toughness = new MageInt(6);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
// Crew 4
|
// Crew 4
|
||||||
this.addAbility(new CrewAbility(4));
|
this.addAbility(new CrewAbility(4));
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class AshesOfTheAbhorrent extends CardImpl {
|
||||||
public AshesOfTheAbhorrent(UUID ownerId, CardSetInfo setInfo) {
|
public AshesOfTheAbhorrent(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
|
||||||
|
|
||||||
// Players can't cast spells from graveyards or activate abilities from graveyards.
|
// Players can't cast spells from graveyards or activate abilities of cards in graveyards.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AshesOfTheAbhorrentEffect()));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AshesOfTheAbhorrentEffect()));
|
||||||
|
|
||||||
// Whenever a creature dies, you gain 1 life.
|
// Whenever a creature dies, you gain 1 life.
|
||||||
|
@ -73,7 +73,7 @@ class AshesOfTheAbhorrentEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
public AshesOfTheAbhorrentEffect() {
|
public AshesOfTheAbhorrentEffect() {
|
||||||
super(Duration.WhileOnBattlefield, Outcome.Neutral);
|
super(Duration.WhileOnBattlefield, Outcome.Neutral);
|
||||||
staticText = "Players can't cast spells from graveyards or activate abilities from graveyards";
|
staticText = "Players can't cast spells from graveyards or activate abilities of cards in graveyards";
|
||||||
}
|
}
|
||||||
|
|
||||||
public AshesOfTheAbhorrentEffect(final AshesOfTheAbhorrentEffect effect) {
|
public AshesOfTheAbhorrentEffect(final AshesOfTheAbhorrentEffect effect) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class AtarkaPummeler extends CardImpl {
|
||||||
// <i>Formidable</i> - {3}{R}{R}: Creatures you control gain menace until end of turn. Activate this ability only if creature you control have total power 8 or greater. (They can't be blocked except by two or more creatures.)
|
// <i>Formidable</i> - {3}{R}{R}: Creatures you control gain menace until end of turn. Activate this ability only if creature you control have total power 8 or greater. (They can't be blocked except by two or more creatures.)
|
||||||
Ability ability = new ActivateIfConditionActivatedAbility(
|
Ability ability = new ActivateIfConditionActivatedAbility(
|
||||||
Zone.BATTLEFIELD,
|
Zone.BATTLEFIELD,
|
||||||
new GainAbilityAllEffect(MenaceAbility.getInstance(), Duration.EndOfTurn, filter),
|
new GainAbilityAllEffect(new MenaceAbility(), Duration.EndOfTurn, filter),
|
||||||
new ManaCostsImpl("{3}{R}{R}"),
|
new ManaCostsImpl("{3}{R}{R}"),
|
||||||
FormidableCondition.instance);
|
FormidableCondition.instance);
|
||||||
ability.setAbilityWord(AbilityWord.FORMIDABLE);
|
ability.setAbilityWord(AbilityWord.FORMIDABLE);
|
||||||
|
|
|
@ -35,14 +35,11 @@ import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
import mage.abilities.keyword.DoubleStrikeAbility;
|
import mage.abilities.keyword.DoubleStrikeAbility;
|
||||||
import mage.abilities.keyword.FlyingAbility;
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
import mage.abilities.keyword.TrampleAbility;
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
import mage.abilities.text.TextPartSubType;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||||
import mage.filter.predicate.mageobject.TextPartSubtypePredicate;
|
|
||||||
import mage.filter.predicate.permanent.TappedPredicate;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
@ -68,11 +65,7 @@ public class AtarkaWorldRender extends CardImpl {
|
||||||
this.addAbility(TrampleAbility.getInstance());
|
this.addAbility(TrampleAbility.getInstance());
|
||||||
|
|
||||||
// Whenever a Dragon you control attacks, it gains double strike until end of turn.
|
// Whenever a Dragon you control attacks, it gains double strike until end of turn.
|
||||||
TextPartSubType textPart1 = (TextPartSubType) addTextPart(new TextPartSubType(SubType.DRAGON));
|
this.addAbility(new AtarkaWorldRenderEffect());
|
||||||
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Dragon you control");
|
|
||||||
filter.add(new TextPartSubtypePredicate(textPart1));
|
|
||||||
filter.add(Predicates.not(new TappedPredicate()));
|
|
||||||
this.addAbility(new AtarkaWorldRenderEffect(filter));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,16 +81,18 @@ public class AtarkaWorldRender extends CardImpl {
|
||||||
|
|
||||||
class AtarkaWorldRenderEffect extends TriggeredAbilityImpl {
|
class AtarkaWorldRenderEffect extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
FilterControlledCreaturePermanent filter;
|
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("dragon you control");
|
||||||
|
|
||||||
public AtarkaWorldRenderEffect(FilterControlledCreaturePermanent filter) {
|
static {
|
||||||
|
filter.add(new SubtypePredicate(SubType.DRAGON));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AtarkaWorldRenderEffect() {
|
||||||
super(Zone.BATTLEFIELD, new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn));
|
super(Zone.BATTLEFIELD, new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn));
|
||||||
this.filter = filter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtarkaWorldRenderEffect(final AtarkaWorldRenderEffect ability) {
|
public AtarkaWorldRenderEffect(final AtarkaWorldRenderEffect ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.filter = ability.filter.copy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
84
Mage.Sets/src/mage/cards/a/AtzocanArcher.java
Normal file
84
Mage.Sets/src/mage/cards/a/AtzocanArcher.java
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.a;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.FightTargetSourceEffect;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.abilities.keyword.ReachAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.permanent.AnotherPredicate;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class AtzocanArcher extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new AnotherPredicate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AtzocanArcher(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.subtype.add(SubType.ARCHER);
|
||||||
|
this.power = new MageInt(1);
|
||||||
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
// Reach
|
||||||
|
this.addAbility(ReachAbility.getInstance());
|
||||||
|
|
||||||
|
// When Atzocan Archer enters the battlefield, you may have it fight another target creature.
|
||||||
|
Effect effect = new FightTargetSourceEffect();
|
||||||
|
effect.setText("you may have it fight another target creature");
|
||||||
|
Ability ability = new EntersBattlefieldTriggeredAbility(effect, true);
|
||||||
|
ability.addTarget(new TargetCreaturePermanent(filter));
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AtzocanArcher(final AtzocanArcher card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AtzocanArcher copy() {
|
||||||
|
return new AtzocanArcher(this);
|
||||||
|
}
|
||||||
|
}
|
113
Mage.Sets/src/mage/cards/b/Backslide.java
Normal file
113
Mage.Sets/src/mage/cards/b/Backslide.java
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.b;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureAllEffect;
|
||||||
|
import mage.abilities.keyword.CyclingAbility;
|
||||||
|
import mage.abilities.keyword.MorphAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.Predicate;
|
||||||
|
import mage.filter.predicate.Predicates;
|
||||||
|
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||||
|
import mage.filter.predicate.permanent.PermanentIdPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.target.Target;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class Backslide extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with a morph ability");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new AbilityPredicate(MorphAbility.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Backslide(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
|
||||||
|
|
||||||
|
// Turn target creature with a morph ability face down.
|
||||||
|
this.getSpellAbility().addEffect(new BackslideEffect());
|
||||||
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
|
||||||
|
|
||||||
|
// Cycling {U}
|
||||||
|
this.addAbility(new CyclingAbility(new ManaCostsImpl("{U}")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Backslide(final Backslide card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Backslide copy() {
|
||||||
|
return new Backslide(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BackslideEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
BackslideEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
this.staticText = "Turn target creature with a morph ability face down.";
|
||||||
|
}
|
||||||
|
|
||||||
|
BackslideEffect(final BackslideEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BackslideEffect copy() {
|
||||||
|
return new BackslideEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Predicate pred = new PermanentIdPredicate(UUID.randomUUID());
|
||||||
|
for (Target target : source.getTargets()) {
|
||||||
|
for (UUID targetId : target.getTargets()) {
|
||||||
|
pred = Predicates.or(pred, new PermanentIdPredicate(targetId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||||
|
filter.add(pred);
|
||||||
|
game.addEffect(new BecomesFaceDownCreatureAllEffect(filter), source);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,7 +52,7 @@ public class BehindTheScenes extends CardImpl {
|
||||||
|
|
||||||
// Creatures you control have skulk.
|
// Creatures you control have skulk.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||||
new GainAbilityControlledEffect(SkulkAbility.getInstance(), Duration.WhileOnBattlefield, FILTER_PERMANENT_CREATURES)));
|
new GainAbilityControlledEffect(new SkulkAbility(), Duration.WhileOnBattlefield, FILTER_PERMANENT_CREATURES)));
|
||||||
|
|
||||||
// {4}{W}: Creatures you control get +1/+1 until end of turn.
|
// {4}{W}: Creatures you control get +1/+1 until end of turn.
|
||||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||||
|
|
|
@ -37,7 +37,7 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +54,7 @@ public class BelligerentBrontodon extends CardImpl {
|
||||||
this.toughness = new MageInt(6);
|
this.toughness = new MageInt(6);
|
||||||
|
|
||||||
// Each creature you control assigns combat damage equal to its toughness rather than its power.
|
// Each creature you control assigns combat damage equal to its toughness rather than its power.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MilitantDinosaurCombatDamageRuleEffect()));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BelligerentBrontodonCombatDamageRuleEffect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BelligerentBrontodon(final BelligerentBrontodon card) {
|
public BelligerentBrontodon(final BelligerentBrontodon card) {
|
||||||
|
@ -67,31 +67,27 @@ public class BelligerentBrontodon extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MilitantDinosaurCombatDamageRuleEffect extends ContinuousEffectImpl {
|
class BelligerentBrontodonCombatDamageRuleEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
public BelligerentBrontodonCombatDamageRuleEffect() {
|
||||||
|
|
||||||
static {
|
|
||||||
filter.add(new ControllerPredicate(TargetController.YOU));
|
|
||||||
}
|
|
||||||
|
|
||||||
public MilitantDinosaurCombatDamageRuleEffect() {
|
|
||||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||||
staticText = "Each creature you control assigns combat damage equal to its toughness rather than its power";
|
staticText = "Each creature you control assigns combat damage equal to its toughness rather than its power";
|
||||||
}
|
}
|
||||||
|
|
||||||
public MilitantDinosaurCombatDamageRuleEffect(final MilitantDinosaurCombatDamageRuleEffect effect) {
|
public BelligerentBrontodonCombatDamageRuleEffect(final BelligerentBrontodonCombatDamageRuleEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MilitantDinosaurCombatDamageRuleEffect copy() {
|
public BelligerentBrontodonCombatDamageRuleEffect copy() {
|
||||||
return new MilitantDinosaurCombatDamageRuleEffect(this);
|
return new BelligerentBrontodonCombatDamageRuleEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||||
// Change the rule
|
// Change the rule
|
||||||
|
FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||||
|
filter.add(new ControllerIdPredicate(source.getControllerId()));
|
||||||
game.getCombat().setUseToughnessForDamage(true);
|
game.getCombat().setUseToughnessForDamage(true);
|
||||||
game.getCombat().addUseToughnessForDamageFilter(filter);
|
game.getCombat().addUseToughnessForDamageFilter(filter);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class BelligerentSliver extends CardImpl {
|
||||||
this.toughness = new MageInt(2);
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
// Sliver creatures you control have menace. (They can't be blocked except by two or more creatures.)"
|
// Sliver creatures you control have menace. (They can't be blocked except by two or more creatures.)"
|
||||||
Effect effect = new GainAbilityAllEffect(MenaceAbility.getInstance(), Duration.WhileOnBattlefield, filter);
|
Effect effect = new GainAbilityAllEffect(new MenaceAbility(), Duration.WhileOnBattlefield, filter);
|
||||||
effect.setText("Sliver creatures you control have menace. (They can't be blocked except by two or more creatures.)");
|
effect.setText("Sliver creatures you control have menace. (They can't be blocked except by two or more creatures.)");
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ import mage.abilities.keyword.VigilanceAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.ComparisonType;
|
import mage.constants.ComparisonType;
|
||||||
|
import mage.constants.SubType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.common.FilterCreatureCard;
|
import mage.filter.common.FilterCreatureCard;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
|
@ -69,7 +69,8 @@ public class BishopOfRebirth extends CardImpl {
|
||||||
this.addAbility(VigilanceAbility.getInstance());
|
this.addAbility(VigilanceAbility.getInstance());
|
||||||
|
|
||||||
// Whenever Bishop of Rebirth attacks, you may return target creature card with converted mana cost 3 or less from your graveyard to the battlefield.
|
// Whenever Bishop of Rebirth attacks, you may return target creature card with converted mana cost 3 or less from your graveyard to the battlefield.
|
||||||
Ability ability = new AttacksTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), true);
|
Ability ability = new AttacksTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()
|
||||||
|
.setText("you may return target creature card with converted mana cost 3 or less from your graveyard to the battlefield"), true);
|
||||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,15 +33,15 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||||
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
import mage.constants.TargetController;
|
import mage.constants.TargetController;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||||
import mage.target.TargetPlayer;
|
import mage.target.common.TargetOpponent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -64,9 +64,9 @@ public class BishopOfTheBloodstained extends CardImpl {
|
||||||
this.power = new MageInt(3);
|
this.power = new MageInt(3);
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
// When Bishop of the Bloodstained enters the battlefield, target player loses 1 life for each vampire you control.
|
// When Bishop of the Bloodstained enters the battlefield, target opponent loses 1 life for each vampire you control.
|
||||||
Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(new PermanentsOnBattlefieldCount(filter)));
|
Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(new PermanentsOnBattlefieldCount(filter)));
|
||||||
ability.addTarget(new TargetPlayer());
|
ability.addTarget(new TargetOpponent());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
65
Mage.Sets/src/mage/cards/b/BishopsSoldier.java
Normal file
65
Mage.Sets/src/mage/cards/b/BishopsSoldier.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.cards.b;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.abilities.keyword.LifelinkAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class BishopsSoldier extends CardImpl {
|
||||||
|
|
||||||
|
public BishopsSoldier(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.VAMPIRE);
|
||||||
|
this.subtype.add(SubType.SOLDIER);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
// Lifelink
|
||||||
|
this.addAbility(LifelinkAbility.getInstance());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public BishopsSoldier(final BishopsSoldier card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BishopsSoldier copy() {
|
||||||
|
return new BishopsSoldier(this);
|
||||||
|
}
|
||||||
|
}
|
81
Mage.Sets/src/mage/cards/b/BlightKeeper.java
Normal file
81
Mage.Sets/src/mage/cards/b/BlightKeeper.java
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.b;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.common.GainLifeEffect;
|
||||||
|
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.target.common.TargetOpponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class BlightKeeper extends CardImpl {
|
||||||
|
|
||||||
|
public BlightKeeper(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.BAT);
|
||||||
|
this.subtype.add(SubType.IMP);
|
||||||
|
this.power = new MageInt(1);
|
||||||
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
|
// {7}{B}, {T}, Sacrifice Blight Keeper: Target opponent loses 4 life and you gain 4 life.
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseLifeTargetEffect(4), new ManaCostsImpl("{7}{B}"));
|
||||||
|
ability.addEffect(new GainLifeEffect(4).setText("and you gain 4 life"));
|
||||||
|
ability.addTarget(new TargetOpponent());
|
||||||
|
ability.addCost(new TapSourceCost());
|
||||||
|
ability.addCost(new SacrificeSourceCost());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlightKeeper(final BlightKeeper card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlightKeeper copy() {
|
||||||
|
return new BlightKeeper(this);
|
||||||
|
}
|
||||||
|
}
|
64
Mage.Sets/src/mage/cards/b/BlindingFog.java
Normal file
64
Mage.Sets/src/mage/cards/b/BlindingFog.java
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.b;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.effects.common.PreventAllDamageToAllEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||||
|
import mage.abilities.keyword.HexproofAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE;
|
||||||
|
import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class BlindingFog extends CardImpl {
|
||||||
|
|
||||||
|
public BlindingFog(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}");
|
||||||
|
|
||||||
|
// Prevent all damage that would be dealt to creatures this turn.
|
||||||
|
this.getSpellAbility().addEffect(new PreventAllDamageToAllEffect(Duration.EndOfTurn, FILTER_PERMANENT_CREATURES));
|
||||||
|
// Creatures you control gain hexproof until end of turn.
|
||||||
|
this.getSpellAbility().addEffect(new GainAbilityControlledEffect(HexproofAbility.getInstance(), Duration.EndOfTurn, FILTER_PERMANENT_CREATURE, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlindingFog(final BlindingFog card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlindingFog copy() {
|
||||||
|
return new BlindingFog(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,7 +60,7 @@ public class BloodChinRager extends CardImpl {
|
||||||
this.toughness = new MageInt(2);
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
// Whenever Blood-Chin Rager attacks, Warrior creatures you control gain menace until end of turn. (They can't be blocked except by two or more creatures.)
|
// Whenever Blood-Chin Rager attacks, Warrior creatures you control gain menace until end of turn. (They can't be blocked except by two or more creatures.)
|
||||||
this.addAbility(new AttacksTriggeredAbility(new GainAbilityAllEffect(MenaceAbility.getInstance(), Duration.EndOfTurn, filter), false));
|
this.addAbility(new AttacksTriggeredAbility(new GainAbilityAllEffect(new MenaceAbility(), Duration.EndOfTurn, filter), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BloodChinRager(final BloodChinRager card) {
|
public BloodChinRager(final BloodChinRager card) {
|
||||||
|
|
145
Mage.Sets/src/mage/cards/b/BloodOath.java
Normal file
145
Mage.Sets/src/mage/cards/b/BloodOath.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.cards.b;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageObject;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.cards.Cards;
|
||||||
|
import mage.choices.Choice;
|
||||||
|
import mage.choices.ChoiceImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class BloodOath extends CardImpl {
|
||||||
|
|
||||||
|
public BloodOath(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}");
|
||||||
|
|
||||||
|
// Choose a card type. Target opponent reveals his or her hand. Blood Oath deals 3 damage to that player for each card of the chosen type revealed this way.
|
||||||
|
this.getSpellAbility().addEffect(new BloodOathEffect());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BloodOath(final BloodOath card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BloodOath copy() {
|
||||||
|
return new BloodOath(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BloodOathEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
private static final Set<String> choice = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
choice.add(CardType.ARTIFACT.toString());
|
||||||
|
choice.add(CardType.CREATURE.toString());
|
||||||
|
choice.add(CardType.ENCHANTMENT.toString());
|
||||||
|
choice.add(CardType.INSTANT.toString());
|
||||||
|
choice.add(CardType.LAND.toString());
|
||||||
|
choice.add(CardType.PLANESWALKER.toString());
|
||||||
|
choice.add(CardType.SORCERY.toString());
|
||||||
|
choice.add(CardType.TRIBAL.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BloodOathEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
staticText = "Choose a card type. Target opponent reveals his or her hand. {this} deals 3 damage to that player for each card of the chosen type revealed this way";
|
||||||
|
}
|
||||||
|
|
||||||
|
public BloodOathEffect(final BloodOathEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BloodOathEffect copy() {
|
||||||
|
return new BloodOathEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||||
|
Player player = game.getPlayer(source.getControllerId());
|
||||||
|
Player opponent = game.getPlayer(source.getFirstTarget());
|
||||||
|
if (player != null && opponent != null && sourceObject != null) {
|
||||||
|
Choice choiceImpl = new ChoiceImpl();
|
||||||
|
choiceImpl.setChoices(choice);
|
||||||
|
while (player.canRespond() && !player.choose(Outcome.Neutral, choiceImpl, game)) {
|
||||||
|
}
|
||||||
|
CardType type = null;
|
||||||
|
String choosenType = choiceImpl.getChoice();
|
||||||
|
|
||||||
|
if (choosenType.equals(CardType.ARTIFACT.toString())) {
|
||||||
|
type = CardType.ARTIFACT;
|
||||||
|
} else if (choosenType.equals(CardType.LAND.toString())) {
|
||||||
|
type = CardType.LAND;
|
||||||
|
} else if (choosenType.equals(CardType.CREATURE.toString())) {
|
||||||
|
type = CardType.CREATURE;
|
||||||
|
} else if (choosenType.equals(CardType.ENCHANTMENT.toString())) {
|
||||||
|
type = CardType.ENCHANTMENT;
|
||||||
|
} else if (choosenType.equals(CardType.INSTANT.toString())) {
|
||||||
|
type = CardType.INSTANT;
|
||||||
|
} else if (choosenType.equals(CardType.SORCERY.toString())) {
|
||||||
|
type = CardType.SORCERY;
|
||||||
|
} else if (choosenType.equals(CardType.PLANESWALKER.toString())) {
|
||||||
|
type = CardType.PLANESWALKER;
|
||||||
|
} else if (choosenType.equals(CardType.TRIBAL.toString())) {
|
||||||
|
type = CardType.TRIBAL;
|
||||||
|
}
|
||||||
|
if (type != null) {
|
||||||
|
Cards hand = opponent.getHand();
|
||||||
|
opponent.revealCards(sourceObject.getIdName(), hand, game);
|
||||||
|
Set<Card> cards = hand.getCards(game);
|
||||||
|
int count = 0;
|
||||||
|
for (Card card : cards) {
|
||||||
|
if (card != null && card.getCardType().contains(type)) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opponent.damage(count * 3, source.getSourceId(), game, false, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,7 +85,7 @@ public class BloodbondMarch extends CardImpl {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spell spell = (Spell) game.getStack().getStackObject(targetPointer.getFirst(game, source));
|
Spell spell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
|
||||||
|
|
||||||
if (spell == null) {
|
if (spell == null) {
|
||||||
return false;
|
return false;
|
||||||
|
|
70
Mage.Sets/src/mage/cards/b/BlossomDryad.java
Normal file
70
Mage.Sets/src/mage/cards/b/BlossomDryad.java
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.b;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.effects.common.UntapTargetEffect;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.target.common.TargetLandPermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class BlossomDryad extends CardImpl {
|
||||||
|
|
||||||
|
public BlossomDryad(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.DRYAD);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
// {t}: Untap target land.
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapTargetEffect(), new TapSourceCost());
|
||||||
|
ability.addTarget(new TargetLandPermanent());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlossomDryad(final BlossomDryad card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlossomDryad copy() {
|
||||||
|
return new BlossomDryad(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,7 +60,7 @@ public class BobaFett extends CardImpl {
|
||||||
this.toughness = new MageInt(4);
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
// Deathtouch
|
// Deathtouch
|
||||||
this.addAbility(DeathtouchAbility.getInstance());
|
this.addAbility(DeathtouchAbility.getInstance());
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class BoggartBrute extends CardImpl {
|
||||||
this.toughness = new MageInt(2);
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoggartBrute(final BoggartBrute card) {
|
public BoggartBrute(final BoggartBrute card) {
|
||||||
|
|
65
Mage.Sets/src/mage/cards/b/BondedHorncrest.java
Normal file
65
Mage.Sets/src/mage/cards/b/BondedHorncrest.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.cards.b;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.keyword.CantAttackAloneAbility;
|
||||||
|
import mage.abilities.keyword.CantBlockAloneAbility;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class BondedHorncrest extends CardImpl {
|
||||||
|
|
||||||
|
public BondedHorncrest(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.DINOSAUR);
|
||||||
|
this.power = new MageInt(5);
|
||||||
|
this.toughness = new MageInt(5);
|
||||||
|
|
||||||
|
// Bonded Horncrest can't attack or block alone.
|
||||||
|
this.addAbility(new CantAttackAloneAbility());
|
||||||
|
this.addAbility(CantBlockAloneAbility.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BondedHorncrest(final BondedHorncrest card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BondedHorncrest copy() {
|
||||||
|
return new BondedHorncrest(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,7 +65,7 @@ public class BontuTheGlorified extends CardImpl {
|
||||||
this.toughness = new MageInt(6);
|
this.toughness = new MageInt(6);
|
||||||
|
|
||||||
//Menace
|
//Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
//Indestructible
|
//Indestructible
|
||||||
this.addAbility(IndestructibleAbility.getInstance());
|
this.addAbility(IndestructibleAbility.getInstance());
|
||||||
|
|
|
@ -48,7 +48,7 @@ import mage.players.Player;
|
||||||
public class BounteousKirin extends CardImpl {
|
public class BounteousKirin extends CardImpl {
|
||||||
|
|
||||||
public BounteousKirin(UUID ownerId, CardSetInfo setInfo) {
|
public BounteousKirin(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{G}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}");
|
||||||
addSuperType(SuperType.LEGENDARY);
|
addSuperType(SuperType.LEGENDARY);
|
||||||
this.subtype.add(SubType.KIRIN, SubType.SPIRIT);
|
this.subtype.add(SubType.KIRIN, SubType.SPIRIT);
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class BounteousKirinEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getState().getStack().getSpell(getTargetPointer().getFirst(game, source));
|
Spell spell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
|
|
63
Mage.Sets/src/mage/cards/b/BrightReprisal.java
Normal file
63
Mage.Sets/src/mage/cards/b/BrightReprisal.java
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.b;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.target.common.TargetAttackingCreature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class BrightReprisal extends CardImpl {
|
||||||
|
|
||||||
|
public BrightReprisal(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{W}");
|
||||||
|
|
||||||
|
// Destroy target attacking creature.
|
||||||
|
this.getSpellAbility().addEffect(new DestroyTargetEffect());
|
||||||
|
this.getSpellAbility().addTarget(new TargetAttackingCreature());
|
||||||
|
|
||||||
|
// Draw a card.
|
||||||
|
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BrightReprisal(final BrightReprisal card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BrightReprisal copy() {
|
||||||
|
return new BrightReprisal(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,13 +29,13 @@ package mage.cards.b;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
|
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.Cost;
|
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.LookLibraryControllerEffect;
|
import mage.abilities.effects.common.LookLibraryControllerEffect;
|
||||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||||
|
@ -43,6 +43,7 @@ import mage.abilities.keyword.FirstStrikeAbility;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
@ -55,7 +56,7 @@ import mage.players.Player;
|
||||||
public class BrutalDeceiver extends CardImpl {
|
public class BrutalDeceiver extends CardImpl {
|
||||||
|
|
||||||
public BrutalDeceiver(UUID ownerId, CardSetInfo setInfo) {
|
public BrutalDeceiver(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
|
||||||
this.subtype.add(SubType.SPIRIT);
|
this.subtype.add(SubType.SPIRIT);
|
||||||
|
|
||||||
this.power = new MageInt(2);
|
this.power = new MageInt(2);
|
||||||
|
@ -65,9 +66,7 @@ public class BrutalDeceiver extends CardImpl {
|
||||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(), new GenericManaCost(1)));
|
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new LookLibraryControllerEffect(), new GenericManaCost(1)));
|
||||||
|
|
||||||
// {2}: Reveal the top card of your library. If it's a land card, {this} gets +1/+0 and gains first strike until end of turn.
|
// {2}: Reveal the top card of your library. If it's a land card, {this} gets +1/+0 and gains first strike until end of turn.
|
||||||
Ability ability = new BrutalDeceiverAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{2}"));
|
this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new BrutalDeceiverEffect(), new ManaCostsImpl("{2}")));
|
||||||
ability.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn));
|
|
||||||
this.addAbility(ability);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BrutalDeceiver(final BrutalDeceiver card) {
|
public BrutalDeceiver(final BrutalDeceiver card) {
|
||||||
|
@ -80,38 +79,39 @@ public class BrutalDeceiver extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BrutalDeceiverAbility extends LimitedTimesPerTurnActivatedAbility {
|
class BrutalDeceiverEffect extends OneShotEffect {
|
||||||
|
|
||||||
public BrutalDeceiverAbility(Zone zone, Effect effect, Cost cost) {
|
public BrutalDeceiverEffect() {
|
||||||
super(zone, effect, cost);
|
super(Outcome.BoostCreature);
|
||||||
|
this.staticText = "Reveal the top card of your library. If it's a land card, {this} gets +1/+0 and gains first strike until end of turn";
|
||||||
}
|
}
|
||||||
|
|
||||||
public BrutalDeceiverAbility(BrutalDeceiverAbility ability) {
|
public BrutalDeceiverEffect(final BrutalDeceiverEffect effect) {
|
||||||
super(ability);
|
super(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BrutalDeceiverAbility copy() {
|
public BrutalDeceiverEffect copy() {
|
||||||
return new BrutalDeceiverAbility(this);
|
return new BrutalDeceiverEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkIfClause(Game game) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player player = game.getPlayer(this.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (player != null) {
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
|
if (controller != null && sourceObject != null) {
|
||||||
Cards cards = new CardsImpl();
|
Cards cards = new CardsImpl();
|
||||||
Card card = player.getLibrary().getFromTop(game);
|
Card card = controller.getLibrary().getFromTop(game);
|
||||||
|
if (card != null) {
|
||||||
cards.add(card);
|
cards.add(card);
|
||||||
player.revealCards("Brutal Deceiver", cards, game);
|
controller.revealCards(sourceObject.getIdName(), cards, game);
|
||||||
if (card != null && card.isLand()) {
|
if (card.isLand()) {
|
||||||
return true;
|
game.addEffect(new BoostSourceEffect(1, 0, Duration.EndOfTurn), source);
|
||||||
|
game.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "{2}: Reveal the top card of your library. If it's a land card, {this} gets +1/+0 and gains first strike until end of turn. Activate this ability only once each turn.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ public class BullRancor extends CardImpl {
|
||||||
|
|
||||||
// As long as Bull Rancor is monstrous, creatures you control have menace.
|
// As long as Bull Rancor is monstrous, creatures you control have menace.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
|
||||||
new GainAbilityControlledEffect(MenaceAbility.getInstance(), Duration.WhileOnBattlefield),
|
new GainAbilityControlledEffect(new MenaceAbility(), Duration.WhileOnBattlefield),
|
||||||
MonstrousCondition.instance,
|
MonstrousCondition.instance,
|
||||||
"As long as Bull Rancor is monstrous, creatures you control have menace")
|
"As long as Bull Rancor is monstrous, creatures you control have menace")
|
||||||
));
|
));
|
||||||
|
|
|
@ -52,11 +52,10 @@ import mage.target.common.TargetCardInYourGraveyard;
|
||||||
*
|
*
|
||||||
* @author cbt33
|
* @author cbt33
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class CabalInquisitor extends CardImpl {
|
public class CabalInquisitor extends CardImpl {
|
||||||
|
|
||||||
public CabalInquisitor(UUID ownerId, CardSetInfo setInfo) {
|
public CabalInquisitor(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
|
||||||
this.subtype.add(SubType.HUMAN);
|
this.subtype.add(SubType.HUMAN);
|
||||||
this.subtype.add(SubType.MINION);
|
this.subtype.add(SubType.MINION);
|
||||||
|
|
||||||
|
@ -82,11 +81,8 @@ public class CabalInquisitor extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ActivateAsSorceryConditionalActivatedAbility extends ActivatedAbilityImpl {
|
class ActivateAsSorceryConditionalActivatedAbility extends ActivatedAbilityImpl {
|
||||||
|
|
||||||
private Condition condition;
|
|
||||||
|
|
||||||
private static final Effects emptyEffects = new Effects();
|
private static final Effects emptyEffects = new Effects();
|
||||||
|
|
||||||
public ActivateAsSorceryConditionalActivatedAbility(Zone zone, Effect effect, ManaCosts cost, Condition condition) {
|
public ActivateAsSorceryConditionalActivatedAbility(Zone zone, Effect effect, ManaCosts cost, Condition condition) {
|
||||||
|
@ -95,10 +91,8 @@ class ActivateAsSorceryConditionalActivatedAbility extends ActivatedAbilityImpl
|
||||||
timing = TimingRule.SORCERY;
|
timing = TimingRule.SORCERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ActivateAsSorceryConditionalActivatedAbility(final ActivateAsSorceryConditionalActivatedAbility ability) {
|
public ActivateAsSorceryConditionalActivatedAbility(final ActivateAsSorceryConditionalActivatedAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.condition = ability.condition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -109,14 +103,6 @@ class ActivateAsSorceryConditionalActivatedAbility extends ActivatedAbilityImpl
|
||||||
return super.getEffects(game, effectType);
|
return super.getEffects(game, effectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canActivate(UUID playerId, Game game) {
|
|
||||||
if (!condition.apply(game, this)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return super.canActivate(playerId, game);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActivateAsSorceryConditionalActivatedAbility copy() {
|
public ActivateAsSorceryConditionalActivatedAbility copy() {
|
||||||
return new ActivateAsSorceryConditionalActivatedAbility(this);
|
return new ActivateAsSorceryConditionalActivatedAbility(this);
|
||||||
|
|
|
@ -56,7 +56,7 @@ import mage.players.Player;
|
||||||
public class CallousDeceiver extends CardImpl {
|
public class CallousDeceiver extends CardImpl {
|
||||||
|
|
||||||
public CallousDeceiver(UUID ownerId, CardSetInfo setInfo) {
|
public CallousDeceiver(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
|
||||||
this.subtype.add(SubType.SPIRIT);
|
this.subtype.add(SubType.SPIRIT);
|
||||||
|
|
||||||
this.power = new MageInt(1);
|
this.power = new MageInt(1);
|
||||||
|
|
|
@ -53,6 +53,7 @@ public class CandelabraOfTawnos extends CardImpl {
|
||||||
public CandelabraOfTawnos(UUID ownerId, CardSetInfo setInfo) {
|
public CandelabraOfTawnos(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}");
|
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}");
|
||||||
|
|
||||||
|
//TODO: Make ability properly copiable
|
||||||
// {X}, {T}: Untap X target lands.
|
// {X}, {T}: Untap X target lands.
|
||||||
Effect effect = new UntapTargetEffect();
|
Effect effect = new UntapTargetEffect();
|
||||||
effect.setText("untap X target lands");
|
effect.setText("untap X target lands");
|
||||||
|
|
|
@ -66,13 +66,13 @@ public class CaterwaulingBoggart extends CardImpl {
|
||||||
|
|
||||||
// Each Goblin you control has menace. (They can't be blocked except by two or more creatures.)
|
// Each Goblin you control has menace. (They can't be blocked except by two or more creatures.)
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(
|
||||||
MenaceAbility.getInstance(),
|
new MenaceAbility(),
|
||||||
Duration.WhileOnBattlefield, filterGoblin,
|
Duration.WhileOnBattlefield, filterGoblin,
|
||||||
"Each Goblin you control has menace. (They can't be blocked except by two or more creatures.)")));
|
"Each Goblin you control has menace. (They can't be blocked except by two or more creatures.)")));
|
||||||
|
|
||||||
// Each Elemental you control has menace. (They can't be blocked except by two or more creatures.)
|
// Each Elemental you control has menace. (They can't be blocked except by two or more creatures.)
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(
|
||||||
MenaceAbility.getInstance(),
|
new MenaceAbility(),
|
||||||
Duration.WhileOnBattlefield, filterElemental,
|
Duration.WhileOnBattlefield, filterElemental,
|
||||||
"Each Elemental you control has menace. (They can't be blocked except by two or more creatures.)")));
|
"Each Elemental you control has menace. (They can't be blocked except by two or more creatures.)")));
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ import mage.game.stack.Spell;
|
||||||
public class CelestialKirin extends CardImpl {
|
public class CelestialKirin extends CardImpl {
|
||||||
|
|
||||||
public CelestialKirin(UUID ownerId, CardSetInfo setInfo) {
|
public CelestialKirin(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
|
||||||
addSuperType(SuperType.LEGENDARY);
|
addSuperType(SuperType.LEGENDARY);
|
||||||
this.subtype.add(SubType.KIRIN);
|
this.subtype.add(SubType.KIRIN);
|
||||||
this.subtype.add(SubType.SPIRIT);
|
this.subtype.add(SubType.SPIRIT);
|
||||||
|
@ -92,7 +92,7 @@ class CelestialKirinEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getState().getStack().getSpell(getTargetPointer().getFirst(game, source));
|
Spell spell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
int cmc = spell.getConvertedManaCost();
|
int cmc = spell.getConvertedManaCost();
|
||||||
FilterPermanent filter = new FilterPermanent();
|
FilterPermanent filter = new FilterPermanent();
|
||||||
|
|
|
@ -75,6 +75,7 @@ public class ChampionOfStraySouls extends CardImpl {
|
||||||
* ability, before you pay any costs. You can't target any of the
|
* ability, before you pay any costs. You can't target any of the
|
||||||
* creatures you sacrifice.
|
* creatures you sacrifice.
|
||||||
*/
|
*/
|
||||||
|
//TODO: Make ability properly copiable
|
||||||
// {3}{B}{B}, {T}, Sacrifice X other creatures: Return X target creatures from your graveyard to the battlefield.
|
// {3}{B}{B}, {T}, Sacrifice X other creatures: Return X target creatures from your graveyard to the battlefield.
|
||||||
Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect();
|
Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect();
|
||||||
effect.setText("Return X target creatures from your graveyard to the battlefield");
|
effect.setText("Return X target creatures from your graveyard to the battlefield");
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class ChandraTheFirebrand extends CardImpl {
|
||||||
class ChandraTheFirebrandAbility extends DelayedTriggeredAbility {
|
class ChandraTheFirebrandAbility extends DelayedTriggeredAbility {
|
||||||
|
|
||||||
ChandraTheFirebrandAbility() {
|
ChandraTheFirebrandAbility() {
|
||||||
super(new CopyTargetSpellEffect(), Duration.EndOfTurn);
|
super(new CopyTargetSpellEffect(true), Duration.EndOfTurn);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChandraTheFirebrandAbility(final ChandraTheFirebrandAbility ability) {
|
ChandraTheFirebrandAbility(final ChandraTheFirebrandAbility ability) {
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class ChitinousCloak extends CardImpl {
|
||||||
|
|
||||||
// Equipped creature gets +2/+2 and has menace.
|
// Equipped creature gets +2/+2 and has menace.
|
||||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2));
|
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(2, 2));
|
||||||
Effect effect = new GainAbilityAttachedEffect(MenaceAbility.getInstance(), AttachmentType.EQUIPMENT);
|
Effect effect = new GainAbilityAttachedEffect(new MenaceAbility(), AttachmentType.EQUIPMENT);
|
||||||
effect.setText("and has menace");
|
effect.setText("and has menace");
|
||||||
ability.addEffect(effect);
|
ability.addEffect(effect);
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
|
@ -61,13 +61,13 @@ public class ChitteringHost extends MeldCard {
|
||||||
this.addAbility(HasteAbility.getInstance());
|
this.addAbility(HasteAbility.getInstance());
|
||||||
|
|
||||||
// Menace <i>(This creature can't be blocked except by two or more creatures.
|
// Menace <i>(This creature can't be blocked except by two or more creatures.
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
// When Chittering Host enters the battlefield, other creatures you control get +1/+0 and gain menace until end of turn.
|
// When Chittering Host enters the battlefield, other creatures you control get +1/+0 and gain menace until end of turn.
|
||||||
Effect effect = new BoostControlledEffect(1, 0, Duration.EndOfTurn, true);
|
Effect effect = new BoostControlledEffect(1, 0, Duration.EndOfTurn, true);
|
||||||
effect.setText("other creatures you control get +1/+0");
|
effect.setText("other creatures you control get +1/+0");
|
||||||
Ability ability = new EntersBattlefieldTriggeredAbility(effect, false);
|
Ability ability = new EntersBattlefieldTriggeredAbility(effect, false);
|
||||||
effect = new GainAbilityAllEffect(MenaceAbility.getInstance(), Duration.EndOfTurn, new FilterControlledCreaturePermanent("other creatures"), true);
|
effect = new GainAbilityAllEffect(new MenaceAbility(), Duration.EndOfTurn, new FilterControlledCreaturePermanent("other creatures"), true);
|
||||||
effect.setText("and gain menace until end of turn");
|
effect.setText("and gain menace until end of turn");
|
||||||
ability.addEffect(effect);
|
ability.addEffect(effect);
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
|
@ -59,7 +59,7 @@ import mage.game.permanent.token.Token;
|
||||||
public class ChronatogTotem extends CardImpl {
|
public class ChronatogTotem extends CardImpl {
|
||||||
|
|
||||||
public ChronatogTotem(UUID ownerId, CardSetInfo setInfo) {
|
public ChronatogTotem(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||||
|
|
||||||
// {tap}: Add {U} to your mana pool.
|
// {tap}: Add {U} to your mana pool.
|
||||||
this.addAbility(new BlueManaAbility());
|
this.addAbility(new BlueManaAbility());
|
||||||
|
@ -91,8 +91,6 @@ class ChronatogTotemAbility extends LimitedTimesPerTurnActivatedAbility {
|
||||||
|
|
||||||
private static final Effects emptyEffects = new Effects();
|
private static final Effects emptyEffects = new Effects();
|
||||||
|
|
||||||
private final Condition condition;
|
|
||||||
|
|
||||||
public ChronatogTotemAbility(Zone zone, Effect effect, Cost cost, Condition condition) {
|
public ChronatogTotemAbility(Zone zone, Effect effect, Cost cost, Condition condition) {
|
||||||
super(zone, effect, cost);
|
super(zone, effect, cost);
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
|
@ -100,7 +98,6 @@ class ChronatogTotemAbility extends LimitedTimesPerTurnActivatedAbility {
|
||||||
|
|
||||||
public ChronatogTotemAbility(ChronatogTotemAbility ability) {
|
public ChronatogTotemAbility(ChronatogTotemAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.condition = ability.condition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -111,14 +108,6 @@ class ChronatogTotemAbility extends LimitedTimesPerTurnActivatedAbility {
|
||||||
return super.getEffects(game, effectType);
|
return super.getEffects(game, effectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canActivate(UUID playerId, Game game) {
|
|
||||||
if (!condition.apply(game, this)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return super.canActivate(playerId, game);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChronatogTotemAbility copy() {
|
public ChronatogTotemAbility copy() {
|
||||||
return new ChronatogTotemAbility(this);
|
return new ChronatogTotemAbility(this);
|
||||||
|
|
|
@ -54,7 +54,7 @@ import mage.target.TargetPlayer;
|
||||||
public class CloudhoofKirin extends CardImpl {
|
public class CloudhoofKirin extends CardImpl {
|
||||||
|
|
||||||
public CloudhoofKirin(UUID ownerId, CardSetInfo setInfo) {
|
public CloudhoofKirin(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
|
||||||
addSuperType(SuperType.LEGENDARY);
|
addSuperType(SuperType.LEGENDARY);
|
||||||
this.subtype.add(SubType.KIRIN);
|
this.subtype.add(SubType.KIRIN);
|
||||||
this.subtype.add(SubType.SPIRIT);
|
this.subtype.add(SubType.SPIRIT);
|
||||||
|
@ -98,10 +98,10 @@ class CloudhoofKirinEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
Player targetPlayer = null;
|
Player targetPlayer = null;
|
||||||
for(Target target: source.getTargets()) {
|
for (Target target : source.getTargets()) {
|
||||||
if (target instanceof TargetPlayer) {
|
if (target instanceof TargetPlayer) {
|
||||||
targetPlayer = game.getPlayer(target.getFirstTarget());
|
targetPlayer = game.getPlayer(target.getFirstTarget());
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class ClovenCasting extends CardImpl {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{5}{U}{R}");
|
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{5}{U}{R}");
|
||||||
|
|
||||||
// Whenever you cast a multicolored instant or sorcery spell, you may pay {1}. If you do, copy that spell. You may choose new targets for the copy.
|
// Whenever you cast a multicolored instant or sorcery spell, you may pay {1}. If you do, copy that spell. You may choose new targets for the copy.
|
||||||
Effect effect = new CopyTargetSpellEffect();
|
Effect effect = new CopyTargetSpellEffect(true);
|
||||||
effect.setText("copy that spell. You may choose new targets for the copy");
|
effect.setText("copy that spell. You may choose new targets for the copy");
|
||||||
this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(effect, new GenericManaCost(1)), filter, true, true));
|
this.addAbility(new SpellCastControllerTriggeredAbility(new DoIfCostPaid(effect, new GenericManaCost(1)), filter, true, true));
|
||||||
}
|
}
|
||||||
|
|
64
Mage.Sets/src/mage/cards/c/ColossalDreadmaw.java
Normal file
64
Mage.Sets/src/mage/cards/c/ColossalDreadmaw.java
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class ColossalDreadmaw extends CardImpl {
|
||||||
|
|
||||||
|
public ColossalDreadmaw(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.DINOSAUR);
|
||||||
|
this.power = new MageInt(6);
|
||||||
|
this.toughness = new MageInt(6);
|
||||||
|
|
||||||
|
// Trample
|
||||||
|
this.addAbility(TrampleAbility.getInstance());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColossalDreadmaw(final ColossalDreadmaw card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ColossalDreadmaw copy() {
|
||||||
|
return new ColossalDreadmaw(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,7 +33,7 @@ import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
|
||||||
import mage.abilities.mana.ColorlessManaAbility;
|
import mage.abilities.mana.ColorlessManaAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
|
@ -71,7 +71,7 @@ public class ConquerorsFoothold extends CardImpl {
|
||||||
|
|
||||||
// {6}, {T}: Return target card from your graveyard to your hand.
|
// {6}, {T}: Return target card from your graveyard to your hand.
|
||||||
SimpleActivatedAbility ability3 = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
SimpleActivatedAbility ability3 = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||||
new ReturnToHandTargetEffect(),
|
new ReturnFromGraveyardToHandTargetEffect(),
|
||||||
new ManaCostsImpl("{6}"));
|
new ManaCostsImpl("{6}"));
|
||||||
ability3.addCost(new TapSourceCost());
|
ability3.addCost(new TapSourceCost());
|
||||||
ability3.addTarget(new TargetCardInYourGraveyard());
|
ability3.addTarget(new TargetCardInYourGraveyard());
|
||||||
|
|
62
Mage.Sets/src/mage/cards/c/ContractKilling.java
Normal file
62
Mage.Sets/src/mage/cards/c/ContractKilling.java
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.game.permanent.token.TreasureToken;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class ContractKilling extends CardImpl {
|
||||||
|
|
||||||
|
public ContractKilling(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}");
|
||||||
|
|
||||||
|
// Destroy target creature. Create two colorless Treasure artifact tokens with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool."
|
||||||
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||||
|
this.getSpellAbility().addEffect(new DestroyTargetEffect());
|
||||||
|
this.getSpellAbility().addEffect(new CreateTokenEffect(new TreasureToken(), 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContractKilling(final ContractKilling card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContractKilling copy() {
|
||||||
|
return new ContractKilling(this);
|
||||||
|
}
|
||||||
|
}
|
74
Mage.Sets/src/mage/cards/c/CostlyPlunder.java
Normal file
74
Mage.Sets/src/mage/cards/c/CostlyPlunder.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.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||||
|
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
|
import mage.filter.predicate.Predicates;
|
||||||
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
|
import mage.target.common.TargetControlledPermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class CostlyPlunder extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact or creature");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(Predicates.or(
|
||||||
|
new CardTypePredicate(CardType.ARTIFACT),
|
||||||
|
new CardTypePredicate(CardType.CREATURE)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CostlyPlunder(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}");
|
||||||
|
|
||||||
|
// As an additional cost to cast Costly Plunder, sacrifice an artifact or creature.
|
||||||
|
this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledPermanent(1, 1, filter, true)));
|
||||||
|
|
||||||
|
// Draw two cards.
|
||||||
|
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CostlyPlunder(final CostlyPlunder card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CostlyPlunder copy() {
|
||||||
|
return new CostlyPlunder(this);
|
||||||
|
}
|
||||||
|
}
|
68
Mage.Sets/src/mage/cards/c/CrashTheRamparts.java
Normal file
68
Mage.Sets/src/mage/cards/c/CrashTheRamparts.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.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class CrashTheRamparts extends CardImpl {
|
||||||
|
|
||||||
|
public CrashTheRamparts(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}");
|
||||||
|
|
||||||
|
// Target creature gets +3/+3 and gains trample until end of turn.
|
||||||
|
Effect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn);
|
||||||
|
effect.setText("Target creature gets +3/+3");
|
||||||
|
this.getSpellAbility().addEffect(effect);
|
||||||
|
effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn);
|
||||||
|
effect.setText("and gains trample until end of turn");
|
||||||
|
this.getSpellAbility().addEffect(effect);
|
||||||
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrashTheRamparts(final CrashTheRamparts card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CrashTheRamparts copy() {
|
||||||
|
return new CrashTheRamparts(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,6 +68,7 @@ public class CrownOfDoom extends CardImpl {
|
||||||
effect.setText("it gets +2/+0 until end of turn");
|
effect.setText("it gets +2/+0 until end of turn");
|
||||||
this.addAbility(new AttacksAllTriggeredAbility(effect, false, StaticFilters.FILTER_PERMANENT_CREATURE, SetTargetPointer.PERMANENT, true));
|
this.addAbility(new AttacksAllTriggeredAbility(effect, false, StaticFilters.FILTER_PERMANENT_CREATURE, SetTargetPointer.PERMANENT, true));
|
||||||
|
|
||||||
|
//TODO: Make ability properly copiable
|
||||||
// {2}: Target player other than Crown of Doom's owner gains control of it. Activate this ability only during your turn.
|
// {2}: Target player other than Crown of Doom's owner gains control of it. Activate this ability only during your turn.
|
||||||
Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new CrownOfDoomEffect(), new ManaCostsImpl("{2}"), MyTurnCondition.instance);
|
Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new CrownOfDoomEffect(), new ManaCostsImpl("{2}"), MyTurnCondition.instance);
|
||||||
ability.addTarget(new TargetPlayer(1, 1, false, new FilterPlayer("player other than Crown of Doom's owner")));
|
ability.addTarget(new TargetPlayer(1, 1, false, new FilterPlayer("player other than Crown of Doom's owner")));
|
||||||
|
|
|
@ -29,16 +29,17 @@ package mage.cards.c;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.DealsDamageToACreatureTriggeredAbility;
|
||||||
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
|
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
import mage.abilities.effects.common.LookLibraryControllerEffect;
|
import mage.abilities.effects.common.LookLibraryControllerEffect;
|
||||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
|
||||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||||
import mage.abilities.keyword.TrampleAbility;
|
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
|
@ -55,7 +56,7 @@ import mage.players.Player;
|
||||||
public class CruelDeceiver extends CardImpl {
|
public class CruelDeceiver extends CardImpl {
|
||||||
|
|
||||||
public CruelDeceiver(UUID ownerId, CardSetInfo setInfo) {
|
public CruelDeceiver(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
|
||||||
this.subtype.add(SubType.SPIRIT);
|
this.subtype.add(SubType.SPIRIT);
|
||||||
|
|
||||||
this.power = new MageInt(2);
|
this.power = new MageInt(2);
|
||||||
|
@ -82,7 +83,7 @@ class CruelDeceiverEffect extends OneShotEffect {
|
||||||
|
|
||||||
public CruelDeceiverEffect() {
|
public CruelDeceiverEffect() {
|
||||||
super(Outcome.AddAbility);
|
super(Outcome.AddAbility);
|
||||||
this.staticText = "Reveal the top card of your library. If it's a land card, {this} gets +2/+2 and gains trample until end of turn";
|
this.staticText = "Reveal the top card of your library. If it's a land card, {this} gains \"Whenever Cruel Deceiver deals damage to a creature, destroy that creature\" until end of turn";
|
||||||
}
|
}
|
||||||
|
|
||||||
public CruelDeceiverEffect(final CruelDeceiverEffect effect) {
|
public CruelDeceiverEffect(final CruelDeceiverEffect effect) {
|
||||||
|
@ -96,15 +97,17 @@ class CruelDeceiverEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (player != null) {
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
|
if (controller != null && sourceObject != null) {
|
||||||
Cards cards = new CardsImpl();
|
Cards cards = new CardsImpl();
|
||||||
Card card = player.getLibrary().getFromTop(game);
|
Card card = controller.getLibrary().getFromTop(game);
|
||||||
|
if (card != null) {
|
||||||
cards.add(card);
|
cards.add(card);
|
||||||
player.revealCards("Cruel Deceiver", cards, game);
|
controller.revealCards(sourceObject.getIdName(), cards, game);
|
||||||
if (card != null && card.isLand()) {
|
if (card.isLand()) {
|
||||||
game.addEffect(new BoostSourceEffect(2,2,Duration.EndOfTurn), source);
|
game.addEffect(new GainAbilitySourceEffect(new DealsDamageToACreatureTriggeredAbility(new DestroyTargetEffect(true), false, false, true), Duration.EndOfTurn), source);
|
||||||
game.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(),Duration.EndOfTurn), source);
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
76
Mage.Sets/src/mage/cards/c/CrushingCanopy.java
Normal file
76
Mage.Sets/src/mage/cards/c/CrushingCanopy.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.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Mode;
|
||||||
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
import mage.target.common.TargetEnchantmentPermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class CrushingCanopy extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with flying");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new AbilityPredicate(FlyingAbility.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrushingCanopy(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}");
|
||||||
|
|
||||||
|
// Choose one --
|
||||||
|
// * Destroy target creature with flying.
|
||||||
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
|
||||||
|
this.getSpellAbility().addEffect(new DestroyTargetEffect());
|
||||||
|
// * Destroy target enchantment.
|
||||||
|
Mode mode = new Mode();
|
||||||
|
mode.getTargets().add(new TargetEnchantmentPermanent());
|
||||||
|
mode.getEffects().add(new DestroyTargetEffect());
|
||||||
|
this.getSpellAbility().addMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CrushingCanopy(final CrushingCanopy card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CrushingCanopy copy() {
|
||||||
|
return new CrushingCanopy(this);
|
||||||
|
}
|
||||||
|
}
|
136
Mage.Sets/src/mage/cards/c/CulturalExchange.java
Normal file
136
Mage.Sets/src/mage/cards/c/CulturalExchange.java
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.c;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.effects.ContinuousEffect;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.TargetPlayer;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class CulturalExchange extends CardImpl {
|
||||||
|
|
||||||
|
public CulturalExchange(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U}{U}");
|
||||||
|
|
||||||
|
// Choose any number of creatures target player controls. Choose the same number of creatures another target player controls. Those players exchange control of those creatures.
|
||||||
|
this.getSpellAbility().addEffect(new CulturalExchangeEffect());
|
||||||
|
this.getSpellAbility().addTarget(new TargetPlayer(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CulturalExchange(final CulturalExchange card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CulturalExchange copy() {
|
||||||
|
return new CulturalExchange(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CulturalExchangeEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
CulturalExchangeEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
this.staticText = "Choose any number of creatures target player controls. "
|
||||||
|
+ "Choose the same number of creatures another target player controls. "
|
||||||
|
+ "Those players exchange control of those creatures.";
|
||||||
|
}
|
||||||
|
|
||||||
|
CulturalExchangeEffect(final CulturalExchangeEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CulturalExchangeEffect copy() {
|
||||||
|
return new CulturalExchangeEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player player1 = game.getPlayer(targetPointer.getTargets(game, source).get(0));
|
||||||
|
Player player2 = game.getPlayer(targetPointer.getTargets(game, source).get(1));
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (player1 == null || player2 == null || controller == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creatures " + player1.getLogName() + " controls");
|
||||||
|
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creatures " + player2.getLogName() + " controls");
|
||||||
|
filter1.add(new ControllerIdPredicate(player1.getId()));
|
||||||
|
filter2.add(new ControllerIdPredicate(player2.getId()));
|
||||||
|
int creatureCount1 = game.getBattlefield().count(filter1, source.getSourceId(), source.getControllerId(), game);
|
||||||
|
int creatureCount2 = game.getBattlefield().count(filter2, source.getSourceId(), source.getControllerId(), game);
|
||||||
|
int creaturesToSwitch = Math.min(creatureCount1, creatureCount2);
|
||||||
|
if (creaturesToSwitch == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
TargetCreaturePermanent target1 = new TargetCreaturePermanent(0, creaturesToSwitch, filter1, true);
|
||||||
|
if (target1.choose(Outcome.Benefit, controller.getId(), source.getSourceId(), game)) {
|
||||||
|
int otherToSwitch = target1.getTargets().size();
|
||||||
|
TargetCreaturePermanent target2 = new TargetCreaturePermanent(otherToSwitch, otherToSwitch, filter2, true);
|
||||||
|
if (target2.choose(Outcome.Benefit, controller.getId(), source.getSourceId(), game)) {
|
||||||
|
for (UUID creatureId : target1.getTargets()) {
|
||||||
|
Permanent creature = game.getPermanent(creatureId);
|
||||||
|
if (creature != null) {
|
||||||
|
ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, player2.getId());
|
||||||
|
game.informPlayers(player2.getLogName() + " gains control of " + creature.getLogName());
|
||||||
|
effect.setTargetPointer(new FixedTarget(creature, game));
|
||||||
|
game.addEffect(effect, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (UUID creatureId : target2.getTargets()) {
|
||||||
|
Permanent creature = game.getPermanent(creatureId);
|
||||||
|
if (creature != null) {
|
||||||
|
ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, player1.getId());
|
||||||
|
game.informPlayers(player1.getLogName() + " gains control of " + creature.getLogName());
|
||||||
|
effect.setTargetPointer(new FixedTarget(creature, game));
|
||||||
|
game.addEffect(effect, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,6 +62,7 @@ public class CuombajjWitches extends CardImpl {
|
||||||
this.power = new MageInt(1);
|
this.power = new MageInt(1);
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
|
//TODO: Make ability properly copiable
|
||||||
// {T}: Cuombajj Witches deals 1 damage to target creature or player and 1 damage to target creature or player of an opponent's choice.
|
// {T}: Cuombajj Witches deals 1 damage to target creature or player and 1 damage to target creature or player of an opponent's choice.
|
||||||
Effect effect = new DamageTargetEffect(1);
|
Effect effect = new DamageTargetEffect(1);
|
||||||
effect.setText("{this} deals 1 damage to target creature or player and 1 damage to target creature or player of an opponent's choice");
|
effect.setText("{this} deals 1 damage to target creature or player and 1 damage to target creature or player of an opponent's choice");
|
||||||
|
|
|
@ -58,7 +58,7 @@ import mage.target.targetpointer.FixedTarget;
|
||||||
public class CurseOfEchoes extends CardImpl {
|
public class CurseOfEchoes extends CardImpl {
|
||||||
|
|
||||||
public CurseOfEchoes(UUID ownerId, CardSetInfo setInfo) {
|
public CurseOfEchoes(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}");
|
||||||
this.subtype.add(SubType.AURA, SubType.CURSE);
|
this.subtype.add(SubType.AURA, SubType.CURSE);
|
||||||
|
|
||||||
// Enchant player
|
// Enchant player
|
||||||
|
@ -143,7 +143,7 @@ class CurseOfEchoesEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
|
Spell spell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
String chooseMessage = "Copy target spell? You may choose new targets for the copy.";
|
String chooseMessage = "Copy target spell? You may choose new targets for the copy.";
|
||||||
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
|
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class CursedMinotaur extends CardImpl {
|
||||||
this.toughness = new MageInt(2);
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,21 +28,17 @@
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.ReturnToHandFromBattlefieldAllEffect;
|
||||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||||
import mage.abilities.keyword.OverloadAbility;
|
import mage.abilities.keyword.OverloadAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.TargetController;
|
import mage.constants.TargetController;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.common.FilterNonlandPermanent;
|
import mage.filter.common.FilterNonlandPermanent;
|
||||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.target.common.TargetNonlandPermanent;
|
import mage.target.common.TargetNonlandPermanent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,14 +54,16 @@ public class CyclonicRift extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CyclonicRift(UUID ownerId, CardSetInfo setInfo) {
|
public CyclonicRift(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
|
||||||
|
|
||||||
// Return target nonland permanent you don't control to its owner's hand.
|
// Return target nonland permanent you don't control to its owner's hand.
|
||||||
this.getSpellAbility().addTarget(new TargetNonlandPermanent(filter));
|
this.getSpellAbility().addTarget(new TargetNonlandPermanent(filter));
|
||||||
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
|
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
|
||||||
|
|
||||||
// Overload {6}{U} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.")
|
// Overload {6}{U} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.")
|
||||||
this.addAbility(new OverloadAbility(this, new CyclonicRiftEffect(), new ManaCostsImpl("{6}{U}")));
|
Effect effect = new ReturnToHandFromBattlefieldAllEffect(filter);
|
||||||
|
effect.setText("Return each nonland permanent you don't control to its owner's hand");
|
||||||
|
this.addAbility(new OverloadAbility(this, effect, new ManaCostsImpl("{6}{U}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CyclonicRift(final CyclonicRift card) {
|
public CyclonicRift(final CyclonicRift card) {
|
||||||
|
@ -77,33 +75,3 @@ public class CyclonicRift extends CardImpl {
|
||||||
return new CyclonicRift(this);
|
return new CyclonicRift(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CyclonicRiftEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
private static final FilterNonlandPermanent filter = new FilterNonlandPermanent();
|
|
||||||
|
|
||||||
public CyclonicRiftEffect() {
|
|
||||||
super(Outcome.ReturnToHand);
|
|
||||||
staticText = "Return each nonland permanent you don't control to its owner's hand";
|
|
||||||
}
|
|
||||||
|
|
||||||
public CyclonicRiftEffect(final CyclonicRiftEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
for (Permanent creature : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
|
||||||
if (!creature.getControllerId().equals(source.getControllerId())) {
|
|
||||||
creature.moveToZone(Zone.HAND, source.getSourceId(), game, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CyclonicRiftEffect copy() {
|
|
||||||
return new CyclonicRiftEffect(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
61
Mage.Sets/src/mage/cards/d/DarkNourishment.java
Normal file
61
Mage.Sets/src/mage/cards/d/DarkNourishment.java
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
|
import mage.abilities.effects.common.GainLifeEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.target.common.TargetCreatureOrPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class DarkNourishment extends CardImpl {
|
||||||
|
|
||||||
|
public DarkNourishment(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{B}");
|
||||||
|
|
||||||
|
// Dark Nourishment deals 3 damage to target creature or player. You gain 3 life.
|
||||||
|
this.getSpellAbility().addEffect(new DamageTargetEffect(3));
|
||||||
|
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
|
||||||
|
this.getSpellAbility().addEffect(new GainLifeEffect(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DarkNourishment(final DarkNourishment card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DarkNourishment copy() {
|
||||||
|
return new DarkNourishment(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,7 +63,7 @@ public class DarthVader extends CardImpl {
|
||||||
this.nightCard = true;
|
this.nightCard = true;
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
// Lifelink
|
// Lifelink
|
||||||
this.addAbility(LifelinkAbility.getInstance());
|
this.addAbility(LifelinkAbility.getInstance());
|
||||||
|
|
|
@ -49,7 +49,10 @@ public class DeadeyeQuartermaster extends CardImpl {
|
||||||
private static final FilterCard filter = new FilterCard("an Equipment or Vehicle card");
|
private static final FilterCard filter = new FilterCard("an Equipment or Vehicle card");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(Predicates.or(new SubtypePredicate(SubType.EQUIPMENT), new SubtypePredicate(SubType.EQUIPMENT)));
|
filter.add(Predicates.or(
|
||||||
|
new SubtypePredicate(SubType.EQUIPMENT),
|
||||||
|
new SubtypePredicate(SubType.VEHICLE)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeadeyeQuartermaster(UUID ownerId, CardSetInfo setInfo) {
|
public DeadeyeQuartermaster(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
|
|
@ -40,12 +40,9 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.TargetController;
|
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.target.common.TargetCardInOpponentsGraveyard;
|
||||||
import mage.filter.predicate.other.OwnerPredicate;
|
|
||||||
import mage.target.common.TargetCardInASingleGraveyard;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -53,12 +50,6 @@ import mage.target.common.TargetCardInASingleGraveyard;
|
||||||
*/
|
*/
|
||||||
public class DeadeyeTracker extends CardImpl {
|
public class DeadeyeTracker extends CardImpl {
|
||||||
|
|
||||||
private static final FilterCard filter = new FilterCard("cards from an opponent's graveyard");
|
|
||||||
|
|
||||||
static {
|
|
||||||
filter.add(Predicates.not(new OwnerPredicate(TargetController.YOU)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeadeyeTracker(UUID ownerId, CardSetInfo setInfo) {
|
public DeadeyeTracker(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
|
||||||
|
|
||||||
|
@ -73,7 +64,7 @@ public class DeadeyeTracker extends CardImpl {
|
||||||
Effect effect = new ExploreSourceEffect();
|
Effect effect = new ExploreSourceEffect();
|
||||||
effect.setText("{this} explores");
|
effect.setText("{this} explores");
|
||||||
ability.addEffect(effect);
|
ability.addEffect(effect);
|
||||||
ability.addTarget(new TargetCardInASingleGraveyard(2, 2, filter));
|
ability.addTarget(new TargetCardInOpponentsGraveyard(2, 2, new FilterCard("cards from an opponent's graveyard"), true));
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
111
Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.java
Normal file
111
Mage.Sets/src/mage/cards/d/DeathgorgeScavenger.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.cards.d;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.common.TargetCardInGraveyard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class DeathgorgeScavenger extends CardImpl {
|
||||||
|
|
||||||
|
public DeathgorgeScavenger(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.DINOSAUR);
|
||||||
|
this.power = new MageInt(3);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
// Whenever Deathgorge Scavenger enters the battlefield or attacks, you may exile target card from a graveyard. If a creature card is exiled this way, you gain 2 life. If a noncreature card is exiled this way, Deathgorge Scavenger gets +1/+1 until end of turn.
|
||||||
|
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DeathgorgeScavengerEffect(), true);
|
||||||
|
ability.addTarget(new TargetCardInGraveyard());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeathgorgeScavenger(final DeathgorgeScavenger card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeathgorgeScavenger copy() {
|
||||||
|
return new DeathgorgeScavenger(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeathgorgeScavengerEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public DeathgorgeScavengerEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
this.staticText = "exile target card from a graveyard. If a creature card is exiled this way, you gain 2 life. If a noncreature card is exiled this way, {this} gets +1/+1 until end of turn";
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeathgorgeScavengerEffect(final DeathgorgeScavengerEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeathgorgeScavengerEffect copy() {
|
||||||
|
return new DeathgorgeScavengerEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller != null) {
|
||||||
|
Card card = game.getCard(getTargetPointer().getFirst(game, source));
|
||||||
|
if (card != null) {
|
||||||
|
controller.moveCards(card, Zone.EXILED, source, game);
|
||||||
|
if (card.isCreature()) {
|
||||||
|
controller.gainLife(2, game);
|
||||||
|
} else {
|
||||||
|
game.addEffect(new BoostSourceEffect(1, 1, Duration.EndOfTurn), source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.TapTargetCost;
|
import mage.abilities.costs.common.TapTargetCost;
|
||||||
import mage.abilities.effects.common.ReturnToHandSourceEffect;
|
import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect;
|
||||||
import mage.abilities.keyword.FlyingAbility;
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
|
@ -69,7 +69,9 @@ public class DeathlessAncient extends CardImpl {
|
||||||
this.addAbility(FlyingAbility.getInstance());
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
// Tap three untapped Vampires you control: Return Deathless Ancient from your graveyard to your hand.
|
// Tap three untapped Vampires you control: Return Deathless Ancient from your graveyard to your hand.
|
||||||
this.addAbility(new SimpleActivatedAbility(Zone.GRAVEYARD, new ReturnToHandSourceEffect(), new TapTargetCost(new TargetControlledPermanent(3, 3, filter, true))));
|
this.addAbility(new SimpleActivatedAbility(Zone.GRAVEYARD,
|
||||||
|
new ReturnSourceFromGraveyardToHandEffect(),
|
||||||
|
new TapTargetCost(new TargetControlledPermanent(3, 3, filter, true))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ public class DeclarationOfNaught extends CardImpl {
|
||||||
// As Declaration of Naught enters the battlefield, name a card.
|
// As Declaration of Naught enters the battlefield, name a card.
|
||||||
this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.ALL)));
|
this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.ALL)));
|
||||||
|
|
||||||
|
//TODO: Make ability properly copiable
|
||||||
// {U}: Counter target spell with the chosen name.
|
// {U}: Counter target spell with the chosen name.
|
||||||
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl("{U}"));
|
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl("{U}"));
|
||||||
ability.addTarget(new TargetSpell(filter));
|
ability.addTarget(new TargetSpell(filter));
|
||||||
|
|
|
@ -68,6 +68,7 @@ public class DeepfireElemental extends CardImpl {
|
||||||
this.power = new MageInt(4);
|
this.power = new MageInt(4);
|
||||||
this.toughness = new MageInt(4);
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
|
//TODO: Make ability properly copiable
|
||||||
// {X}{X}{1}: Destroy target artifact or creature with converted mana cost X.
|
// {X}{X}{1}: Destroy target artifact or creature with converted mana cost X.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{X}{X}{1}"));
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{X}{X}{1}"));
|
||||||
ability.addTarget(new TargetPermanent(filter));
|
ability.addTarget(new TargetPermanent(filter));
|
||||||
|
|
69
Mage.Sets/src/mage/cards/d/DeeprootWarrior.java
Normal file
69
Mage.Sets/src/mage/cards/d/DeeprootWarrior.java
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.BecomesBlockedTriggeredAbility;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class DeeprootWarrior extends CardImpl {
|
||||||
|
|
||||||
|
public DeeprootWarrior(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.MERFOLK);
|
||||||
|
this.subtype.add(SubType.WARRIOR);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
// Whenever Deeproot Warrior becomes blocked, it gets +1/+1 until end of turn.
|
||||||
|
Effect effect = new BoostSourceEffect(1, 1, Duration.EndOfTurn);
|
||||||
|
effect.setText("it gets +1/+1 until end of turn");
|
||||||
|
this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeeprootWarrior(final DeeprootWarrior card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeeprootWarrior copy() {
|
||||||
|
return new DeeprootWarrior(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,7 +52,7 @@ public class Demoralize extends CardImpl {
|
||||||
|
|
||||||
|
|
||||||
// All creatures gain menace until end of turn. (They can't be blocked except by two or more creatures.)
|
// All creatures gain menace until end of turn. (They can't be blocked except by two or more creatures.)
|
||||||
this.getSpellAbility().addEffect(new GainAbilityAllEffect(MenaceAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURES));
|
this.getSpellAbility().addEffect(new GainAbilityAllEffect(new MenaceAbility(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURES));
|
||||||
|
|
||||||
// Threshold — If seven or more cards are in your graveyard, creatures can't block this turn.
|
// Threshold — If seven or more cards are in your graveyard, creatures can't block this turn.
|
||||||
this.getSpellAbility().addEffect(
|
this.getSpellAbility().addEffect(
|
||||||
|
|
62
Mage.Sets/src/mage/cards/d/DepthsOfDesire.java
Normal file
62
Mage.Sets/src/mage/cards/d/DepthsOfDesire.java
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
|
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.game.permanent.token.TreasureToken;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class DepthsOfDesire extends CardImpl {
|
||||||
|
|
||||||
|
public DepthsOfDesire(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
|
||||||
|
|
||||||
|
// Return target creature to its owner's hand. Create a colorless Treasure token with "{t}, Sacrifice this artifact: Add one mana of any color to your mana pool."
|
||||||
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||||
|
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
|
||||||
|
this.getSpellAbility().addEffect(new CreateTokenEffect(new TreasureToken()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DepthsOfDesire(final DepthsOfDesire card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DepthsOfDesire copy() {
|
||||||
|
return new DepthsOfDesire(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,7 +50,7 @@ public class DeputizedProtester extends CardImpl {
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
// Melee
|
// Melee
|
||||||
this.addAbility(new MeleeAbility());
|
this.addAbility(new MeleeAbility());
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class DerangedWhelp extends CardImpl {
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
}
|
}
|
||||||
|
|
||||||
public DerangedWhelp(final DerangedWhelp card) {
|
public DerangedWhelp(final DerangedWhelp card) {
|
||||||
|
|
|
@ -64,7 +64,8 @@ public class DireFleetCaptain extends CardImpl {
|
||||||
|
|
||||||
// Whenever Dire Fleet Captain attacks, it gets +1/+1 until end of turn for each other attacking Pirate.
|
// Whenever Dire Fleet Captain attacks, it gets +1/+1 until end of turn for each other attacking Pirate.
|
||||||
PermanentsOnBattlefieldCount value = new PermanentsOnBattlefieldCount(filter);
|
PermanentsOnBattlefieldCount value = new PermanentsOnBattlefieldCount(filter);
|
||||||
this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(value, value, Duration.EndOfTurn, true), false));
|
this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(value, value, Duration.EndOfTurn, true)
|
||||||
|
.setText("it gets +1/+1 until end of turn for each other attacking Pirate"), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DireFleetCaptain(final DireFleetCaptain card) {
|
public DireFleetCaptain(final DireFleetCaptain card) {
|
||||||
|
|
69
Mage.Sets/src/mage/cards/d/DireFleetInterloper.java
Normal file
69
Mage.Sets/src/mage/cards/d/DireFleetInterloper.java
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
package mage.cards.d;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||||
|
import mage.abilities.effects.keyword.ExploreSourceEffect;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.abilities.keyword.MenaceAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class DireFleetInterloper extends CardImpl {
|
||||||
|
|
||||||
|
public DireFleetInterloper(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
||||||
|
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.subtype.add(SubType.PIRATE);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
// Menace
|
||||||
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
|
// When Dire Fleet Interloper enters the battlefield, it explores.
|
||||||
|
this.addAbility(new EntersBattlefieldTriggeredAbility(new ExploreSourceEffect()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DireFleetInterloper(final DireFleetInterloper card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DireFleetInterloper copy() {
|
||||||
|
return new DireFleetInterloper(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -58,7 +58,7 @@ public class DireFleetRavager extends CardImpl {
|
||||||
this.toughness = new MageInt(4);
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
// Deathtouch
|
// Deathtouch
|
||||||
this.addAbility(DeathtouchAbility.getInstance());
|
this.addAbility(DeathtouchAbility.getInstance());
|
||||||
|
|
68
Mage.Sets/src/mage/cards/d/DiveDown.java
Normal file
68
Mage.Sets/src/mage/cards/d/DiveDown.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.cards.d;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
|
import mage.abilities.keyword.HexproofAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.target.common.TargetControlledCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author TheElk801
|
||||||
|
*/
|
||||||
|
public class DiveDown extends CardImpl {
|
||||||
|
|
||||||
|
public DiveDown(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}");
|
||||||
|
|
||||||
|
// Target creature you control gets +0/+3 and gains hexproof until end of turn.
|
||||||
|
Effect effect = new BoostTargetEffect(0, 3, Duration.EndOfTurn);
|
||||||
|
effect.setText("Target creature you control gets +0/+3");
|
||||||
|
this.getSpellAbility().addEffect(effect);
|
||||||
|
effect = new GainAbilityTargetEffect(HexproofAbility.getInstance(), Duration.EndOfTurn);
|
||||||
|
effect.setText("and gains hexproof until end of turn");
|
||||||
|
this.getSpellAbility().addEffect(effect);
|
||||||
|
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiveDown(final DiveDown card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DiveDown copy() {
|
||||||
|
return new DiveDown(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,6 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.SetTargetPointer;
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.FilterSpell;
|
import mage.filter.FilterSpell;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
|
@ -92,12 +91,9 @@ class DovescapeEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Spell spell = game.getStack().getSpell(this.getTargetPointer().getFirst(game, source));
|
Spell spell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
|
||||||
int spellCMC = 0;
|
int spellCMC = 0;
|
||||||
UUID spellControllerID = null;
|
UUID spellControllerID = null;
|
||||||
if (spell == null) {
|
|
||||||
spell = (Spell) game.getLastKnownInformation(this.getTargetPointer().getFirst(game, source), Zone.STACK);
|
|
||||||
}
|
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
spellCMC = spell.getConvertedManaCost();
|
spellCMC = spell.getConvertedManaCost();
|
||||||
spellControllerID = spell.getControllerId();
|
spellControllerID = spell.getControllerId();
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class Dreamstealer extends CardImpl {
|
||||||
this.toughness = new MageInt(2);
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
// Menace
|
// Menace
|
||||||
this.addAbility(MenaceAbility.getInstance());
|
this.addAbility(new MenaceAbility());
|
||||||
|
|
||||||
// When Dreamstealer deals combat damage to a player, that player discards that many cards.
|
// When Dreamstealer deals combat damage to a player, that player discards that many cards.
|
||||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DreamstealerDiscardEffect(), false, true));
|
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DreamstealerDiscardEffect(), false, true));
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue