Merge branch 'master' into master

This commit is contained in:
rikimaru1234321 2019-11-08 08:29:36 +08:00 committed by GitHub
commit 64f3bf3534
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
459 changed files with 19117 additions and 2060 deletions

3
.gitignore vendored
View file

@ -152,3 +152,6 @@ mage-bundle
# build-tools config and log files when building client/server with Atom
.build-tools.cson
build-output.log
# Visual Studio Code
.history

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-client</artifactId>

View file

@ -695,13 +695,13 @@ public class MageBook extends JComponent {
int totalTokensEmblems = totalTokens + getTotalNumEmblems(set);
int start = 0;
if (!(page * conf.CARDS_PER_PAGE <= totalTokensEmblems && (page + 1) * conf.CARDS_PER_PAGE >= totalTokensEmblems)) {
start = page * conf.CARDS_PER_PAGE - totalTokensEmblems;
start = Math.max(0, page * conf.CARDS_PER_PAGE - totalTokensEmblems);
pageRight.setVisible(true);
}
int end = planes.size();
if ((page + 1) * conf.CARDS_PER_PAGE < totalTokensEmblems + planes.size()) {
end = (page + 1) * conf.CARDS_PER_PAGE - totalTokensEmblems;
end = Math.max(0, (page + 1) * conf.CARDS_PER_PAGE - totalTokensEmblems);
pageRight.setVisible(true);
} else {
pageRight.setVisible(false);

View file

@ -422,11 +422,10 @@
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/us.png"/>
</Property>
<Property name="text" type="java.lang.String" value="P"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to mtg.powersofwar.com (USA, use any username without registration)"/>
<Property name="text" type="java.lang.String" value="US"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to us.xmage.today (USA, use any username without registration)"/>
<Property name="actionCommand" type="java.lang.String" value="connectXmageus"/>
<Property name="alignmentY" type="float" value="0.0"/>
<Property name="enabled" type="boolean" value="false"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
<Insets value="[2, 2, 2, 2]"/>
</Property>

View file

@ -283,11 +283,10 @@ public class ConnectDialog extends MageDialog {
});
btnFindUs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N
btnFindUs.setText("P");
btnFindUs.setToolTipText("Connect to mtg.powersofwar.com (USA, use any username without registration)");
btnFindUs.setText("US");
btnFindUs.setToolTipText("Connect to us.xmage.today (USA, use any username without registration)");
btnFindUs.setActionCommand("connectXmageus");
btnFindUs.setAlignmentY(0.0F);
btnFindUs.setEnabled(false);
btnFindUs.setMargin(new java.awt.Insets(2, 2, 2, 2));
btnFindUs.setName("connectXmageusBtn"); // NOI18N
btnFindUs.setPreferredSize(new java.awt.Dimension(23, 23));
@ -338,8 +337,6 @@ public class ConnectDialog extends MageDialog {
);
txtPort.addKeyListener(new java.awt.event.KeyAdapter() {
@Override
public void keyTyped(java.awt.event.KeyEvent evt) {
ConnectDialog.this.keyTyped(evt);
}
@ -768,7 +765,7 @@ public class ConnectDialog extends MageDialog {
}//GEN-LAST:event_btnFind2findPublicServerActionPerformed
private void connectXmageus(java.awt.event.ActionEvent evt) {
String serverAddress = "mtg.powersofwar.com";
String serverAddress = "us.xmage.today";
this.txtServer.setText(serverAddress);
this.txtPort.setText("17171");
// Update userName and password according to the chosen server.
@ -777,7 +774,7 @@ public class ConnectDialog extends MageDialog {
}
private void connectBeta(java.awt.event.ActionEvent evt) {
String serverAddress = "xmage.today";
String serverAddress = "beta.xmage.today";
this.txtServer.setText(serverAddress);
this.txtPort.setText("17171");
// Update userName and password according to the chosen server.

View file

@ -637,6 +637,7 @@ public class NewTableDialog extends MageDialog {
case "Variant Magic - Commander":
case "Variant Magic - Duel Commander":
case "Variant Magic - MTGO 1v1 Commander":
case "Variant Magic - Centurion Commander":
case "Variant Magic - Penny Dreadful Commander":
if (!options.getGameType().startsWith("Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE);
@ -683,6 +684,7 @@ public class NewTableDialog extends MageDialog {
if (!options.getDeckType().equals("Variant Magic - Commander")
&& !options.getDeckType().equals("Variant Magic - Duel Commander")
&& !options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander")
&& !options.getDeckType().equals("Variant Magic - Centurion Commander")
&& !options.getDeckType().equals("Variant Magic - Freeform Commander")
&& !options.getDeckType().equals("Variant Magic - Penny Dreadful Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Commander needs also a Commander game type", "Error", JOptionPane.ERROR_MESSAGE);

View file

@ -366,6 +366,20 @@
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JToggleButton" name="btnFormatPioneer">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="Pioneer"/>
<Property name="toolTipText" type="java.lang.String" value="Pioneer format."/>
<Property name="focusPainted" type="boolean" value="false"/>
<Property name="focusable" type="boolean" value="false"/>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnFilterActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JToggleButton" name="btnFormatLegacy">
<Properties>

View file

@ -333,7 +333,7 @@ public class TablesPanel extends javax.swing.JPanel {
filterButtons = new JToggleButton[]{btnStateWaiting, btnStateActive, btnStateFinished,
btnTypeMatch, btnTypeTourneyConstructed, btnTypeTourneyLimited,
btnFormatBlock, btnFormatStandard, btnFormatModern, btnFormatLegacy, btnFormatVintage, btnFormatPremodern, btnFormatCommander, btnFormatTinyLeader, btnFormatLimited, btnFormatOther,
btnSkillBeginner, btnSkillCasual, btnSkillSerious, btnRated, btnUnrated, btnOpen, btnPassword, btnFormatOathbreaker};
btnSkillBeginner, btnSkillCasual, btnSkillSerious, btnRated, btnUnrated, btnOpen, btnPassword, btnFormatOathbreaker, btnFormatPioneer};
JComponent[] components = new JComponent[]{chatPanelMain, jSplitPane1, jScrollPaneTablesActive, jScrollPaneTablesFinished, jPanelTop, jPanelTables};
for (JComponent component : components) {
@ -802,6 +802,9 @@ public class TablesPanel extends javax.swing.JPanel {
if (btnFormatModern.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Modern", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatPioneer.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Pioneer", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatLegacy.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Legacy", TablesTableModel.COLUMN_DECK_TYPE));
}
@ -812,7 +815,7 @@ public class TablesPanel extends javax.swing.JPanel {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Premodern", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatCommander.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Penny Dreadful Commander|^Freeform Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TablesTableModel.COLUMN_DECK_TYPE));
formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Centurion Commander|^Penny Dreadful Commander|^Freeform Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatTinyLeader.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Tiny", TablesTableModel.COLUMN_DECK_TYPE));
@ -965,6 +968,7 @@ public class TablesPanel extends javax.swing.JPanel {
btnFormatBlock = new javax.swing.JToggleButton();
btnFormatStandard = new javax.swing.JToggleButton();
btnFormatModern = new javax.swing.JToggleButton();
btnFormatPioneer = new javax.swing.JToggleButton();
btnFormatLegacy = new javax.swing.JToggleButton();
btnFormatVintage = new javax.swing.JToggleButton();
btnFormatPremodern = new javax.swing.JToggleButton();
@ -1256,6 +1260,20 @@ public class TablesPanel extends javax.swing.JPanel {
});
filterBar2.add(btnFormatModern);
btnFormatPioneer.setSelected(true);
btnFormatPioneer.setText("Pioneer");
btnFormatPioneer.setToolTipText("Pioneer format.");
btnFormatPioneer.setFocusPainted(false);
btnFormatPioneer.setFocusable(false);
btnFormatPioneer.setRequestFocusEnabled(false);
btnFormatPioneer.setVerifyInputWhenFocusTarget(false);
btnFormatPioneer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnFilterActionPerformed(evt);
}
});
filterBar2.add(btnFormatPioneer);
btnFormatLegacy.setSelected(true);
btnFormatLegacy.setText("Legacy");
btnFormatLegacy.setToolTipText("Legacy format.");
@ -1670,6 +1688,7 @@ public class TablesPanel extends javax.swing.JPanel {
private javax.swing.JToggleButton btnFormatLegacy;
private javax.swing.JToggleButton btnFormatLimited;
private javax.swing.JToggleButton btnFormatModern;
private javax.swing.JToggleButton btnFormatPioneer;
private javax.swing.JToggleButton btnFormatOathbreaker;
private javax.swing.JToggleButton btnFormatOther;
private javax.swing.JToggleButton btnFormatPremodern;

View file

@ -20,6 +20,7 @@ public final class ConstructedFormats {
public static final String STANDARD = "- Standard";
public static final String EXTENDED = "- Extended";
public static final String FRONTIER = "- Frontier";
public static final String PIONEER = "- Pioneer";
public static final String MODERN = "- Modern";
public static final String VINTAGE_LEGACY = "- Vintage / Legacy";
public static final String JOKE = "- Joke Sets";
@ -29,6 +30,7 @@ public final class ConstructedFormats {
// Attention -Month is 0 Based so Feb = 1 for example. //
private static final Date extendedDate = new GregorianCalendar(2009, 7, 20).getTime();
private static final Date frontierDate = new GregorianCalendar(2014, 6, 17).getTime();
private static final Date pioneerDate = new GregorianCalendar(2012, 10, 5).getTime();
private static final Date modernDate = new GregorianCalendar(2003, 6, 20).getTime();
// for all sets just return empty list
@ -82,6 +84,7 @@ public final class ConstructedFormats {
underlyingSetCodesPerFormat.put(STANDARD, new ArrayList<>());
underlyingSetCodesPerFormat.put(EXTENDED, new ArrayList<>());
underlyingSetCodesPerFormat.put(FRONTIER, new ArrayList<>());
underlyingSetCodesPerFormat.put(PIONEER, new ArrayList<>());
underlyingSetCodesPerFormat.put(MODERN, new ArrayList<>());
underlyingSetCodesPerFormat.put(VINTAGE_LEGACY, new ArrayList<>());
underlyingSetCodesPerFormat.put(JOKE, new ArrayList<>());
@ -134,6 +137,11 @@ public final class ConstructedFormats {
underlyingSetCodesPerFormat.get(FRONTIER).add(set.getCode());
}
// frontier
if (set.getType().isStandardLegal() && set.getReleaseDate().after(pioneerDate)) {
underlyingSetCodesPerFormat.get(PIONEER).add(set.getCode());
}
// modern
if (set.getType().isModernLegal() && set.getReleaseDate().after(modernDate)) {
underlyingSetCodesPerFormat.get(MODERN).add(set.getCode());
@ -251,6 +259,7 @@ public final class ConstructedFormats {
formats.add(0, JOKE);
formats.add(0, VINTAGE_LEGACY);
formats.add(0, MODERN);
formats.add(0, PIONEER);
formats.add(0, FRONTIER);
formats.add(0, EXTENDED);
formats.add(0, STANDARD);

View file

@ -23,7 +23,9 @@ public class ScryfallImageSupportCards {
put("EURO", "pelp").
put("GPX", "pgpx").
put("MED", "me1").
put("MEDM", "med").build();
put("MEDM", "med").
put("CELD", "eld"). // scryfall moved ELD and CELD cards in one set, but card numbers are different
build();
private static final Set<String> supportedSets = new ArraySet<String>() {
{
@ -240,6 +242,7 @@ public class ScryfallImageSupportCards {
add("M20");
add("C19");
add("ELD");
add("CELD");
//
add("EURO");
add("GPX");

View file

@ -229,7 +229,7 @@ public class ScryfallImageSupportTokens {
put("MH1/Emblem Wrenn and Six", "https://api.scryfall.com/cards/tmh1/21/en?format=image");
put("MH1/Zombie", "https://api.scryfall.com/cards/tmh1/7/en?format=image");
//M19
// M19
put("M19/Emblem Ajani, Adversary of Tyrants", "https://api.scryfall.com/cards/tm19/15/en?format=image");
put("M19/Angel", "https://api.scryfall.com/cards/tm19/1/en?format=image");
put("M19/Avatar", "https://api.scryfall.com/cards/tm19/2/en?format=image");
@ -262,7 +262,7 @@ public class ScryfallImageSupportTokens {
put("M20/Wolf", "https://api.scryfall.com/cards/tm20/8/en?format=image");
put("M20/Zombie", "https://api.scryfall.com/cards/tm20/6/en?format=image");
//C18
// C18
put("C18/Angel", "https://api.scryfall.com/cards/tc18/3/en?format=image");
put("C18/Cat Warrior", "https://api.scryfall.com/cards/tc18/15/en?format=image");
put("C18/Cat", "https://api.scryfall.com/cards/tc18/5/en?format=image");
@ -312,6 +312,26 @@ public class ScryfallImageSupportTokens {
put("C19/Zombie/1", "https://api.scryfall.com/cards/tc19/11/en?format=image");
put("C19/Zombie/2", "https://api.scryfall.com/cards/tc19/10/en?format=image");
// ELD
put("ELD/Bear", "https://api.scryfall.com/cards/teld/8/en?format=image");
put("ELD/Boar", "https://api.scryfall.com/cards/teld/9/en?format=image");
put("ELD/Dwarf", "https://api.scryfall.com/cards/teld/7/en?format=image");
put("ELD/Faerie", "https://api.scryfall.com/cards/teld/5/en?format=image");
put("ELD/Food/1", "https://api.scryfall.com/cards/teld/15/en?format=image");
put("ELD/Food/2", "https://api.scryfall.com/cards/teld/16/en?format=image");
put("ELD/Food/3", "https://api.scryfall.com/cards/teld/17/en?format=image");
put("ELD/Food/4", "https://api.scryfall.com/cards/teld/18/en?format=image");
put("ELD/Emblem Garruk, Cursed Huntsman", "https://api.scryfall.com/cards/teld/19/en?format=image");
put("ELD/Giant", "https://api.scryfall.com/cards/teld/10/en?format=image");
put("ELD/Goat", "https://api.scryfall.com/cards/teld/1/en?format=image");
put("ELD/Human Cleric", "https://api.scryfall.com/cards/teld/11/en?format=image");
put("ELD/Human Rogue", "https://api.scryfall.com/cards/teld/12/en?format=image");
put("ELD/Human Warrior", "https://api.scryfall.com/cards/teld/13/en?format=image");
put("ELD/Human", "https://api.scryfall.com/cards/teld/2/en?format=image");
put("ELD/Knight", "https://api.scryfall.com/cards/teld/3/en?format=image");
put("ELD/Mouse", "https://api.scryfall.com/cards/teld/4/en?format=image");
put("ELD/Rat", "https://api.scryfall.com/cards/teld/6/en?format=image");
put("ELD/Wolf", "https://api.scryfall.com/cards/teld/14/en?format=image");
// generate supported sets
supportedSets.clear();

View file

@ -100,6 +100,7 @@
|Generate|EMBLEM:DOM|Jaya Ballard||Emblem Jaya Ballard|JayaBallardEmblem|
|Generate|EMBLEM:DOM|Teferi, Hero of Dominaria||Emblem Teferi|TeferiHeroOfDominariaEmblem|
|Generate|EMBLEM:AER|Tezzeret the Schemer||Emblem Tezzeret|TezzeretTheSchemerEmblem|
|Generate|EMBLEM:ELD|Garruk, Cursed Huntsman||Emblem Garruk|GarrukCursedHuntsmanEmblem|
|Generate|PLANE:PCA|Plane - Academy At Tolaria West|||AcademyAtTolariaWestPlane|
|Generate|PLANE:PCA|Plane - Agyrem|||AgyremPlane|
|Generate|PLANE:PCA|Plane - Akoum|||AkoumPlane|
@ -1319,3 +1320,21 @@
|Generate|TOK:M20|Treasure|||TreasureToken|
|Generate|TOK:M20|Wolf|||WolfToken|
|Generate|TOK:M20|Zombie|||ZombieToken|
|Generate|TOK:ELD|Bear|||BearToken|
|Generate|TOK:ELD|Boar|||WolfsQuarryToken|
|Generate|TOK:ELD|Dwarf|||DwarfToken|
|Generate|TOK:ELD|Faerie|||FaerieToken|
|Generate|TOK:ELD|Food|1||FoodToken|
|Generate|TOK:ELD|Food|2||FoodToken|
|Generate|TOK:ELD|Food|3||FoodToken|
|Generate|TOK:ELD|Food|4||FoodToken|
|Generate|TOK:ELD|Giant|||GiantOpportunityToken|
|Generate|TOK:ELD|Goat|||GoatToken|
|Generate|TOK:ELD|Human|||HumanToken|
|Generate|TOK:ELD|Human Cleric|||OutlawsMerrimentClericToken|
|Generate|TOK:ELD|Human Rogue|||OutlawsMerrimentRogueToken|
|Generate|TOK:ELD|Human Warrior|||OutlawsMerrimentWarriorToken|
|Generate|TOK:ELD|Knight|||KnightToken|
|Generate|TOK:ELD|Mouse|||MouseToken|
|Generate|TOK:ELD|Rat|||RatToken|
|Generate|TOK:ELD|Wolf|||GarrukCursedHuntsmanToken|

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-common</artifactId>

View file

@ -11,11 +11,11 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
public static final int MAGE_VERSION_MAJOR = 1;
public static final int MAGE_VERSION_MINOR = 4;
public static final int MAGE_VERSION_PATCH = 37;
public static final int MAGE_VERSION_PATCH = 39;
public static final String MAGE_EDITION_INFO = ""; // set "-beta" for 1.4.32-betaV0
public static final String MAGE_VERSION_MINOR_PATCH = "V4"; // default
public static final String MAGE_VERSION_MINOR_PATCH = "V0"; // default
// strict mode
private static final boolean MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME = true; // set true on uncompatible github changes, set false after new major release (after MAGE_VERSION_PATCH changes)
private static final boolean MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME = false; // set true on uncompatible github changes, set false after new major release (after MAGE_VERSION_PATCH changes)
public static final boolean MAGE_VERSION_SHOW_BUILD_TIME = true;
private final int major;

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-counter-plugin</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-plugins</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage.server.console</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-deck-constructed</artifactId>

View file

@ -29,7 +29,6 @@ public class AusHighlander extends Constructed {
pointMap.put("Sol Ring", 3);
pointMap.put("Time Walk", 3);
pointMap.put("Vampiric Tutor", 3);
pointMap.put("Yawgmoth's Will", 3);
pointMap.put("Channel", 2);
pointMap.put("Dig Through Time", 2);
pointMap.put("Library of Alexandria", 2);
@ -37,13 +36,16 @@ public class AusHighlander extends Constructed {
pointMap.put("Mind Twist", 2);
pointMap.put("Mystical Tutor", 2);
pointMap.put("Protean Hulk", 2);
pointMap.put("Strip Mine", 2);
pointMap.put("Tinker", 2);
pointMap.put("Tolarian Academy", 2);
pointMap.put("Treasure Cruise", 2);
pointMap.put("True-Name Nemesis", 2);
pointMap.put("Balance", 1);
pointMap.put("Birthing Pod", 1);
pointMap.put("Crop Rotation", 1);
pointMap.put("Dark Petition", 1);
pointMap.put("Doomsday", 1);
pointMap.put("Enlightened Tutor", 1);
pointMap.put("Fastbond", 1);
pointMap.put("Flash", 1);
@ -57,25 +59,25 @@ public class AusHighlander extends Constructed {
pointMap.put("Lim-Dul's Vault", 1);
pointMap.put("Mana Drain", 1);
pointMap.put("Mana Vault", 1);
pointMap.put("Memory Jar", 1);
pointMap.put("Merchant Scroll", 1);
pointMap.put("Mishra's Workshop", 1);
pointMap.put("Natural Order", 1);
pointMap.put("Oath of Druids", 1);
pointMap.put("Personal Tutor", 1);
pointMap.put("Scheming Symmetry", 1);
pointMap.put("Sensei's Divining Top", 1);
pointMap.put("Skullclamp", 1);
pointMap.put("Snapcaster Mage", 1);
pointMap.put("Stoneforge Mystic", 1);
pointMap.put("Strip Mine", 1);
pointMap.put("Survival of the Fittest", 1);
pointMap.put("Tainted Pact", 1);
pointMap.put("Tendrils of Agony", 1);
pointMap.put("Time Spiral", 1);
pointMap.put("Timetwister", 1);
pointMap.put("True-Name Nemesis", 1);
pointMap.put("Umezawa's Jitte", 1);
pointMap.put("Wasteland", 1);
pointMap.put("Yawgmoth's Bargain", 1);
pointMap.put("Yawgmoth's Will", 1);
}
public AusHighlander() {
@ -133,14 +135,7 @@ public class AusHighlander extends Constructed {
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
int totalPoints = 0;
for (Map.Entry<String, Integer> entry : counts.entrySet()) {

View file

@ -22,8 +22,6 @@ public class Brawl extends Constructed {
// Copy of standard sets
setCodes.addAll(Standard.makeLegalSets());
banned.add("Baral, Chief of Compliance");
banned.add("Smuggler's Copter");
banned.add("Sorcerous Spyglass");
}
@ -49,14 +47,7 @@ public class Brawl extends Constructed {
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) {

View file

@ -20,7 +20,8 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Balance", 1);
pointMap.put("Birthing Pod", 2);
pointMap.put("Black Lotus", 7);
pointMap.put("Demonic Tutor", 3);
pointMap.put("Crop Rotation", 1);
pointMap.put("Demonic Tutor", 4);
pointMap.put("Dig Through Time", 1);
pointMap.put("Enlightened Tutor", 1);
pointMap.put("Flash", 6);
@ -28,7 +29,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Imperial Seal", 1);
pointMap.put("Intuition", 1);
pointMap.put("Library of Alexandria", 1);
pointMap.put("Mana Crypt", 3);
pointMap.put("Mana Crypt", 4);
pointMap.put("Mana Drain", 1);
pointMap.put("Mana Vault", 1);
pointMap.put("Merchant Scroll", 1);
@ -41,7 +42,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Mystical Tutor", 2);
pointMap.put("Natural Order", 4);
pointMap.put("Protean Hulk", 3);
pointMap.put("Sol Ring", 3);
pointMap.put("Sol Ring", 4);
pointMap.put("Spellseeker", 1);
pointMap.put("Stoneforge Mystic", 1);
pointMap.put("Strip Mine", 2);
@ -88,14 +89,7 @@ public class CanadianHighlander extends Constructed {
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
int allowedPoints = 10;
int totalPoints = 0;

View file

@ -0,0 +1,86 @@
package mage.deck;
/**
*
* @author andreacosta
*/
public class CenturionCommander extends Commander {
public CenturionCommander() {
super("Centurion Commander");
banned.add("Ancestral Recall");
banned.add("Ancient Tomb");
banned.add("Back to Basic");
banned.add("Balance");
banned.add("Bazaar of Baghdad");
banned.add("Black Lotus");
banned.add("Cataclysm");
banned.add("Channel");
banned.add("Chaos Orb");
banned.add("Chrome Mox");
banned.add("Demonic Tutor");
banned.add("Dig Through Time");
banned.add("Emrakul, the Aeons Torn");
banned.add("Emrakul, the Promised End");
banned.add("Entomb");
banned.add("Erayo, Soratami Ascendant");
banned.add("Falling Star");
banned.add("Fastbond");
banned.add("Food Chain");
banned.add("Gaeas Cradle");
banned.add("Gifts Ungiven");
banned.add("Grim Monolith");
banned.add("Grindstone");
banned.add("Hermit Druid");
banned.add("High Tide");
banned.add("Humility");
banned.add("Imperial Seal");
banned.add("Karakas");
banned.add("Library of Alexandria");
banned.add("Mana Crypt");
banned.add("Mana Drain");
banned.add("Mana Vault");
banned.add("Mishras Workshop");
banned.add("Mind Twist");
banned.add("Mox Diamond");
banned.add("Mox Emerald");
banned.add("Mox Jet");
banned.add("Mox Pearl");
banned.add("Mox Ruby");
banned.add("Mox Sapphire");
banned.add("Mystical Tutor");
banned.add("Natural Order");
banned.add("Necropotence");
banned.add("Oath of Druids");
banned.add("Protean Hulk");
banned.add("Senseis Diving Top");
banned.add("Serra Ascendant");
banned.add("Sharazad");
banned.add("Survival of the Fittest");
banned.add("Sol Ring");
banned.add("Strip Mine");
banned.add("The Tabernacle at Pendrell Vale");
banned.add("Time Vault");
banned.add("Time Walk");
banned.add("Tinker");
banned.add("Tolarian Academy");
banned.add("Treasure Cruise");
banned.add("Vampiric Tutor");
banned.add("Vanishing");
banned.add("Winter Orb");
banned.add("Yawgmoths Bargain");
bannedCommander.add("Baral, Chief of Compliance");
bannedCommander.add("Derevi, Empyrial Tactician");
bannedCommander.add("Edgar Markov");
bannedCommander.add("Kess, Dissident Mage");
bannedCommander.add("Rofellos, Llanowar Emissary");
bannedPartner.add("Rowan Kenrith");
bannedPartner.add("Tymna the Weaver");
bannedPartner.add("Will Kenrith");
bannedPartner.add("Vial Smasher The Fierce");
}
}

View file

@ -21,7 +21,8 @@ import java.util.*;
*/
public class Commander extends Constructed {
protected List<String> bannedCommander = new ArrayList<>();
protected final List<String> bannedCommander = new ArrayList<>();
protected final List<String> bannedPartner = new ArrayList<>();
protected boolean partnerAllowed = true;
public Commander() {
@ -99,14 +100,7 @@ public class Commander extends Constructed {
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) {
@ -136,20 +130,25 @@ public class Commander extends Constructed {
invalid.put("Commander", "Commander invalid (" + commander.getName() + ')');
valid = false;
}
if (deck.getSideboard().size() == 2 && !commander.getAbilities().contains(PartnerAbility.getInstance())) {
boolean partnersWith = false;
for (Ability ability : commander.getAbilities()) {
if (ability instanceof PartnerWithAbility
&& commanderNames.contains(((PartnerWithAbility) ability).getPartnerName())) {
partnersWith = true;
break;
}
if (deck.getSideboard().size() == 2) {
if (commander.getAbilities().contains(PartnerAbility.getInstance())) {
if (bannedPartner.contains(commander.getName())) {
invalid.put("Commander", "Partner banned (" + commander.getName() + ')');
valid = false;
}
} else {
boolean partnersWith = commander.getAbilities()
.stream()
.filter(PartnerWithAbility.class::isInstance)
.map(PartnerWithAbility.class::cast)
.map(PartnerWithAbility::getPartnerName)
.anyMatch(commanderNames::contains);
if (!partnersWith) {
invalid.put("Commander", "Commander without Partner (" + commander.getName() + ')');
valid = false;
}
}
}
ManaUtil.collectColorIdentity(colorIdentity, commander.getColorIdentity());
}
}

View file

@ -59,14 +59,7 @@ public class FreeformCommander extends Constructed {
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
if (deck.getSideboard().isEmpty() || deck.getSideboard().size() > 2) {
invalid.put("Commander", "Sideboard must contain only the commander(s)");

View file

@ -52,7 +52,6 @@ public class Oathbreaker extends Vintage {
banned.add("Painter's Servant");
banned.add("Panoptic Mirror");
banned.add("Primal Surge");
banned.add("Recurring Nightmare");
banned.add("Saheeli, the Gifted");
banned.add("Sol Ring");
banned.add("Sundering Titan");
@ -99,14 +98,7 @@ public class Oathbreaker extends Vintage {
}
}
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
Set<String> commanderNames = new HashSet<>();
Set<String> signatureSpells = new HashSet<>();

View file

@ -21,6 +21,7 @@ public class Pauper extends Constructed {
rarities.add(Rarity.COMMON);
rarities.add(Rarity.LAND);
banned.add("Arcum's Astrolabe");
banned.add("Cloud of Faeries");
banned.add("Cloudpost");
banned.add("Cranial Plating");

View file

@ -0,0 +1,34 @@
package mage.deck;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.cards.decks.Constructed;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* @author TheElk801
*/
public class Pioneer extends Constructed {
public Pioneer() {
super("Constructed - Pioneer");
Date cutoff = new GregorianCalendar(2012, 10, 5).getTime(); // M15 release date
for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getSetType().isStandardLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) {
setCodes.add(set.getCode());
}
}
banned.add("Bloodstained Mire");
banned.add("Flooded Strand");
banned.add("Polluted Delta");
banned.add("Windswept Heath");
banned.add("Wooded Foothills");
banned.add("Felidar Guardian");
banned.add("Leyline of Abundance");
banned.add("Oath of Nissa");
}
}

View file

@ -54,7 +54,6 @@ public class Premodern extends Constructed {
banned.add("Entomb");
banned.add("Flash");
banned.add("Force of Will");
banned.add("Frantic Search");
banned.add("Goblin Recruiter");
banned.add("Grim Monolith");
banned.add("Jeweled Bird");
@ -76,5 +75,6 @@ public class Premodern extends Constructed {
banned.add("Windfall");
banned.add("Worldgorger Dragon");
banned.add("Yawgmoth's Will");
banned.add("Yawgmoth's Bargain");
}
}

View file

@ -16,6 +16,8 @@ public class Standard extends Constructed {
super("Constructed - Standard");
setCodes.addAll(makeLegalSets());
banned.add("Field of the Dead"); // since 2019-10-21
}
private static boolean isFallSet(ExpansionSet set) {
@ -25,7 +27,7 @@ public class Standard extends Constructed {
return set.getSetType() == SetType.EXPANSION && (cal.get(Calendar.MONTH) > 7);
}
public static List<String> makeLegalSets() {
static List<String> makeLegalSets() {
List<String> codes = new ArrayList<>();
GregorianCalendar current = new GregorianCalendar();
List<ExpansionSet> sets = new ArrayList(Sets.getInstance().values());

View file

@ -113,14 +113,7 @@ public class TinyLeaders extends Constructed {
counts.put(deck.getName(), 1); // add the commander to the counts, so it can't be in the deck or sideboard again
countCards(counts, deck.getCards());
countCards(counts, deck.getSideboard());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
if (!basicLandNames.contains(entry.getKey()) && !anyNumberCardsAllowed.contains(entry.getKey())) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
}
valid = checkCounts(1, counts) && valid;
for (String bannedCard : banned) {
if (counts.containsKey(bannedCard)) {

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-deck-limited</artifactId>

View file

@ -3,6 +3,9 @@ package mage.deck;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckValidator;
import java.util.HashMap;
import java.util.Map;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -29,9 +32,15 @@ public class Limited extends DeckValidator {
if (deck.getCards().size() < getDeckMinSize()) {
invalid.put("Deck", "Must contain at least " + getDeckMinSize() + " cards: has only " + deck.getCards().size() + " cards");
valid = false;
}
Map<String, Integer> counts = new HashMap<>();
countCards(counts, deck.getCards());
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 7 && entry.getKey().equals("Seven Dwarves")) {
invalid.put(entry.getKey(), "Too many: " + entry.getValue());
valid = false;
}
}
return valid;
}
}

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-brawlduel</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-brawlfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-canadianhighlanderduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-commanderduel</artifactId>

View file

@ -22,7 +22,7 @@ public class CommanderDuelMatch extends MatchImpl {
startLife = 20; // Starting with the Commander 2016 update (on November 11th, 2016), Duel Commander will be played with 20 life points instead of 30.
checkCommanderDamage = false; // since nov 16 duel commander uses no longer commander damage rule
}
if (options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander")) {
if (options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander") || options.getDeckType().equals("Variant Magic - Centurion Commander")) {
startLife = 30;
}
Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans());

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-commanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-freeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-freeformcommanderduel</artifactId>

View file

@ -15,7 +15,7 @@ public class FreeformCommanderDuelMatch extends MatchImpl {
@Override
public void startGame() throws GameException {
int startLife = 20;
int startLife = 40;
Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans());
FreeformCommanderDuel game = new FreeformCommanderDuel(options.getAttackOption(), options.getRange(), mulligan, startLife);

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-freeformcommanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-momirduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-momirfreeforall</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-oathbreakerduel</artifactId>
@ -22,7 +22,7 @@
<dependency>
<groupId>org.mage</groupId>
<artifactId>mage-game-oathbreakerfreeforall</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
<scope>compile</scope>
</dependency>
</dependencies>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-oathbreakerfreeforall</artifactId>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-pennydreadfulcommanderfreeforall</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-tinyleadersduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-game-twoplayerduel</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-player-ai-draftbot</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-player-ai-ma</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-player-ai</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-player-ai-mcts</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-player-aiminimax</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-player-human</artifactId>

View file

@ -708,7 +708,11 @@ public class HumanPlayer extends PlayerImpl {
while (!abort) {
prepareForResponse(game);
if (!isExecutingMacro()) {
game.fireSelectTargetEvent(playerId, new MessageToClient(target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), getRelatedObjectName(source, game)),
String selectedNames = target.getTargetedName(game);
game.fireSelectTargetEvent(playerId, new MessageToClient(target.getMessage()
+ "<br> Amount remaining: " + target.getAmountRemaining()
+ (selectedNames.isEmpty() ? "" : ", selected: " + selectedNames),
getRelatedObjectName(source, game)),
target.possibleTargets(source == null ? null : source.getSourceId(), playerId, game),
target.isRequired(source),
getOptions(target, null));
@ -717,8 +721,19 @@ public class HumanPlayer extends PlayerImpl {
if (response.getUUID() != null) {
if (target.canTarget(response.getUUID(), source, game)) {
UUID targetId = response.getUUID();
MageObject targetObject = game.getObject(targetId);
boolean removeMode = target.getTargets().contains(targetId)
&& chooseUse(outcome, "What do you want to do with " + (targetObject != null ? targetObject.getLogName() : "target") + "?", "",
"Remove from selected", "Add extra amount", source, game);
if (removeMode) {
target.remove(targetId);
} else {
int amountSelected = getAmount(1, target.getAmountRemaining(), "Select amount", game);
target.addTarget(targetId, amountSelected, source, game);
}
return true;
}
} else if (!target.isRequired(source)) {

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-tournament-boosterdraft</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-tournament-constructed</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-tournament-sealed</artifactId>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-server-plugins</artifactId>

View file

@ -149,6 +149,7 @@
<deckType name="Constructed - Standard" jar="mage-deck-constructed.jar" className="mage.deck.Standard"/>
<deckType name="Constructed - Extended" jar="mage-deck-constructed.jar" className="mage.deck.Extended"/>
<deckType name="Constructed - Frontier" jar="mage-deck-constructed.jar" className="mage.deck.Frontier"/>
<deckType name="Constructed - Pioneer" jar="mage-deck-constructed.jar" className="mage.deck.Pioneer"/>
<deckType name="Constructed - Modern" jar="mage-deck-constructed.jar" className="mage.deck.Modern"/>
<deckType name="Constructed - Modern - No Banned List" jar="mage-deck-constructed.jar" className="mage.deck.ModernNoBannedList"/>
<deckType name="Constructed - Eternal" jar="mage-deck-constructed.jar" className="mage.deck.Eternal"/>
@ -169,6 +170,7 @@
<deckType name="Variant Magic - Commander" jar="mage-deck-constructed.jar" className="mage.deck.Commander"/>
<deckType name="Variant Magic - Duel Commander" jar="mage-deck-constructed.jar" className="mage.deck.DuelCommander"/>
<deckType name="Variant Magic - MTGO 1v1 Commander" jar="mage-deck-constructed.jar" className="mage.deck.MTGO1v1Commander"/>
<deckType name="Variant Magic - Centurion Commander" jar="mage-deck-constructed.jar" className="mage.deck.CenturionCommander"/>
<deckType name="Variant Magic - Tiny Leaders" jar="mage-deck-constructed.jar" className="mage.deck.TinyLeaders"/>
<deckType name="Variant Magic - Momir Basic" jar="mage-deck-constructed.jar" className="mage.deck.Momir"/>
<deckType name="Variant Magic - Penny Dreadful Commander" jar="mage-deck-constructed.jar" className="mage.deck.PennyDreadfulCommander"/>

View file

@ -6,7 +6,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-server</artifactId>
@ -91,7 +91,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.18</version>
<version>[1.19,)</version>
</dependency>
<dependency>

View file

@ -143,6 +143,7 @@
<deckType name="Constructed - Standard" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Standard"/>
<deckType name="Constructed - Extended" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Extended"/>
<deckType name="Constructed - Frontier" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Frontier"/>
<deckType name="Constructed - Pioneer" jar="mage-deck-constructed.jar" className="mage.deck.Pioneer"/>
<deckType name="Constructed - Modern" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Modern"/>
<deckType name="Constructed - Modern - No Banned List" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.ModernNoBannedList"/>
<deckType name="Constructed - Eternal" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Eternal"/>
@ -163,6 +164,7 @@
<deckType name="Variant Magic - Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Commander"/>
<deckType name="Variant Magic - Duel Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.DuelCommander"/>
<deckType name="Variant Magic - MTGO 1v1 Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.MTGO1v1Commander"/>
<deckType name="Variant Magic - Centurion Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.CenturionCommander"/>
<deckType name="Variant Magic - Tiny Leaders" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.TinyLeaders"/>
<deckType name="Variant Magic - Momir Basic" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Momir"/>
<deckType name="Variant Magic - Penny Dreadful Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.PennyDreadfulCommander"/>

View file

@ -7,7 +7,7 @@
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-root</artifactId>
<version>1.4.37</version>
<version>1.4.39</version>
</parent>
<artifactId>mage-sets</artifactId>

View file

@ -1,7 +1,5 @@
package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -24,24 +22,25 @@ import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
*
* @author cbt33
*/
public final class AboshanCephalidEmperor extends CardImpl {
static final FilterControlledCreaturePermanent filter1 = new FilterControlledCreaturePermanent("untapped Cephalid you control");
static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creatures without flying");
static final FilterControlledCreaturePermanent filter1 = new FilterControlledCreaturePermanent("untapped Cephalid you control");
static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creatures without flying");
static {
static {
filter1.add(new SubtypePredicate(SubType.CEPHALID));
filter2.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
}
}
public AboshanCephalidEmperor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.CEPHALID);
this.subtype.add(SubType.CEPHALID, SubType.NOBLE);
this.power = new MageInt(3);
this.toughness = new MageInt(3);

View file

@ -0,0 +1,79 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.filter.predicate.permanent.AnotherPredicate;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AcclaimedContender extends CardImpl {
private static final FilterPermanent filter = new FilterControlledPermanent(SubType.KNIGHT);
private static final FilterCard filter2
= new FilterCard("a Knight, Aura, Equipment, or legendary artifact card");
static {
filter.add(AnotherPredicate.instance);
filter2.add(Predicates.or(
new SubtypePredicate(SubType.KNIGHT),
new SubtypePredicate(SubType.AURA),
new SubtypePredicate(SubType.EQUIPMENT),
Predicates.and(
new SupertypePredicate(SuperType.LEGENDARY),
new CardTypePredicate(CardType.ARTIFACT)
)
));
}
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
public AcclaimedContender(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// When Acclaimed Contender enters the battlefield, if you control another Knight, look at the top five cards of your library. You may reveal a Knight, Aura, Equipment, or legendary artifact card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect(
new StaticValue(5), false, new StaticValue(1), filter2, Zone.LIBRARY, false,
true, false, Zone.HAND, true, false, false
).setBackInRandomOrder(true)), condition, "When {this} enters the battlefield, " +
"if you control another Knight, look at the top five cards of your library. " +
"You may reveal a Knight, Aura, Equipment, or legendary artifact card from among them " +
"and put it into your hand. Put the rest on the bottom of your library in a random order."
));
}
private AcclaimedContender(final AcclaimedContender card) {
super(card);
}
@Override
public AcclaimedContender copy() {
return new AcclaimedContender(this);
}
}

View file

@ -23,7 +23,6 @@ import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class AkoumHellkite extends CardImpl {
@ -56,9 +55,6 @@ public final class AkoumHellkite extends CardImpl {
class AkoumHellkiteTriggeredAbility extends TriggeredAbilityImpl {
private static final String text = "<i>Landfall</i> &mdash; Whenever a land enters the battlefield under your control, {this} deals 1 damage to any target. "
+ "If that land is a Mountain, Akoum Hellkite deals 2 damage to that permanent or player instead.";
public AkoumHellkiteTriggeredAbility() {
super(Zone.BATTLEFIELD, new AkoumHellkiteDamageEffect());
}
@ -98,7 +94,8 @@ class AkoumHellkiteTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return text;
return "<i>Landfall</i> &mdash; Whenever a land enters the battlefield under your control, " +
"{this} deals 1 damage to any target. If that land is a Mountain, {this} deals 2 damage instead.";
}
}

View file

@ -34,7 +34,7 @@ import java.util.UUID;
*
* @author Colin Redman
*/
public class AminatouTheFateShifter extends CardImpl {
public class AminatouTheFateshifter extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("permanent you own");
@ -43,7 +43,7 @@ public class AminatouTheFateShifter extends CardImpl {
filter.add(AnotherPredicate.instance);
}
public AminatouTheFateShifter(UUID ownerId, CardSetInfo setInfo) {
public AminatouTheFateshifter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{W}{U}{B}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AMINATOU);
@ -69,13 +69,13 @@ public class AminatouTheFateShifter extends CardImpl {
this.addAbility(CanBeYourCommanderAbility.getInstance());
}
public AminatouTheFateShifter(final AminatouTheFateShifter card) {
public AminatouTheFateshifter(final AminatouTheFateshifter card) {
super(card);
}
@Override
public AminatouTheFateShifter copy() {
return new AminatouTheFateShifter(this);
public AminatouTheFateshifter copy() {
return new AminatouTheFateshifter(this);
}
}

View file

@ -0,0 +1,93 @@
package mage.cards.a;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class Apathy extends CardImpl {
public Apathy(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Enchanted creature doesn't untap during its controller's untap step.
this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepEnchantedEffect()));
// At the beginning of the upkeep of enchanted creatures controller, that player may discard a card at random. If the player does, untap that creature.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(
new ApathyEffect(), TargetController.CONTROLLER_ATTACHED_TO, false
));
}
private Apathy(final Apathy card) {
super(card);
}
@Override
public Apathy copy() {
return new Apathy(this);
}
}
class ApathyEffect extends OneShotEffect {
ApathyEffect() {
super(Outcome.Benefit);
staticText = "that player may discard a card at random. If the player does, untap that creature";
}
private ApathyEffect(final ApathyEffect effect) {
super(effect);
}
@Override
public ApathyEffect copy() {
return new ApathyEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(game.getActivePlayerId());
if (player == null) {
return false;
}
if (!player.chooseUse(outcome, "Discard a card at random to untap enchanted creature?", source, game)
|| player.discardOne(true, source, game) == null) {
return false;
}
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent == null) {
return false;
}
permanent = game.getPermanent(permanent.getAttachedTo());
return permanent != null && permanent.untap(game);
}
}

View file

@ -1,6 +1,7 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.abilities.keyword.FlyingAbility;
@ -32,7 +33,7 @@ public final class ArcanistsOwl extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Arcanist's Owl enters the battlefield, look at the top four cards of your library. You may reveal an artifact or enchantment card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
this.getSpellAbility().addEffect(
this.addAbility(new EntersBattlefieldTriggeredAbility(
new LookLibraryAndPickControllerEffect(
new StaticValue(4), false, new StaticValue(1), filter,
Zone.LIBRARY, false, true, false, Zone.HAND,
@ -40,7 +41,7 @@ public final class ArcanistsOwl extends CardImpl {
).setBackInRandomOrder(true).setText("Look at the top four cards of your library. " +
"You may reveal an artifact or enchantment from among them and put it into your hand. " +
"Put the rest on the bottom of your library in a random order.")
);
));
}
private ArcanistsOwl(final ArcanistsOwl card) {

View file

@ -73,7 +73,7 @@ class ArchfiendOfSpiteAbility extends TriggeredAbilityImpl {
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
return event.getType() == GameEvent.EventType.DAMAGED_CREATURE;
}
@Override

View file

@ -0,0 +1,49 @@
package mage.cards.a;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.combat.CantAttackYouUnlessPayManaAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ArchonOfAbsolution extends CardImpl {
public ArchonOfAbsolution(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.ARCHON);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Protection from white
this.addAbility(ProtectionAbility.from(ObjectColor.WHITE));
// Creatures can't attack you or a planeswalker you control unless their controller pays {1} for each of those creatures.
this.addAbility(new SimpleStaticAbility(
new CantAttackYouUnlessPayManaAllEffect(new ManaCostsImpl("{1}"), true)
));
}
private ArchonOfAbsolution(final ArchonOfAbsolution card) {
super(card);
}
@Override
public ArchonOfAbsolution copy() {
return new ArchonOfAbsolution(this);
}
}

View file

@ -0,0 +1,74 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalRestrictionEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.Game;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ArcticFoxes extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
static {
filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 1));
}
public ArcticFoxes(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.FOX);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Creatures with power 2 or greater can't block Arctic Foxes as long as defending player controls a snow land.
this.addAbility(new SimpleStaticAbility(new ConditionalRestrictionEffect(
new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield),
ArcticFoxesCondition.instance, "creatures with power 2 or greater can't block {this}" +
" as long as defending player controls a snow land"
)));
}
private ArcticFoxes(final ArcticFoxes card) {
super(card);
}
@Override
public ArcticFoxes copy() {
return new ArcticFoxes(this);
}
}
enum ArcticFoxesCondition implements Condition {
instance;
private static final FilterPermanent filter = new FilterLandPermanent();
static {
filter.add(new SupertypePredicate(SuperType.SNOW));
}
@Override
public boolean apply(Game game, Ability source) {
UUID defenderId = game.getCombat().getDefendingPlayerId(source.getSourceId(), game);
if (defenderId == null) {
return false;
}
return game.getBattlefield().contains(filter, defenderId, 1, game);
}
}

View file

@ -0,0 +1,46 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.condition.common.AdamantCondition;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.watchers.common.ManaSpentToCastWatcher;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ArdenvalePaladin extends CardImpl {
public ArdenvalePaladin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.power = new MageInt(2);
this.toughness = new MageInt(5);
// Adamant If at least three white mana was spent to cast this spell, Ardenvale Paladin enters the battlefield with a +1/+1 counter on it.
this.addAbility(new EntersBattlefieldAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance()),
AdamantCondition.WHITE, "<br><i>Adamant</i> &mdash; " +
"If at least three white mana was spent to cast this spell, " +
"{this} enters the battlefield with a +1/+1 counter on it.", ""
), new ManaSpentToCastWatcher());
}
private ArdenvalePaladin(final ArdenvalePaladin card) {
super(card);
}
@Override
public ArdenvalePaladin copy() {
return new ArdenvalePaladin(this);
}
}

View file

@ -0,0 +1,44 @@
package mage.cards.a;
import mage.MageInt;
import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.AdventureCard;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ArdenvaleTactician extends AdventureCard {
public ArdenvaleTactician(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, new CardType[]{CardType.INSTANT}, "{1}{W}{W}", "Dizzying Swoop", "{1}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Dizzying Swoop
// Tap up to two target creatures.
this.getAdventureSpellAbility().addEffect(new TapTargetEffect());
this.getAdventureSpellAbility().addTarget(new TargetCreaturePermanent(0, 2));
}
private ArdenvaleTactician(final ArdenvaleTactician card) {
super(card);
}
@Override
public ArdenvaleTactician copy() {
return new ArdenvaleTactician(this);
}
}

View file

@ -0,0 +1,70 @@
package mage.cards.a;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class AyaraFirstOfLocthwain extends CardImpl {
private static final FilterPermanent filter
= new FilterCreaturePermanent("{this} or another black creature");
private static final FilterControlledPermanent filter2
= new FilterControlledCreaturePermanent("another black creature");
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
filter2.add(new ColorPredicate(ObjectColor.BLACK));
}
public AyaraFirstOfLocthwain(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}{B}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ELF);
this.subtype.add(SubType.NOBLE);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Whenever Ayara, First of Locthwain or another black creature enters the battlefield under your control, each opponent loses 1 life and you gain 1 life.
Ability ability = new EntersBattlefieldControlledTriggeredAbility(new LoseLifeOpponentsEffect(1), filter);
ability.addEffect(new GainLifeEffect(1).concatBy("and"));
this.addAbility(ability);
// {T}, Sacrifice another black creature: Draw a card.
ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter2)));
this.addAbility(ability);
}
private AyaraFirstOfLocthwain(final AyaraFirstOfLocthwain card) {
super(card);
}
@Override
public AyaraFirstOfLocthwain copy() {
return new AyaraFirstOfLocthwain(this);
}
}

View file

@ -23,11 +23,11 @@ import mage.game.permanent.Permanent;
*
* @author jeffwadsworth
*/
public final class AzoriusAEthermage extends CardImpl {
public final class AzoriusAethermage extends CardImpl {
private static final String rule = "Whenever a permanent is returned to your hand, ";
public AzoriusAEthermage(UUID ownerId, CardSetInfo setInfo) {
public AzoriusAethermage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}");
this.subtype.add(SubType.HUMAN);
@ -40,13 +40,13 @@ public final class AzoriusAEthermage extends CardImpl {
this.addAbility(new AzoriusAEthermageAbility(Zone.BATTLEFIELD, Zone.BATTLEFIELD, Zone.HAND, effect, new FilterPermanent(), rule, true));
}
public AzoriusAEthermage(final AzoriusAEthermage card) {
public AzoriusAethermage(final AzoriusAethermage card) {
super(card);
}
@Override
public AzoriusAEthermage copy() {
return new AzoriusAEthermage(this);
public AzoriusAethermage copy() {
return new AzoriusAethermage(this);
}
}

View file

@ -0,0 +1,52 @@
package mage.cards.b;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.AttackingPredicate;
import mage.target.common.TargetAttackingCreature;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BargeIn extends CardImpl {
private static final FilterPermanent filter
= new FilterCreaturePermanent("Each attacking non-Human creature");
static {
filter.add(AttackingPredicate.instance);
filter.add(Predicates.not(new SubtypePredicate(SubType.HUMAN)));
}
public BargeIn(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}");
// Target attacking creature gets +2/+2 until end of turn. Each attacking non-Human creature gains trample until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn));
this.getSpellAbility().addEffect(new GainAbilityAllEffect(
TrampleAbility.getInstance(), Duration.EndOfTurn, filter
));
this.getSpellAbility().addTarget(new TargetAttackingCreature());
}
private BargeIn(final BargeIn card) {
super(card);
}
@Override
public BargeIn copy() {
return new BargeIn(this);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealtDamageAndDiedTriggeredAbility;
@ -22,8 +20,9 @@ import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class BaronSengir extends CardImpl {
@ -36,9 +35,9 @@ public final class BaronSengir extends CardImpl {
}
public BaronSengir(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{B}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}{B}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.VAMPIRE);
this.subtype.add(SubType.VAMPIRE, SubType.NOBLE);
this.power = new MageInt(5);
this.toughness = new MageInt(5);

View file

@ -0,0 +1,50 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BarrowWitches extends CardImpl {
private static final FilterCard filter = new FilterCard("Knight card from your graveyard");
static {
filter.add(new SubtypePredicate(SubType.KNIGHT));
}
public BarrowWitches(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARLOCK);
this.power = new MageInt(3);
this.toughness = new MageInt(4);
// When Barrow Witches enters the battlefield, return target Knight card from your graveyard to your hand.
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
private BarrowWitches(final BarrowWitches card) {
super(card);
}
@Override
public BarrowWitches copy() {
return new BarrowWitches(this);
}
}

View file

@ -0,0 +1,66 @@
package mage.cards.b;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DiscardCardControllerTriggeredAbility;
import mage.abilities.meta.OrTriggeredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.game.permanent.token.FoodToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BarteredCow extends CardImpl {
private static final FilterCard filter = new FilterCard();
static {
filter.add(BarteredCowPredicate.instance);
}
public BarteredCow(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.OX);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// When Bartered Cow dies or when you discard it, create a Food token.
this.addAbility(new OrTriggeredAbility(
Zone.ALL, new CreateTokenEffect(new FoodToken()), false,
"When {this} dies or when you discard it, ", new DiesTriggeredAbility((Effect) null),
new DiscardCardControllerTriggeredAbility(null, false, filter)
));
}
private BarteredCow(final BarteredCow card) {
super(card);
}
@Override
public BarteredCow copy() {
return new BarteredCow(this);
}
}
enum BarteredCowPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<MageObject>> {
instance;
@Override
public boolean apply(ObjectSourcePlayer<MageObject> input, Game game) {
return input.getObject().getId().equals(input.getSourceId());
}
}

View file

@ -36,11 +36,11 @@ public final class BatwingBrume extends CardImpl {
// Prevent all combat damage that would be dealt this turn if {W} was spent to cast Batwing Brume. Each player loses 1 life for each attacking creature he or she controls if {B} was spent to cast Batwing Brume.
Effect effect = new ConditionalReplacementEffect(new PreventAllDamageByAllPermanentsEffect(Duration.EndOfTurn, true),
new LockedInCondition(new ManaWasSpentCondition(ColoredManaSymbol.W)));
effect.setText("Prevent all combat damage that would be dealt this turn if {W} was spent to cast {this}");
effect.setText("Prevent all combat damage that would be dealt this turn if {W} was spent to cast this spell");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new BatwingBrumeEffect(),
new ManaWasSpentCondition(ColoredManaSymbol.B), "Each player loses 1 life for each attacking creature he or she controls if {B} was spent to cast {this}"));
new ManaWasSpentCondition(ColoredManaSymbol.B), "Each player loses 1 life for each attacking creature he or she controls if {B} was spent to cast this spell"));
this.getSpellAbility().addEffect(new InfoEffect("<i>(Do both if {W}{B} was spent.)</i>"));
this.getSpellAbility().addWatcher(new ManaSpentToCastWatcher());

View file

@ -14,6 +14,7 @@ import mage.abilities.keyword.ProwessAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.filter.common.FilterInstantOrSorceryCard;
/**
@ -29,7 +30,7 @@ public final class BedlamReveler extends CardImpl {
this.toughness = new MageInt(4);
// Bedlam Reveler costs {1} less to cast for each instant or sorcery card in your graveyard.
Ability ability = new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(new FilterInstantOrSorceryCard()));
Ability ability = new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY));
ability.setRuleAtTheTop(true);
this.addAbility(ability);

View file

@ -0,0 +1,55 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BelovedPrincess extends CardImpl {
private static final FilterCreaturePermanent filter
= new FilterCreaturePermanent("creatures with power 3 or greater");
static {
filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 2));
}
public BelovedPrincess(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.NOBLE);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
// Beloved Princess can't be blocked by creatures with power 3 or greater.
this.addAbility(new SimpleStaticAbility(
new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield)
));
}
private BelovedPrincess(final BelovedPrincess card) {
super(card);
}
@Override
public BelovedPrincess copy() {
return new BelovedPrincess(this);
}
}

View file

@ -37,12 +37,10 @@ public final class BiomancersFamiliar extends CardImpl {
this.toughness = new MageInt(2);
// Activated abilities of creatures you control cost {2} less to activate. This effect can't reduce the amount of mana an ability costs to activate to less than one mana.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BiomancersFamiliarCostReductionEffect()));
this.addAbility(new SimpleStaticAbility(new BiomancersFamiliarCostReductionEffect()));
// {T}: The next time target creature adapts this turn, it adapts as though it had no +1/+1 counters on it.
Ability ability = new SimpleActivatedAbility(
new BiomancersFamiliarReplacementEffect(), new TapSourceCost()
);
Ability ability = new SimpleActivatedAbility(new BiomancersFamiliarReplacementEffect(), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
@ -74,7 +72,9 @@ class BiomancersFamiliarCostReductionEffect extends CostModificationEffectImpl {
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
Player controller = game.getPlayer(abilityToModify.getControllerId());
if (controller != null) {
if (controller == null) {
return false;
}
Mana mana = abilityToModify.getManaCostsToPay().getMana();
int reduceMax = mana.getGeneric();
if (reduceMax > 0 && mana.count() == mana.getGeneric()) {
@ -83,7 +83,9 @@ class BiomancersFamiliarCostReductionEffect extends CostModificationEffectImpl {
if (reduceMax > 2) {
reduceMax = 2;
}
if (reduceMax > 0) {
if (reduceMax <= 0) {
return true;
}
ChoiceImpl choice = new ChoiceImpl(true);
Set<String> set = new LinkedHashSet<>();
@ -97,24 +99,21 @@ class BiomancersFamiliarCostReductionEffect extends CostModificationEffectImpl {
}
int reduce = Integer.parseInt(choice.getChoice());
CardUtil.reduceCost(abilityToModify, reduce);
}
return true;
}
return false;
}
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify.getAbilityType() == AbilityType.ACTIVATED
|| (abilityToModify.getAbilityType() == AbilityType.MANA && abilityToModify instanceof ActivatedAbility)) {
if (abilityToModify.getAbilityType() != AbilityType.ACTIVATED
&& (abilityToModify.getAbilityType() != AbilityType.MANA
|| !(abilityToModify instanceof ActivatedAbility))) {
return false;
}
//Activated abilities of creatures you control
Permanent permanent = game.getPermanent(abilityToModify.getSourceId());
if (permanent != null && permanent.isCreature() && permanent.isControlledBy(source.getControllerId())) {
return true;
}
}
return false;
return permanent != null && permanent.isCreature()
&& permanent.isControlledBy(source.getControllerId());
}
@Override

View file

@ -0,0 +1,61 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.Effect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.abilities.keyword.FlashAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author Tsirides
*/
public final class BlacklanceParagon extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.KNIGHT, "Knight");
public BlacklanceParagon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.power = new MageInt(3);
this.toughness = new MageInt(1);
// Flash
this.addAbility(FlashAbility.getInstance());
// When Blacklance Paragon enters the battlefield, target Knight gains deathtouch and lifelink until end of turn.
Effect effect = new GainAbilityTargetEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn);
effect.setText("target Knight gains deathtouch");
Ability ability = new EntersBattlefieldTriggeredAbility(effect);
effect = new GainAbilityTargetEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn);
effect.setText("and lifelink until end of turn");
ability.addEffect(effect);
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
}
public BlacklanceParagon(final BlacklanceParagon card) {
super(card);
}
@Override
public BlacklanceParagon copy() {
return new BlacklanceParagon(this);
}
}

View file

@ -0,0 +1,83 @@
package mage.cards.b;
import mage.abilities.Ability;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.continuous.LoseAbilityAllEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.DamageCreatureEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BlindFury extends CardImpl {
public BlindFury(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}{R}");
// All creatures lose trample until end of turn. If a creature would deal combat damage to a creature this turn, it deals double that damage to that creature instead.
this.getSpellAbility().addEffect(new LoseAbilityAllEffect(
TrampleAbility.getInstance(), Duration.EndOfTurn,
StaticFilters.FILTER_PERMANENT_CREATURES
).setText("All creatures lose trample until end of turn."));
this.getSpellAbility().addEffect(new FurnaceOfRathEffect());
}
private BlindFury(final BlindFury card) {
super(card);
}
@Override
public BlindFury copy() {
return new BlindFury(this);
}
}
class FurnaceOfRathEffect extends ReplacementEffectImpl {
FurnaceOfRathEffect() {
super(Duration.EndOfTurn, Outcome.Damage);
staticText = "If a creature would deal combat damage to a creature this turn, " +
"it deals double that damage to that creature instead";
}
private FurnaceOfRathEffect(final FurnaceOfRathEffect effect) {
super(effect);
}
@Override
public FurnaceOfRathEffect copy() {
return new FurnaceOfRathEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGE_CREATURE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Permanent permanent = game.getPermanent(event.getSourceId());
return permanent != null
&& permanent.isCreature()
&& ((DamageCreatureEvent) event).isCombatDamage();
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
event.setAmount(CardUtil.addWithOverflowCheck(event.getAmount(), event.getAmount()));
return false;
}
}

View file

@ -1,6 +1,5 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
@ -16,13 +15,15 @@ import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author North
*/
public final class BlindZealot extends CardImpl {
@ -42,7 +43,7 @@ public final class BlindZealot extends CardImpl {
this.addAbility(ability);
}
public BlindZealot(final BlindZealot card) {
private BlindZealot(final BlindZealot card) {
super(card);
}
@ -54,11 +55,11 @@ public final class BlindZealot extends CardImpl {
class BlindZealotTriggeredAbility extends TriggeredAbilityImpl {
public BlindZealotTriggeredAbility() {
BlindZealotTriggeredAbility() {
super(Zone.BATTLEFIELD, new DoIfCostPaid(new DestroyTargetEffect(), new SacrificeSourceCost()), true);
}
public BlindZealotTriggeredAbility(final BlindZealotTriggeredAbility ability) {
private BlindZealotTriggeredAbility(final BlindZealotTriggeredAbility ability) {
super(ability);
}
@ -75,15 +76,17 @@ class BlindZealotTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Player opponent = game.getPlayer(event.getPlayerId());
if (opponent != null && event.getSourceId().equals(this.sourceId)) {
if (opponent == null
|| !event.getSourceId().equals(this.sourceId)
|| !((DamagedEvent) event).isCombatDamage()) {
return false;
}
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature " + opponent.getLogName() + " controls");
filter.add(new ControllerIdPredicate(opponent.getId()));
this.getTargets().clear();
this.addTarget(new TargetCreaturePermanent(filter));
return true;
}
return false;
}
@Override
public String getRule() {

View file

@ -56,7 +56,7 @@ class BloodForBonesEffect extends OneShotEffect {
= new FilterCreatureCard("creature card in your graveyard (to put into your hand");
BloodForBonesEffect() {
super(Outcome.Benefit);
super(Outcome.PutCardInPlay);
staticText = "Return a creature card from your graveyard to the battlefield, " +
"then return another creature card from your graveyard to your hand.";
}

View file

@ -0,0 +1,47 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DrawSecondCardTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BloodhazeWolverine extends CardImpl {
public BloodhazeWolverine(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.WOLVERINE);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// Whenever you draw your second card each turn, Bloodhaze Wolverine gets +1/+1 and gains first strike until end of turn.
Ability ability = new DrawSecondCardTriggeredAbility(new BoostSourceEffect(
1, 1, Duration.EndOfTurn
).setText("{this} gets +1/+1"), false);
ability.addEffect(new GainAbilitySourceEffect(
FirstStrikeAbility.getInstance(), Duration.EndOfTurn
).setText("and gains first strike until end of turn"));
this.addAbility(ability);
}
private BloodhazeWolverine(final BloodhazeWolverine card) {
super(card);
}
@Override
public BloodhazeWolverine copy() {
return new BloodhazeWolverine(this);
}
}

View file

@ -0,0 +1,70 @@
package mage.cards.b;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.combat.CantBlockTargetEffect;
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.game.Game;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
import java.util.Collection;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BlowYourHouseDown extends CardImpl {
public BlowYourHouseDown(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
// Up to three target creatures can't block this turn. Destroy any of them that are Walls.
this.getSpellAbility().addEffect(new CantBlockTargetEffect(Duration.EndOfTurn));
this.getSpellAbility().addEffect(new BlowYourHouseDownEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 3));
}
private BlowYourHouseDown(final BlowYourHouseDown card) {
super(card);
}
@Override
public BlowYourHouseDown copy() {
return new BlowYourHouseDown(this);
}
}
class BlowYourHouseDownEffect extends OneShotEffect {
BlowYourHouseDownEffect() {
super(Outcome.Benefit);
staticText = "Destroy any of them that are Walls";
}
private BlowYourHouseDownEffect(final BlowYourHouseDownEffect effect) {
super(effect);
}
@Override
public BlowYourHouseDownEffect copy() {
return new BlowYourHouseDownEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
source.getTargets()
.stream()
.map(Target::getTargets)
.flatMap(Collection::stream)
.map(game::getPermanent)
.filter(permanent -> permanent != null && permanent.hasSubtype(SubType.WALL, game))
.forEach(permanent -> permanent.destroy(source.getSourceId(), game, false));
return true;
}
}

View file

@ -0,0 +1,55 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.common.FilterControlledPermanent;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BogNaughty extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.FOOD, "a Food");
public BogNaughty(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.subtype.add(SubType.FAERIE);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// {2}{B}, Sacrifice a Food: Target creature gets -3/-3 until end of turn.
Ability ability = new SimpleActivatedAbility(
new BoostTargetEffect(-3, -3, Duration.EndOfTurn), new ManaCostsImpl("{2}{B}")
);
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter)));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
private BogNaughty(final BogNaughty card) {
super(card);
}
@Override
public BogNaughty copy() {
return new BogNaughty(this);
}
}

View file

@ -0,0 +1,82 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BecomesTargetTriggeredAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.AdventureCard;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.common.TargetAnyTarget;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BonecrusherGiant extends AdventureCard {
public BonecrusherGiant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, new CardType[]{CardType.INSTANT}, "{2}{R}", "Stomp", "{1}{R}");
this.subtype.add(SubType.GIANT);
this.power = new MageInt(4);
this.toughness = new MageInt(3);
// Whenever Bonecrusher Giant becomes the target of a spell, Bonecrusher Giant deals 2 damage to that spell's controller.
this.addAbility(new BecomesTargetTriggeredAbility(new DamageTargetEffect(
2, true, "that's spell's controller", "{this}"
), StaticFilters.FILTER_SPELL_A, SetTargetPointer.PLAYER));
// Stomp
// Damage cant be prevented this turn. Stomp deals 2 damage to any target.
this.getAdventureSpellAbility().addEffect(new StompEffect());
this.getAdventureSpellAbility().addEffect(new DamageTargetEffect(2));
this.getAdventureSpellAbility().addTarget(new TargetAnyTarget());
}
private BonecrusherGiant(final BonecrusherGiant card) {
super(card);
}
@Override
public BonecrusherGiant copy() {
return new BonecrusherGiant(this);
}
}
class StompEffect extends ReplacementEffectImpl {
StompEffect() {
super(Duration.EndOfTurn, Outcome.Benefit);
staticText = "Damage can't be prevented this turn.";
}
private StompEffect(final StompEffect effect) {
super(effect);
}
@Override
public StompEffect copy() {
return new StompEffect(this);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.PREVENT_DAMAGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return true;
}
}

View file

@ -2,6 +2,7 @@ package mage.cards.b;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
@ -10,8 +11,10 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.target.Target;
import mage.util.CardUtil;
import java.util.Collection;
import java.util.UUID;
/**
@ -72,15 +75,11 @@ class BorealElementalCostIncreaseEffect extends CostModificationEffectImpl {
.getSelectedModes()
.stream()
.map(uuid -> abilityToModify.getModes().get(uuid))
.anyMatch(mode -> mode
.getTargets()
.stream()
.anyMatch(target -> target
.getTargets()
.stream()
.anyMatch(uuid -> uuid.equals(source.getSourceId()))
)
);
.map(Mode::getTargets)
.flatMap(Collection::stream)
.map(Target::getTargets)
.flatMap(Collection::stream)
.anyMatch(uuid -> uuid.equals(source.getSourceId()));
}
@Override

View file

@ -37,7 +37,7 @@ public final class BorosFuryShield extends CardImpl {
// If {R} was spent to cast Boros Fury-Shield, it deals damage to that creature's controller equal to the creature's power.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new BorosFuryShieldDamageEffect(),
new ManaWasSpentCondition(ColoredManaSymbol.R), "If {R} was spent to cast {this}, it deals damage to that creature's controller equal to the creature's power"));
new ManaWasSpentCondition(ColoredManaSymbol.R), "If {R} was spent to cast this spell, it deals damage to that creature's controller equal to the creature's power"));
}
public BorosFuryShield(final BorosFuryShield card) {

View file

@ -1,7 +1,5 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
@ -20,8 +18,9 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class BragoKingEternal extends CardImpl {
@ -29,7 +28,7 @@ public final class BragoKingEternal extends CardImpl {
public BragoKingEternal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.SPIRIT);
this.subtype.add(SubType.SPIRIT, SubType.NOBLE);
this.power = new MageInt(2);
this.toughness = new MageInt(4);

View file

@ -0,0 +1,47 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPlaneswalkerPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BramblefortFink extends CardImpl {
private static final FilterPermanent filter
= new FilterControlledPlaneswalkerPermanent(SubType.OKO, "you control an Oko planeswalker");
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
public BramblefortFink(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add(SubType.OUPHE);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {8}: Bramblefort Fink has base power and toughness 10/10 until end of turn. Activate this ability only if you control an Oko planeswalker.
this.addAbility(new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new SetPowerToughnessSourceEffect(
10, 10, Duration.EndOfTurn, SubLayer.SetPT_7b
).setText("{this} has base power and toughness 10/10 until end of turn"), new GenericManaCost(8), condition));
}
private BramblefortFink(final BramblefortFink card) {
super(card);
}
@Override
public BramblefortFink copy() {
return new BramblefortFink(this);
}
}

View file

@ -0,0 +1,63 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.common.CanBlockOnlyFlyingAbility;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.AdventureCard;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BrazenBorrower extends AdventureCard {
private static final FilterPermanent filter
= new FilterNonlandPermanent("nonland permanent an opponent controls");
static {
filter.add(new ControllerPredicate(TargetController.OPPONENT));
}
public BrazenBorrower(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, new CardType[]{CardType.INSTANT}, "{1}{U}{U}", "Petty Theft", "{1}{U}");
this.subtype.add(SubType.FAERIE);
this.subtype.add(SubType.ROGUE);
this.power = new MageInt(3);
this.toughness = new MageInt(1);
// Flash
this.addAbility(FlashAbility.getInstance());
// Flying
this.addAbility(FlyingAbility.getInstance());
// Bazen Borrower can block only creatures with flying.
this.addAbility(new CanBlockOnlyFlyingAbility());
// Petty Theft
// Return target nonland permanent an opponent controls to its owner's hand.
this.getAdventureSpellAbility().addEffect(new ReturnToHandTargetEffect());
this.getAdventureSpellAbility().addTarget(new TargetPermanent(filter));
}
private BrazenBorrower(final BrazenBorrower card) {
super(card);
}
@Override
public BrazenBorrower copy() {
return new BrazenBorrower(this);
}
}

View file

@ -0,0 +1,57 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.DamagePlayersEffect;
import mage.abilities.effects.common.UntapSourceEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BrimstoneTrebuchet extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent(SubType.KNIGHT, "a Knight");
public BrimstoneTrebuchet(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{R}");
this.subtype.add(SubType.WALL);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// Defender
this.addAbility(DefenderAbility.getInstance());
// Reach
this.addAbility(ReachAbility.getInstance());
// {T}: Brimstone Trebuchet deals 1 damage to each opponent.
this.addAbility(new SimpleActivatedAbility(
new DamagePlayersEffect(1, TargetController.OPPONENT), new TapSourceCost()
));
// Whenever a Knight enters the battlefield under your control, untap Brimstone Trebuchet.
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new UntapSourceEffect(), filter));
}
private BrimstoneTrebuchet(final BrimstoneTrebuchet card) {
super(card);
}
@Override
public BrimstoneTrebuchet copy() {
return new BrimstoneTrebuchet(this);
}
}

View file

@ -1,20 +1,17 @@
package mage.cards.b;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.condition.common.HellbentCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
import mage.watchers.Watcher;
import mage.watchers.common.MorbidWatcher;
import java.util.UUID;
/**
* @author nantuko
*/
@ -25,8 +22,13 @@ public final class BrimstoneVolley extends CardImpl {
// Brimstone Volley deals 3 damage to any target.
// <i>Morbid</i> &mdash; Brimstone Volley deals 5 damage to that creature or player instead if a creature died this turn.
this.getSpellAbility().addEffect(new BrimstoneVolleyEffect());
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new DamageTargetEffect(3), new DamageTargetEffect(5), HellbentCondition.instance,
"{this} deals 3 damage to any target." +
"<br><i>Morbid</i> &mdash; {this} deals 5 damage instead if a creature died this turn."
));
this.getSpellAbility().addTarget(new TargetAnyTarget());
this.getSpellAbility().addWatcher(new MorbidWatcher());
}
public BrimstoneVolley(final BrimstoneVolley card) {
@ -38,41 +40,3 @@ public final class BrimstoneVolley extends CardImpl {
return new BrimstoneVolley(this);
}
}
class BrimstoneVolleyEffect extends OneShotEffect {
public BrimstoneVolleyEffect() {
super(Outcome.Damage);
staticText = "{this} deals 3 damage to any target.\n <i>Morbid</i> &mdash; {this} deals 5 damage to that permanent or player instead if a creature died this turn";
}
public BrimstoneVolleyEffect(final BrimstoneVolleyEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
int damage = 3;
MorbidWatcher watcher = game.getState().getWatcher(MorbidWatcher.class);
if (watcher != null && watcher.conditionMet()) {
damage = 5;
}
Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
if (permanent != null) {
permanent.damage(damage, source.getSourceId(), game, false, true);
return true;
}
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null) {
player.damage(damage, source.getSourceId(), game, false, true);
return true;
}
return false;
}
@Override
public BrimstoneVolleyEffect copy() {
return new BrimstoneVolleyEffect(this);
}
}

Some files were not shown because too many files have changed in this diff Show more