forked from External/mage
Merge branch 'magefree:master' into case-of-the-pilfered-proof
This commit is contained in:
commit
9cf6119c7e
797 changed files with 36049 additions and 3584 deletions
|
|
@ -151,13 +151,6 @@
|
|||
<version>1.17</version>
|
||||
</dependency>
|
||||
<!-- svg support END -->
|
||||
|
||||
<dependency>
|
||||
<!-- time lib for GUI time info -->
|
||||
<groupId>org.ocpsoft.prettytime</groupId>
|
||||
<artifactId>prettytime</artifactId>
|
||||
<version>4.0.6.Final</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<!-- to get the reference to local repository with com\googlecode\jspf\jspf-core\0.9.1\ -->
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import mage.client.util.GUISizeHelper;
|
|||
import mage.client.util.MageTableRowSorter;
|
||||
import mage.client.util.gui.TableUtil;
|
||||
import mage.client.util.gui.countryBox.CountryCellRenderer;
|
||||
import mage.components.table.MageTable;
|
||||
import mage.components.table.TableInfo;
|
||||
import mage.remote.MageRemoteException;
|
||||
import mage.view.RoomUsersView;
|
||||
import mage.view.UsersView;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ import mage.client.util.MageTableRowSorter;
|
|||
import mage.client.util.URLHandler;
|
||||
import mage.client.util.gui.GuiDisplayUtil;
|
||||
import mage.client.util.gui.TableUtil;
|
||||
import mage.components.table.MageTable;
|
||||
import mage.components.table.TableInfo;
|
||||
import mage.components.table.TimeAgoTableCellRenderer;
|
||||
import mage.constants.*;
|
||||
import mage.game.match.MatchOptions;
|
||||
import mage.players.PlayerType;
|
||||
|
|
@ -155,19 +158,8 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
|
||||
final JToggleButton[] filterButtons;
|
||||
|
||||
// time formater
|
||||
private final PrettyTime timeFormater = new PrettyTime(Locale.ENGLISH);
|
||||
|
||||
// time ago renderer
|
||||
TableCellRenderer timeAgoCellRenderer = new DefaultTableCellRenderer() {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
Date d = (Date) value;
|
||||
label.setText(timeFormater.format(d));
|
||||
return label;
|
||||
}
|
||||
};
|
||||
// time formatter
|
||||
private final PrettyTime timeFormatter = new PrettyTime(Locale.ENGLISH);
|
||||
|
||||
// duration renderer
|
||||
TableCellRenderer durationCellRenderer = new DefaultTableCellRenderer() {
|
||||
|
|
@ -177,8 +169,8 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
Long ms = (Long) value;
|
||||
|
||||
if (ms != 0) {
|
||||
Duration dur = timeFormater.approximateDuration(new Date(ms));
|
||||
label.setText((timeFormater.formatDuration(dur)));
|
||||
Duration dur = timeFormatter.approximateDuration(new Date(ms));
|
||||
label.setText((timeFormatter.formatDuration(dur)));
|
||||
} else {
|
||||
label.setText("");
|
||||
}
|
||||
|
|
@ -298,13 +290,8 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
initComponents();
|
||||
// tableModel.setSession(session);
|
||||
|
||||
// formater
|
||||
// change default just now from 60 to 30 secs
|
||||
// see workaround for 4.0 versions: https://github.com/ocpsoft/prettytime/issues/152
|
||||
TimeFormat timeFormat = timeFormater.removeUnit(JustNow.class);
|
||||
JustNow newJustNow = new JustNow();
|
||||
newJustNow.setMaxQuantity(1000L * 30L); // 30 seconds gap (show "just now" from 0 to 30 secs)
|
||||
timeFormater.registerUnit(newJustNow, timeFormat);
|
||||
// formatter
|
||||
MageTable.fixTimeFormatter(this.timeFormatter);
|
||||
|
||||
// 1. TABLE CURRENT
|
||||
tableTables.createDefaultColumnsFromModel();
|
||||
|
|
@ -334,7 +321,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
tableTables.setRowSorter(activeTablesSorter);
|
||||
|
||||
// time ago
|
||||
tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_CREATED).setCellRenderer(timeAgoCellRenderer);
|
||||
tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_CREATED).setCellRenderer(TimeAgoTableCellRenderer.getInstance());
|
||||
// skill level
|
||||
tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_SKILL).setCellRenderer(skillCellRenderer);
|
||||
// seats
|
||||
|
|
@ -545,7 +532,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
int modelRow = TablesUtil.getSelectedModelRow(table);
|
||||
int modelRow = MageTable.getSelectedModelRow(table);
|
||||
if (modelRow != -1) {
|
||||
// needs only selected
|
||||
String rowId = TablesUtil.getSearchIdFromTable(table, modelRow);
|
||||
|
|
@ -563,7 +550,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
public void run() {
|
||||
String lastRowID = tablesLastSelection.get(table);
|
||||
int needModelRow = TablesUtil.findTableRowFromSearchId(table.getModel(), lastRowID);
|
||||
int needViewRow = TablesUtil.getViewRowFromModel(table, needModelRow);
|
||||
int needViewRow = MageTable.getViewRowFromModel(table, needModelRow);
|
||||
if (needViewRow != -1) {
|
||||
table.clearSelection();
|
||||
table.addRowSelectionInterval(needViewRow, needViewRow);
|
||||
|
|
@ -581,7 +568,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
if (!SwingUtilities.isLeftMouseButton(e)) {
|
||||
return;
|
||||
}
|
||||
int modelRow = TablesUtil.getSelectedModelRow(table);
|
||||
int modelRow = MageTable.getSelectedModelRow(table);
|
||||
if (e.getClickCount() == 2 && modelRow != -1) {
|
||||
action.actionPerformed(new ActionEvent(table, ActionEvent.ACTION_PERFORMED, TablesUtil.getSearchIdFromTable(table, modelRow)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package mage.client.table;
|
||||
|
||||
import mage.client.SessionHandler;
|
||||
import mage.components.table.TableModelWithTooltip;
|
||||
import mage.constants.SkillLevel;
|
||||
import mage.remote.MageRemoteException;
|
||||
import mage.view.TableView;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import org.apache.log4j.Logger;
|
|||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* GUI related
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class TablesUtil {
|
||||
|
|
@ -42,22 +44,4 @@ public class TablesUtil {
|
|||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
public static int getSelectedModelRow(JTable table) {
|
||||
return getModelRowFromView(table, table.getSelectedRow());
|
||||
}
|
||||
|
||||
public static int getModelRowFromView(JTable table, int viewRow) {
|
||||
if (viewRow != -1 && viewRow < table.getModel().getRowCount()) {
|
||||
return table.convertRowIndexToModel(viewRow);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int getViewRowFromModel(JTable table, int modelRow) {
|
||||
if (modelRow != -1 && modelRow < table.getModel().getRowCount()) {
|
||||
return table.convertRowIndexToView(modelRow);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,13 +186,6 @@ public final class GUISizeHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static String textToHtmlWithSize(String text, Font font) {
|
||||
if (text != null && !text.toLowerCase(Locale.ENGLISH).startsWith("<html>")) {
|
||||
return "<html><p style=\"font-size: " + font.getSize() + ";\">" + text + "</p>";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return scrollbar settings, so user can scroll it more faster for bigger cards
|
||||
*
|
||||
|
|
|
|||
|
|
@ -97,13 +97,14 @@ public class GathererSets implements Iterable<DownloadJob> {
|
|||
"GNT", "UMA", "GRN",
|
||||
"RNA", "WAR", "MH1",
|
||||
"M20",
|
||||
"C19","ELD","MB1","GN2","J20","THB","UND","C20","IKO","M21",
|
||||
"JMP","2XM","ZNR","KLR","CMR","KHC","KHM","TSR","STX","STA",
|
||||
"C21","MH2","AFR","AFC","J21","MID","MIC","VOW","VOC","YMID",
|
||||
"NEC","NEO","SNC","NCC","CLB","2X2","DMU","DMC","40K","GN3",
|
||||
"UNF","BRO","BRC","BOT","30A","J22","SCD","DMR","ONE","ONC",
|
||||
"MOM","MOC","MUL","MAT","LTR","CMM","WOE","WHO","RVR","WOT",
|
||||
"WOC","SPG","LCI","LCC","REX"
|
||||
"C19", "ELD", "MB1", "GN2", "J20", "THB", "UND", "C20", "IKO", "M21",
|
||||
"JMP", "2XM", "ZNR", "KLR", "CMR", "KHC", "KHM", "TSR", "STX", "STA",
|
||||
"C21", "MH2", "AFR", "AFC", "J21", "MID", "MIC", "VOW", "VOC", "YMID",
|
||||
"NEC", "NEO", "SNC", "NCC", "CLB", "2X2", "DMU", "DMC", "40K", "GN3",
|
||||
"UNF", "BRO", "BRC", "BOT", "30A", "J22", "SCD", "DMR", "ONE", "ONC",
|
||||
"MOM", "MOC", "MUL", "MAT", "LTR", "CMM", "WOE", "WHO", "RVR", "WOT",
|
||||
"WOC", "SPG", "LCI", "LCC", "REX", "PIP", "MKM", "MKC", "CLU", "OTJ",
|
||||
"OTC", "OTP", "BIG", "MH3", "ACR", "BLB"
|
||||
// "HHO", "ANA" -- do not exist on gatherer
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -547,6 +547,8 @@ public class ScryfallImageSupportCards {
|
|||
add("MKC"); // Murders at Karlov Manor Commander
|
||||
add("CLU"); // Ravnica: Clue Edition
|
||||
add("OTJ"); // Outlaws of Thunder Junction
|
||||
add("OTC"); // Outlaws of Thunder Junction Commander
|
||||
add("OTP"); // Breaking News
|
||||
add("BIG"); // The Big Score
|
||||
add("MH3"); // Modern Horizons 3
|
||||
add("ACR"); // Assassin's Creed
|
||||
|
|
|
|||
|
|
@ -43,6 +43,13 @@
|
|||
<version>4.2.2.GA</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<!-- time lib for GUI time info -->
|
||||
<groupId>org.ocpsoft.prettytime</groupId>
|
||||
<artifactId>prettytime</artifactId>
|
||||
<version>4.0.6.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<!-- A dependency of jboss.remoting -->
|
||||
<groupId>concurrent</groupId>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package mage.client.table;
|
||||
package mage.components.table;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
|
|
@ -1,13 +1,17 @@
|
|||
package mage.client.table;
|
||||
package mage.components.table;
|
||||
|
||||
import mage.client.util.GUISizeHelper;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.ocpsoft.prettytime.PrettyTime;
|
||||
import org.ocpsoft.prettytime.TimeFormat;
|
||||
import org.ocpsoft.prettytime.units.JustNow;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.JTableHeader;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* GUI: basic mage table for any data like game tables list, players list, etc
|
||||
|
|
@ -26,7 +30,7 @@ public class MageTable extends JTable {
|
|||
public MageTable(TableInfo tableInfo) {
|
||||
this.tableInfo = tableInfo;
|
||||
}
|
||||
|
||||
|
||||
public void setTableInfo(TableInfo tableInfo) {
|
||||
this.tableInfo = tableInfo;
|
||||
}
|
||||
|
|
@ -37,7 +41,7 @@ public class MageTable extends JTable {
|
|||
java.awt.Point p = e.getPoint();
|
||||
int viewRow = rowAtPoint(p);
|
||||
int viewCol = columnAtPoint(p);
|
||||
int modelRow = TablesUtil.getModelRowFromView(this, viewRow);
|
||||
int modelRow = getModelRowFromView(this, viewRow);
|
||||
int modelCol = this.convertColumnIndexToModel(viewCol);
|
||||
String tip = null;
|
||||
if (modelRow != -1 && modelCol != -1) {
|
||||
|
|
@ -48,7 +52,7 @@ public class MageTable extends JTable {
|
|||
tip = model.getValueAt(modelRow, modelCol).toString();
|
||||
}
|
||||
}
|
||||
return GUISizeHelper.textToHtmlWithSize(tip, GUISizeHelper.tableFont);
|
||||
return textToHtmlWithSize(tip, this.getFont());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -78,8 +82,43 @@ public class MageTable extends JTable {
|
|||
tip = col.getHeaderValue().toString();
|
||||
}
|
||||
|
||||
return GUISizeHelper.textToHtmlWithSize(tip, GUISizeHelper.tableFont);
|
||||
return textToHtmlWithSize(tip, MageTable.this.getFont());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static int getSelectedModelRow(JTable table) {
|
||||
return getModelRowFromView(table, table.getSelectedRow());
|
||||
}
|
||||
|
||||
public static int getModelRowFromView(JTable table, int viewRow) {
|
||||
if (viewRow != -1 && viewRow < table.getModel().getRowCount()) {
|
||||
return table.convertRowIndexToModel(viewRow);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int getViewRowFromModel(JTable table, int modelRow) {
|
||||
if (modelRow != -1 && modelRow < table.getModel().getRowCount()) {
|
||||
return table.convertRowIndexToView(modelRow);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static String textToHtmlWithSize(String text, Font font) {
|
||||
if (text != null && !text.toLowerCase(Locale.ENGLISH).startsWith("<html>")) {
|
||||
return "<html><p style=\"font-size: " + font.getSize() + ";\">" + text + "</p>";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public static void fixTimeFormatter(PrettyTime timeFormatter) {
|
||||
// TODO: remove after PrettyTime lib upgrade to v5
|
||||
// change default just now from 60 to 30 secs
|
||||
// see workaround for 4.0 versions: https://github.com/ocpsoft/prettytime/issues/152
|
||||
TimeFormat timeFormat = timeFormatter.removeUnit(JustNow.class);
|
||||
JustNow newJustNow = new JustNow();
|
||||
newJustNow.setMaxQuantity(1000L * 30L); // 30 seconds gap (show "just now" from 0 to 30 secs)
|
||||
timeFormatter.registerUnit(newJustNow, timeFormat);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package mage.client.table;
|
||||
package mage.components.table;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package mage.client.table;
|
||||
package mage.components.table;
|
||||
|
||||
/**
|
||||
* GUI: add support of tooltip/hint for table's cells on mouse move (used by MageTable)
|
||||
* <p>
|
||||
* Make sure form and java files uses new MageTable(), not new JTable() code
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package mage.components.table;
|
||||
|
||||
import org.ocpsoft.prettytime.PrettyTime;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* GUI: create time ago cell renderer for date values in the table's cell
|
||||
* <p>
|
||||
* Usage example:
|
||||
* tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_CREATED).setCellRenderer(TimeAgoTableCellRenderer.getInstance());
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class TimeAgoTableCellRenderer extends DefaultTableCellRenderer {
|
||||
|
||||
static final PrettyTime timeFormatter;
|
||||
|
||||
static {
|
||||
timeFormatter = new PrettyTime(Locale.ENGLISH);
|
||||
MageTable.fixTimeFormatter(timeFormatter);
|
||||
}
|
||||
|
||||
private static final TimeAgoTableCellRenderer instance = new TimeAgoTableCellRenderer();
|
||||
|
||||
public static TimeAgoTableCellRenderer getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
Date d = (Date) value;
|
||||
label.setText(timeFormatter.format(d));
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ public class ConnectDialog extends JDialog {
|
|||
public ConnectDialog() {
|
||||
initComponents();
|
||||
cbProxyType.setModel(new DefaultComboBoxModel(Connection.ProxyType.values()));
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
public void showDialog(ConsoleFrame console) {
|
||||
|
|
@ -39,8 +40,8 @@ public class ConnectDialog extends JDialog {
|
|||
this.txtServer.setText(ConsoleFrame.getPreferences().get("serverAddress", "localhost"));
|
||||
this.txtPort.setText(ConsoleFrame.getPreferences().get("serverPort", Integer.toString(17171)));
|
||||
this.chkAutoConnect.setSelected(Boolean.parseBoolean(ConsoleFrame.getPreferences().get("autoConnect", "false")));
|
||||
this.txtProxyServer.setText(ConsoleFrame.getPreferences().get("proxyAddress", "localhost"));
|
||||
this.txtProxyPort.setText(ConsoleFrame.getPreferences().get("proxyPort", Integer.toString(17171)));
|
||||
this.txtProxyServer.setText(ConsoleFrame.getPreferences().get("proxyAddress", ""));
|
||||
this.txtProxyPort.setText(ConsoleFrame.getPreferences().get("proxyPort", Integer.toString(0)));
|
||||
this.cbProxyType.setSelectedItem(Connection.ProxyType.valueOf(ConsoleFrame.getPreferences().get("proxyType", "NONE").toUpperCase(Locale.ENGLISH)));
|
||||
this.txtProxyUserName.setText(ConsoleFrame.getPreferences().get("proxyUsername", ""));
|
||||
this.txtPasswordField.setText(ConsoleFrame.getPreferences().get("proxyPassword", ""));
|
||||
|
|
@ -71,7 +72,16 @@ public class ConnectDialog extends JDialog {
|
|||
private void saveSettings() {
|
||||
ConsoleFrame.getPreferences().put("serverAddress", txtServer.getText());
|
||||
ConsoleFrame.getPreferences().put("serverPort", txtPort.getText());
|
||||
ConsoleFrame.getPreferences().put("autoConnect", Boolean.toString(chkAutoConnect.isSelected()));
|
||||
if (chkAutoConnect.isSelected()) {
|
||||
ConsoleFrame.getPreferences().putBoolean("autoConnect", true);
|
||||
char[] input = txtPassword.getPassword();
|
||||
ConsoleFrame.getPreferences().put("password", new String(input));
|
||||
Arrays.fill(input, '0');
|
||||
} else {
|
||||
ConsoleFrame.getPreferences().putBoolean("autoConnect", false);
|
||||
ConsoleFrame.getPreferences().put("password", "");
|
||||
}
|
||||
|
||||
ConsoleFrame.getPreferences().put("proxyAddress", txtProxyServer.getText());
|
||||
ConsoleFrame.getPreferences().put("proxyPort", txtProxyPort.getText());
|
||||
ConsoleFrame.getPreferences().put("proxyType", cbProxyType.getSelectedItem().toString());
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import org.apache.log4j.Logger;
|
|||
import javax.swing.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
|
@ -63,6 +64,13 @@ public class ConsoleFrame extends javax.swing.JFrame implements MageClient {
|
|||
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
|
||||
session = new SessionImpl(this);
|
||||
connectDialog = new ConnectDialog();
|
||||
|
||||
// try auto connect
|
||||
if (!autoConnect()) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
connectDialog.showDialog(this);
|
||||
});
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.fatal("", ex);
|
||||
}
|
||||
|
|
@ -78,6 +86,29 @@ public class ConsoleFrame extends javax.swing.JFrame implements MageClient {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean autoConnect() {
|
||||
boolean needAutoConnect = Boolean.parseBoolean(ConsoleFrame.getPreferences().get("autoConnect", "false"));
|
||||
boolean status = false;
|
||||
if (needAutoConnect) {
|
||||
String server = ConsoleFrame.getPreferences().get("serverAddress", "localhost");
|
||||
logger.info("Auto-connecting to " + server);
|
||||
Connection newConnection = new Connection();
|
||||
newConnection.setHost(server);
|
||||
newConnection.setPort(ConsoleFrame.getPreferences().getInt("serverPort", 17171));
|
||||
newConnection.setUsername(SessionImpl.ADMIN_NAME);
|
||||
newConnection.setAdminPassword(ConsoleFrame.getPreferences().get("password", ""));
|
||||
newConnection.setProxyType(Connection.ProxyType.valueOf(ConsoleFrame.getPreferences().get("proxyType", "NONE").toUpperCase(Locale.ENGLISH)));
|
||||
if (!newConnection.getProxyType().equals(Connection.ProxyType.NONE)) {
|
||||
newConnection.setProxyHost(ConsoleFrame.getPreferences().get("proxyAddress", ""));
|
||||
newConnection.setProxyPort(ConsoleFrame.getPreferences().getInt("proxyPort", 0));
|
||||
newConnection.setProxyUsername(ConsoleFrame.getPreferences().get("proxyUsername", ""));
|
||||
newConnection.setProxyPassword(ConsoleFrame.getPreferences().get("proxyPassword", ""));
|
||||
}
|
||||
status = connect(newConnection);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatusText(String status) {
|
||||
this.lblStatus.setText(status);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,9 @@
|
|||
<Connection code="tableUserModel" type="code"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MageTable()"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
|
|
@ -262,6 +265,9 @@
|
|||
<Connection code="tableTableModel" type="code"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MageTable()"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package mage.server.console;
|
||||
|
||||
import mage.components.table.MageTable;
|
||||
import mage.components.table.TableModelWithTooltip;
|
||||
import mage.components.table.TimeAgoTableCellRenderer;
|
||||
import mage.remote.Session;
|
||||
import mage.view.TableView;
|
||||
import mage.view.UserView;
|
||||
|
|
@ -13,6 +16,7 @@
|
|||
import java.util.*;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN;
|
||||
import static javax.swing.JTable.AUTO_RESIZE_OFF;
|
||||
|
|
@ -36,6 +40,7 @@
|
|||
this.tableUserModel = new TableUserModel();
|
||||
this.tableTableModel = new TableTableModel();
|
||||
initComponents();
|
||||
|
||||
spinnerMuteDurationMinutes.setValue(60);
|
||||
this.tblUsers.createDefaultColumnsFromModel();
|
||||
this.tblUsers.setRowSorter(new TableRowSorter(tableUserModel));
|
||||
|
|
@ -43,7 +48,8 @@
|
|||
|
||||
this.tblTables.createDefaultColumnsFromModel();
|
||||
this.tblTables.setRowSorter(new TableRowSorter(tableTableModel));
|
||||
this.tblUsers.setAutoResizeMode(AUTO_RESIZE_NEXT_COLUMN);
|
||||
this.tblTables.setAutoResizeMode(AUTO_RESIZE_NEXT_COLUMN);
|
||||
this.tblTables.getColumnModel().getColumn(TableTableModel.COLUMN_CREATED).setCellRenderer(TimeAgoTableCellRenderer.getInstance());
|
||||
}
|
||||
|
||||
public void update(List<UserView> users) {
|
||||
|
|
@ -93,7 +99,7 @@
|
|||
jPanel1 = new javax.swing.JPanel();
|
||||
jPanel3 = new javax.swing.JPanel();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
tblUsers = new javax.swing.JTable();
|
||||
tblUsers = new MageTable();
|
||||
jPanel4 = new javax.swing.JPanel();
|
||||
btnDisconnect = new javax.swing.JButton();
|
||||
btnEndSession = new javax.swing.JButton();
|
||||
|
|
@ -105,7 +111,7 @@
|
|||
jPanel2 = new javax.swing.JPanel();
|
||||
jPanel5 = new javax.swing.JPanel();
|
||||
jScrollPane2 = new javax.swing.JScrollPane();
|
||||
tblTables = new javax.swing.JTable();
|
||||
tblTables = new MageTable();
|
||||
jPanel6 = new javax.swing.JPanel();
|
||||
btnRemoveTable = new javax.swing.JButton();
|
||||
jUserName = new javax.swing.JTextField();
|
||||
|
|
@ -373,7 +379,10 @@
|
|||
|
||||
private void btnRemoveTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveTableActionPerformed
|
||||
int row = this.tblTables.convertRowIndexToModel(tblTables.getSelectedRow());
|
||||
ConsoleFrame.getSession().removeTable((UUID) tableTableModel.getValueAt(row, 7));
|
||||
if (row >= 0) {
|
||||
TableView tableView = this.tableTableModel.getTableView(row);
|
||||
ConsoleFrame.getSession().removeTable(tableView.getTableId());
|
||||
}
|
||||
}//GEN-LAST:event_btnRemoveTableActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
|
|
@ -484,9 +493,11 @@
|
|||
|
||||
}
|
||||
|
||||
class TableTableModel extends AbstractTableModel {
|
||||
class TableTableModel extends AbstractTableModel implements TableModelWithTooltip {
|
||||
|
||||
private final String[] columnNames = new String[]{"Table Name", "Owner", "Game Type", "Deck Type", "Status"};
|
||||
protected static final int COLUMN_CREATED = 4;
|
||||
|
||||
private final String[] columnNames = new String[]{"Table name", "Players", "Game type", "Deck type", "Created", "Status", "Games"};
|
||||
private TableView[] tables = new TableView[0];
|
||||
|
||||
public void loadData(Collection<TableView> tables) {
|
||||
|
|
@ -515,17 +526,20 @@
|
|||
return tables[arg0].getGameType();
|
||||
case 3:
|
||||
return tables[arg0].getDeckType();
|
||||
case 4:
|
||||
return tables[arg0].getTableState().toString();
|
||||
case COLUMN_CREATED:
|
||||
return tables[arg0].getCreateTime();
|
||||
case 5:
|
||||
return tables[arg0].isTournament();
|
||||
case 6:
|
||||
if (!tables[arg0].getGames().isEmpty()) {
|
||||
return tables[arg0].getGames().get(0);
|
||||
return tables[arg0].getTableStateText();
|
||||
case 6:{
|
||||
if (tables[arg0].getGames().isEmpty()) {
|
||||
return "NO GAMES";
|
||||
} else if (tables[arg0].getGames().size() == 1) {
|
||||
return tables[arg0].getGames().get(0).toString();
|
||||
} else {
|
||||
return String.format("%d games:", tables[arg0].getGames().size())
|
||||
+ "<br>" + tables[arg0].getGames().stream().map(UUID::toString).collect(Collectors.joining("<br>"));
|
||||
}
|
||||
return null;
|
||||
case 7:
|
||||
return tables[arg0].getTableId();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
@ -543,14 +557,31 @@
|
|||
|
||||
@Override
|
||||
public Class getColumnClass(int columnIndex) {
|
||||
return String.class;
|
||||
if (columnIndex == COLUMN_CREATED) {
|
||||
return Date.class;
|
||||
} else {
|
||||
return String.class;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
return columnIndex == 5;
|
||||
return false;
|
||||
}
|
||||
|
||||
public TableView getTableView(int row) {
|
||||
if (row >= 0 && row <= this.tables.length - 1) {
|
||||
return this.tables[row];
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown table row: " + row);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltipAt(int rowIndex, int columnIndex) {
|
||||
Object res = this.getValueAt(rowIndex, columnIndex);
|
||||
return res == null ? null : res.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateUsersTask extends SwingWorker<Void, List<UserView>> {
|
||||
|
|
|
|||
|
|
@ -449,8 +449,10 @@ public class Session {
|
|||
logger.warn("SESSION LOCK, possible connection problem - fireCallback - userId: " + userId + " messageId: " + call.getMessageId(), ex);
|
||||
}
|
||||
} catch (HandleCallbackException ex) {
|
||||
// something wrong, maybe connection problem
|
||||
logger.warn("SESSION CALLBACK EXCEPTION - " + ThreadUtils.findRootException(ex) + ", userId " + userId + ", messageId: " + call.getMessageId(), ex);
|
||||
// general error
|
||||
// can raise on server freeze or normal connection problem from a client side
|
||||
// no need to print a full stack log here
|
||||
logger.warn("SESSION CALLBACK EXCEPTION - " + ThreadUtils.findRootException(ex) + ", userId " + userId + ", messageId: " + call.getMessageId());
|
||||
|
||||
// do not send data anymore (user must reconnect)
|
||||
this.valid = false;
|
||||
|
|
|
|||
48
Mage.Sets/src/mage/cards/a/AbradedBluffs.java
Normal file
48
Mage.Sets/src/mage/cards/a/AbradedBluffs.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTappedAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.mana.RedManaAbility;
|
||||
import mage.abilities.mana.WhiteManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.target.common.TargetOpponent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AbradedBluffs extends CardImpl {
|
||||
|
||||
public AbradedBluffs(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||
|
||||
this.subtype.add(SubType.DESERT);
|
||||
|
||||
// Abraded Bluffs enters the battlefield tapped.
|
||||
this.addAbility(new EntersBattlefieldTappedAbility());
|
||||
|
||||
// When Abraded Bluffs enters the battlefield, it deals 1 damage to target opponent.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(1, "it"));
|
||||
ability.addTarget(new TargetOpponent());
|
||||
this.addAbility(ability);
|
||||
|
||||
// {T}: Add {R} or {W}.
|
||||
this.addAbility(new RedManaAbility());
|
||||
this.addAbility(new WhiteManaAbility());
|
||||
}
|
||||
|
||||
private AbradedBluffs(final AbradedBluffs card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbradedBluffs copy() {
|
||||
return new AbradedBluffs(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedBatchForOnePermanentEvent;
|
||||
import mage.game.events.DamagedEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.watchers.Watcher;
|
||||
|
|
@ -56,14 +57,22 @@ class AegarTheFreezingFlameTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT;
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PERMANENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
DamagedEvent dEvent = (DamagedEvent) event;
|
||||
if (dEvent.getExcess() < 1
|
||||
|| !game.getOpponents(getControllerId()).contains(game.getControllerId(event.getTargetId()))) {
|
||||
DamagedBatchForOnePermanentEvent dEvent = (DamagedBatchForOnePermanentEvent) event;
|
||||
|
||||
int excess = dEvent.getEvents()
|
||||
.stream()
|
||||
.mapToInt(DamagedEvent::getExcess)
|
||||
.sum();
|
||||
|
||||
boolean controlledByOpponent =
|
||||
game.getOpponents(getControllerId()).contains(game.getControllerId(event.getTargetId()));
|
||||
|
||||
if (excess < 1 || !controlledByOpponent) {
|
||||
return false;
|
||||
}
|
||||
AegarTheFreezingFlameWatcher watcher = game.getState().getWatcher(AegarTheFreezingFlameWatcher.class);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class AetherSnapEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
Cards tokens = new CardsImpl();
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getSourceId(), game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
|
||||
if (permanent instanceof PermanentToken) {
|
||||
tokens.add(permanent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class AetherworksMarvelEffect extends OneShotEffect {
|
|||
AetherworksMarvelEffect() {
|
||||
super(Outcome.PlayForFree);
|
||||
this.staticText = "Look at the top six cards of your library. "
|
||||
+ "You may cast a card from among them without paying "
|
||||
+ "You may cast a spell from among them without paying "
|
||||
+ "its mana cost. Put the rest on the bottom of your "
|
||||
+ "library in a random order";
|
||||
}
|
||||
|
|
|
|||
135
Mage.Sets/src/mage/cards/a/AgencyOutfitter.java
Normal file
135
Mage.Sets/src/mage/cards/a/AgencyOutfitter.java
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardAndOrCard;
|
||||
import mage.target.common.TargetCardAndOrCardInLibrary;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author notgreat
|
||||
*/
|
||||
public final class AgencyOutfitter extends CardImpl {
|
||||
|
||||
public AgencyOutfitter(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
|
||||
this.subtype.add(SubType.SPHINX);
|
||||
this.subtype.add(SubType.DETECTIVE);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// When Agency Outfitter enters the battlefield, you may search your graveyard, hand, and/or library for a card named Magnifying Glass and/or a card named Thinking Cap and put them onto the battlefield. If you search your library this way, shuffle.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new AgencyOutfitterEffect(), true));
|
||||
}
|
||||
|
||||
private AgencyOutfitter(final AgencyOutfitter card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgencyOutfitter copy() {
|
||||
return new AgencyOutfitter(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AgencyOutfitterEffect extends OneShotEffect {
|
||||
private static final String glassName = "Magnifying Glass";
|
||||
private static final String capName = "Thinking Cap";
|
||||
|
||||
AgencyOutfitterEffect() {
|
||||
super(Outcome.UnboostCreature);
|
||||
this.staticText = "you may search your graveyard, hand, and/or library for a card named Magnifying Glass and/or a card named Thinking Cap and put them onto the battlefield. If you search your library this way, shuffle.";
|
||||
}
|
||||
|
||||
private AgencyOutfitterEffect(final AgencyOutfitterEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgencyOutfitterEffect copy() {
|
||||
return new AgencyOutfitterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Card glassCard = null;
|
||||
Card capCard = null;
|
||||
if (controller.chooseUse(Outcome.Neutral, "Search your library?", source, game)) {
|
||||
TargetCardAndOrCardInLibrary libraryTarget = new TargetCardAndOrCardInLibrary(glassName, capName);
|
||||
if (controller.searchLibrary(libraryTarget, source, game)) {
|
||||
for (UUID id : libraryTarget.getTargets()) {
|
||||
Card card = game.getCard(id);
|
||||
if (card != null) {
|
||||
if (CardUtil.haveSameNames(card, glassName, game)) {
|
||||
glassCard = card;
|
||||
} else if (CardUtil.haveSameNames(card, capName, game)) {
|
||||
capCard = card;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
controller.shuffleLibrary(source, game);
|
||||
}
|
||||
|
||||
if (glassCard == null || capCard == null) {
|
||||
FilterCard filter;
|
||||
TargetCard target;
|
||||
if (glassCard == null && capCard == null) {
|
||||
target = new TargetCardAndOrCard(glassName, capName);
|
||||
filter = target.getFilter();
|
||||
} else {
|
||||
String name = (glassCard == null ? glassName : capName);
|
||||
filter = new FilterCard();
|
||||
filter.add(new NamePredicate(name));
|
||||
target = new TargetCard(0, 1, Zone.ALL, filter);
|
||||
}
|
||||
target.withNotTarget(true);
|
||||
Cards cards = new CardsImpl();
|
||||
cards.addAllCards(controller.getHand().getCards(filter, source.getControllerId(), source, game));
|
||||
cards.addAllCards(controller.getGraveyard().getCards(filter, source.getControllerId(), source, game));
|
||||
if (!cards.isEmpty()) {
|
||||
controller.choose(outcome, cards, target, source, game);
|
||||
for (UUID id : target.getTargets()) {
|
||||
Card card = game.getCard(id);
|
||||
if (card != null) {
|
||||
if (CardUtil.haveSameNames(card, glassName, game)) {
|
||||
glassCard = card;
|
||||
} else if (CardUtil.haveSameNames(card, capName, game)) {
|
||||
capCard = card;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cards foundCards = new CardsImpl();
|
||||
foundCards.add(glassCard);
|
||||
foundCards.add(capCard);
|
||||
if (!foundCards.isEmpty()) {
|
||||
controller.moveCards(foundCards, Zone.BATTLEFIELD, source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -94,7 +94,7 @@ class AgrusKosEternalSoldierTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (targetingObject == null || targetingObject instanceof Spell) {
|
||||
return false;
|
||||
}
|
||||
if (CardUtil.checkTargetedEventAlreadyUsed(this.id.toString(), targetingObject, event, game)) {
|
||||
if (CardUtil.checkTargetedEventAlreadyUsed(this.getId().toString(), targetingObject, event, game)) {
|
||||
return false;
|
||||
}
|
||||
Set<UUID> targets = targetingObject
|
||||
|
|
|
|||
192
Mage.Sets/src/mage/cards/a/AjaniNacatlAvenger.java
Normal file
192
Mage.Sets/src/mage/cards/a/AjaniNacatlAvenger.java
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.LoyaltyAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
|
||||
import mage.abilities.dynamicvalue.common.CreaturesYouControlCount;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersAllEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterNonlandPermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.CatWarrior21Token;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class AjaniNacatlAvenger extends CardImpl {
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.CAT, "Cat you control");
|
||||
|
||||
public AjaniNacatlAvenger(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.AJANI);
|
||||
this.setStartingLoyalty(3);
|
||||
|
||||
this.color.setRed(true);
|
||||
this.color.setWhite(true);
|
||||
this.nightCard = true;
|
||||
|
||||
// +2: Put a +1/+1 counter on each Cat you control.
|
||||
this.addAbility(new LoyaltyAbility(
|
||||
new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter), 2
|
||||
));
|
||||
|
||||
// 0: Create a 2/1 white Car Warrior creature token. When you do, if you control a red permanent other than Ajani, Nacatl Avenger, he deals damage equal to the number of creatures you control to any target.
|
||||
this.addAbility(new LoyaltyAbility(new AjaniNacatlAvengerZeroEffect(), 0));
|
||||
|
||||
// -4: Each opponent chooses an artifact, a creature, an enchantment and a planeswalker from among the nonland permanents they control, then sacrifices the rest.
|
||||
this.addAbility(new LoyaltyAbility(new AjaniNacatlAvengerMinusFourEffect(), -4));
|
||||
}
|
||||
|
||||
private AjaniNacatlAvenger(final AjaniNacatlAvenger card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaniNacatlAvenger copy() {
|
||||
return new AjaniNacatlAvenger(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AjaniNacatlAvengerZeroEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("red permanent other than {this}");
|
||||
|
||||
static {
|
||||
filter.add(new ColorPredicate(ObjectColor.RED));
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, true);
|
||||
|
||||
AjaniNacatlAvengerZeroEffect() {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
staticText = "Create a 2/1 white Car Warrior creature token. "
|
||||
+ "When you do, if you control a red permanent other than {this}, "
|
||||
+ "he deals damage equal to the number of creatures you control to any target.";
|
||||
}
|
||||
|
||||
private AjaniNacatlAvengerZeroEffect(final AjaniNacatlAvengerZeroEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaniNacatlAvengerZeroEffect copy() {
|
||||
return new AjaniNacatlAvengerZeroEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (!new CreateTokenEffect(new CatWarrior21Token()).apply(game, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ReflexiveTriggeredAbility reflexive = new ReflexiveTriggeredAbility(
|
||||
new DamageTargetEffect(CreaturesYouControlCount.instance),
|
||||
false,
|
||||
"When you do, if you control a red permanent other than {this}, "
|
||||
+ "he deals damage equal to the number of creatures you control to any target.",
|
||||
condition
|
||||
);
|
||||
reflexive.addTarget(new TargetAnyTarget());
|
||||
game.fireReflexiveTriggeredAbility(reflexive, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Inspired by Mythos of Snapdax
|
||||
class AjaniNacatlAvengerMinusFourEffect extends OneShotEffect {
|
||||
|
||||
private static final List<CardType> cardTypes = Arrays.asList(
|
||||
CardType.ARTIFACT,
|
||||
CardType.CREATURE,
|
||||
CardType.ENCHANTMENT,
|
||||
CardType.PLANESWALKER
|
||||
);
|
||||
|
||||
AjaniNacatlAvengerMinusFourEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Each opponent chooses an artifact, a creature, an enchantment and a planeswalker "
|
||||
+ "from among the nonland permanents they control, then sacrifices the rest.";
|
||||
}
|
||||
|
||||
private AjaniNacatlAvengerMinusFourEffect(final AjaniNacatlAvengerMinusFourEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaniNacatlAvengerMinusFourEffect copy() {
|
||||
return new AjaniNacatlAvengerMinusFourEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Player> playerList = game
|
||||
.getState()
|
||||
.getPlayersInRange(source.getControllerId(), game)
|
||||
.stream()
|
||||
.map(game::getPlayer)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(player -> controller.hasOpponent(player.getId(), game))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Set<UUID> toKeep = new HashSet();
|
||||
for (Player player : playerList) {
|
||||
for (CardType cardType : cardTypes) {
|
||||
String message = cardType.toString().equals("Artifact") ? "an " : "a ";
|
||||
message += cardType.toString().toLowerCase(Locale.ENGLISH);
|
||||
FilterPermanent filter = new FilterNonlandPermanent(message);
|
||||
filter.add(cardType.getPredicate());
|
||||
filter.add(new ControllerIdPredicate(player.getId()));
|
||||
if (game.getBattlefield().count(filter, source.getControllerId(), source, game) == 0) {
|
||||
continue;
|
||||
}
|
||||
TargetPermanent target = new TargetPermanent(filter);
|
||||
target.withNotTarget(true);
|
||||
player.choose(outcome, target, source, game);
|
||||
toKeep.add(target.getFirstTarget());
|
||||
}
|
||||
}
|
||||
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_NON_LAND, source.getControllerId(), game)) {
|
||||
if (permanent == null || toKeep.contains(permanent.getId()) || !controller.hasOpponent(permanent.getControllerId(), game)) {
|
||||
continue;
|
||||
}
|
||||
permanent.sacrifice(source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
61
Mage.Sets/src/mage/cards/a/AjaniNacatlPariah.java
Normal file
61
Mage.Sets/src/mage/cards/a/AjaniNacatlPariah.java
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Pronoun;
|
||||
import mage.abilities.common.DiesOneOrMoreCreatureTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.ExileAndReturnSourceEffect;
|
||||
import mage.abilities.keyword.TransformAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.game.permanent.token.CatWarrior21Token;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class AjaniNacatlPariah extends CardImpl {
|
||||
|
||||
public static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.CAT, "other Cats you control");
|
||||
|
||||
static {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
filter.add(TargetController.YOU.getControllerPredicate());
|
||||
}
|
||||
|
||||
public AjaniNacatlPariah(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.CAT);
|
||||
this.subtype.add(SubType.WARRIOR);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
this.secondSideCardClazz = mage.cards.a.AjaniNacatlAvenger.class;
|
||||
|
||||
// When Ajani, Nacatl Pariah enters the battlefield, create a 2/1 white Cat Warrior creature token.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new CatWarrior21Token())));
|
||||
|
||||
// Whenever one or more other Cats you control die, you may exile Ajani, then return him to the battlefield transformed under his owner's control.
|
||||
this.addAbility(new TransformAbility());
|
||||
this.addAbility(new DiesOneOrMoreCreatureTriggeredAbility(
|
||||
new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.HE),
|
||||
filter
|
||||
));
|
||||
}
|
||||
|
||||
private AjaniNacatlPariah(final AjaniNacatlPariah card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaniNacatlPariah copy() {
|
||||
return new AjaniNacatlPariah(this);
|
||||
}
|
||||
}
|
||||
62
Mage.Sets/src/mage/cards/a/AkulTheUnrepentant.java
Normal file
62
Mage.Sets/src/mage/cards/a/AkulTheUnrepentant.java
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AkulTheUnrepentant extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledCreaturePermanent("other creatures");
|
||||
|
||||
static {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
public AkulTheUnrepentant(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}{R}{R}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.SCORPION);
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.subtype.add(SubType.ROGUE);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// Sacrifice three other creatures: You may put a creature card from your hand onto the battlefield. Activate only as a sorcery and only once each turn.
|
||||
this.addAbility(new LimitedTimesPerTurnActivatedAbility(
|
||||
Zone.BATTLEFIELD,
|
||||
new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_CREATURE_A),
|
||||
new SacrificeTargetCost(3, filter)
|
||||
).setTiming(TimingRule.SORCERY));
|
||||
}
|
||||
|
||||
private AkulTheUnrepentant(final AkulTheUnrepentant card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AkulTheUnrepentant copy() {
|
||||
return new AkulTheUnrepentant(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ class AlelaCunningConquerorTriggeredAbility extends DealCombatDamageControlledTr
|
|||
if (!super.checkTrigger(event, game)) {
|
||||
return false;
|
||||
}
|
||||
Player opponent = game.getPlayer(event.getPlayerId());
|
||||
Player opponent = game.getPlayer(event.getTargetId());
|
||||
if (opponent == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
59
Mage.Sets/src/mage/cards/a/AloeAlchemist.java
Normal file
59
Mage.Sets/src/mage/cards/a/AloeAlchemist.java
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BecomesPlottedSourceTriggeredAbility;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.keyword.PlotAbility;
|
||||
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.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class AloeAlchemist extends CardImpl {
|
||||
|
||||
public AloeAlchemist(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
|
||||
|
||||
this.subtype.add(SubType.PLANT);
|
||||
this.subtype.add(SubType.WARLOCK);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// When Aloe Alchemist becomes plotted, target creature gets +3/+2 and gains trample until end of turn.
|
||||
Ability ability = new BecomesPlottedSourceTriggeredAbility(
|
||||
new BoostTargetEffect(3, 2, Duration.EndOfTurn)
|
||||
.setText("target creature gets +3/+2")
|
||||
);
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
ability.addEffect(
|
||||
new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn)
|
||||
.setText("and gains trample until end of turn")
|
||||
);
|
||||
this.addAbility(ability);
|
||||
|
||||
// Plot {1}{G}
|
||||
this.addAbility(new PlotAbility("{1}{G}"));
|
||||
}
|
||||
|
||||
private AloeAlchemist(final AloeAlchemist card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AloeAlchemist copy() {
|
||||
return new AloeAlchemist(this);
|
||||
}
|
||||
}
|
||||
45
Mage.Sets/src/mage/cards/a/AmbushGigapede.java
Normal file
45
Mage.Sets/src/mage/cards/a/AmbushGigapede.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.target.common.TargetOpponentsCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AmbushGigapede extends CardImpl {
|
||||
|
||||
public AmbushGigapede(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}");
|
||||
|
||||
this.subtype.add(SubType.INSECT);
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Flash
|
||||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// When Ambush Gigapede enters the battlefield, target creature an opponent controls gets -2/-2 until end of turn.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-2, -2));
|
||||
ability.addTarget(new TargetOpponentsCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private AmbushGigapede(final AmbushGigapede card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AmbushGigapede copy() {
|
||||
return new AmbushGigapede(this);
|
||||
}
|
||||
}
|
||||
97
Mage.Sets/src/mage/cards/a/AmyPond.java
Normal file
97
Mage.Sets/src/mage/cards/a/AmyPond.java
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.SavedDamageValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.PartnerWithAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.abilities.keyword.DoctorsCompanionAbility;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterSuspendedCard;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Skiwkr
|
||||
*/
|
||||
public final class AmyPond extends CardImpl {
|
||||
|
||||
private static final FilterSuspendedCard filter = new FilterSuspendedCard("suspended card you own");
|
||||
static {
|
||||
filter.add(TargetController.YOU.getOwnerPredicate());
|
||||
}
|
||||
|
||||
public AmyPond(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Partner with Rory Williams
|
||||
this.addAbility(new PartnerWithAbility("Rory Williams"));
|
||||
|
||||
// Whenever Amy Pond deals combat damage to a player, choose a suspended card you own and remove that many time counters from it.
|
||||
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new AmyPondEffect(SavedDamageValue.MANY),
|
||||
false, true);
|
||||
ability.addTarget(new TargetCardInExile(filter).withNotTarget(true));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Doctor's companion
|
||||
this.addAbility(DoctorsCompanionAbility.getInstance());
|
||||
|
||||
}
|
||||
|
||||
private AmyPond(final AmyPond card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AmyPond copy() {
|
||||
return new AmyPond(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AmyPondEffect extends OneShotEffect {
|
||||
|
||||
private final DynamicValue numberCounters;
|
||||
|
||||
AmyPondEffect(DynamicValue numberCounters) {
|
||||
super(Outcome.Benefit);
|
||||
this.numberCounters = numberCounters;
|
||||
this.staticText= "choose a suspended card you own and remove that many time counters from it";
|
||||
}
|
||||
|
||||
private AmyPondEffect(final AmyPondEffect effect) {
|
||||
super(effect);
|
||||
this.numberCounters = effect.numberCounters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AmyPondEffect copy() {
|
||||
return new AmyPondEffect(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Card card = game.getExile().getCard(source.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
card.removeCounters(CounterType.TIME.toString(), (Integer) getValue("damage"), source, game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
83
Mage.Sets/src/mage/cards/a/AncientCornucopia.java
Normal file
83
Mage.Sets/src/mage/cards/a/AncientCornucopia.java
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.mana.AnyColorManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.ColorlessPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AncientCornucopia extends CardImpl {
|
||||
|
||||
private static final FilterSpell filter = new FilterSpell("a spell that's one or more colors");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(ColorlessPredicate.instance));
|
||||
}
|
||||
|
||||
public AncientCornucopia(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{G}");
|
||||
|
||||
// Whenever you cast a spell that's one or more colors, you may gain 1 life for each of that spell's colors. Do this only once each turn.
|
||||
this.addAbility(new SpellCastControllerTriggeredAbility(
|
||||
new GainLifeEffect(AncientCornucopiaValue.instance)
|
||||
.setText("gain 1 life for each of that spell's colors"), filter, true
|
||||
).setDoOnlyOnceEachTurn(true));
|
||||
|
||||
// {T}: Add one mana of any color.
|
||||
this.addAbility(new AnyColorManaAbility());
|
||||
}
|
||||
|
||||
private AncientCornucopia(final AncientCornucopia card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AncientCornucopia copy() {
|
||||
return new AncientCornucopia(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum AncientCornucopiaValue implements DynamicValue {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
return Optional
|
||||
.ofNullable(effect.getValue("spellCast"))
|
||||
.map(Spell.class::cast)
|
||||
.map(spell -> spell.getColor(game))
|
||||
.map(ObjectColor::getColorCount)
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AncientCornucopiaValue copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "of that spell's colors";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "1";
|
||||
}
|
||||
}
|
||||
66
Mage.Sets/src/mage/cards/a/AngelOfIndemnity.java
Normal file
66
Mage.Sets/src/mage/cards/a/AngelOfIndemnity.java
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.keyword.EncoreAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterPermanentCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AngelOfIndemnity extends CardImpl {
|
||||
|
||||
private static final FilterCard filter
|
||||
= new FilterPermanentCard("permanent card with mana value 4 or less from your graveyard");
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 5));
|
||||
}
|
||||
|
||||
public AngelOfIndemnity(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}");
|
||||
|
||||
this.subtype.add(SubType.ANGEL);
|
||||
this.subtype.add(SubType.WARRIOR);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Lifelink
|
||||
this.addAbility(LifelinkAbility.getInstance());
|
||||
|
||||
// When Angel of Indemnity enters the battlefield, return target permanent card with mana value 4 or less from your graveyard to the battlefield.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect());
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Encore {6}{W}{W}
|
||||
this.addAbility(new EncoreAbility(new ManaCostsImpl<>("{6}{W}{W}")));
|
||||
}
|
||||
|
||||
private AngelOfIndemnity(final AngelOfIndemnity card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngelOfIndemnity copy() {
|
||||
return new AngelOfIndemnity(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ class AngelheartVialTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
79
Mage.Sets/src/mage/cards/a/AngelicSellSword.java
Normal file
79
Mage.Sets/src/mage/cards/a/AngelicSellSword.java
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.MercenaryToken;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AngelicSellSword extends CardImpl {
|
||||
|
||||
public AngelicSellSword(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}");
|
||||
|
||||
this.subtype.add(SubType.ANGEL);
|
||||
this.subtype.add(SubType.MERCENARY);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// Whenever Angelic Sell-Sword or another nontoken creature enters the battlefield under your control, create a 1/1 red Mercenary creature token with "{T}: Target creature you control gets +1/+0 until end of turn. Activate only as a sorcery."
|
||||
this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
|
||||
new CreateTokenEffect(new MercenaryToken()),
|
||||
StaticFilters.FILTER_CREATURE_NON_TOKEN, false, true
|
||||
));
|
||||
|
||||
// Whenever Angelic Sell-Sword attacks, if its power is 6 or greater, draw a card.
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
|
||||
new AttacksTriggeredAbility(new DrawCardSourceControllerEffect(1)),
|
||||
AngelicSellSwordCondition.instance, "Whenever {this} attacks, " +
|
||||
"if its power is 6 or greater, draw a card."
|
||||
));
|
||||
}
|
||||
|
||||
private AngelicSellSword(final AngelicSellSword card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AngelicSellSword copy() {
|
||||
return new AngelicSellSword(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum AngelicSellSwordCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return Optional
|
||||
.ofNullable(source.getSourcePermanentOrLKI(game))
|
||||
.map(MageObject::getPower)
|
||||
.map(MageInt::getValue)
|
||||
.orElse(0) >= 6;
|
||||
}
|
||||
}
|
||||
36
Mage.Sets/src/mage/cards/a/AnkleBiter.java
Normal file
36
Mage.Sets/src/mage/cards/a/AnkleBiter.java
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.keyword.DeathtouchAbility;
|
||||
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 AnkleBiter extends CardImpl {
|
||||
|
||||
public AnkleBiter(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}");
|
||||
|
||||
this.subtype.add(SubType.SNAKE);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Deathtouch
|
||||
this.addAbility(DeathtouchAbility.getInstance());
|
||||
}
|
||||
|
||||
private AnkleBiter(final AnkleBiter card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnkleBiter copy() {
|
||||
return new AnkleBiter(this);
|
||||
}
|
||||
}
|
||||
67
Mage.Sets/src/mage/cards/a/AnnieFlashTheVeteran.java
Normal file
67
Mage.Sets/src/mage/cards/a/AnnieFlashTheVeteran.java
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BecomesTappedSourceTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.CastFromEverywhereSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.common.FilterPermanentCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class AnnieFlashTheVeteran extends CardImpl {
|
||||
|
||||
private static final FilterPermanentCard filter =
|
||||
new FilterPermanentCard("permanent card with mana value 3 or less from your graveyard");
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 3));
|
||||
}
|
||||
|
||||
public AnnieFlashTheVeteran(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}{W}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.ROGUE);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Flash
|
||||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// When Annie Flash, the Veteran enters the battlefield, if you cast it, return target permanent card with mana value 3 or less from your graveyard to the battlefield tapped.
|
||||
Ability ability = new ConditionalInterveningIfTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(true)),
|
||||
CastFromEverywhereSourceCondition.instance,
|
||||
"When {this} enters the battlefield, if you cast it, "
|
||||
+ "return target permanent card with mana value 3 or less from your graveyard to the battlefield tapped"
|
||||
);
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Whenever Annie Flash becomes tapped, exile the top two cards of your library. You may play those cards this turn.
|
||||
this.addAbility(new BecomesTappedSourceTriggeredAbility(new ExileTopXMayPlayUntilEffect(2, Duration.EndOfTurn)));
|
||||
}
|
||||
|
||||
private AnnieFlashTheVeteran(final AnnieFlashTheVeteran card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnieFlashTheVeteran copy() {
|
||||
return new AnnieFlashTheVeteran(this);
|
||||
}
|
||||
}
|
||||
96
Mage.Sets/src/mage/cards/a/AnnieJoinsUp.java
Normal file
96
Mage.Sets/src/mage/cards/a/AnnieJoinsUp.java
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.NumberOfTriggersEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AnnieJoinsUp extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker an opponent controls");
|
||||
|
||||
static {
|
||||
filter.add(TargetController.OPPONENT.getControllerPredicate());
|
||||
}
|
||||
|
||||
public AnnieJoinsUp(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{G}{W}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
|
||||
// When Annie Joins Up enters the battlefield, it deals 5 damage to target creature or planeswalker an opponent controls.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(5));
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
this.addAbility(ability);
|
||||
|
||||
// If a triggered ability of a legendary creature you control triggers, that ability triggers an additional time.
|
||||
this.addAbility(new SimpleStaticAbility(new AnnieJoinsUpEffect()));
|
||||
}
|
||||
|
||||
private AnnieJoinsUp(final AnnieJoinsUp card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnieJoinsUp copy() {
|
||||
return new AnnieJoinsUp(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AnnieJoinsUpEffect extends ReplacementEffectImpl {
|
||||
|
||||
AnnieJoinsUpEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
staticText = "if a triggered ability of a legendary creature you control triggers, " +
|
||||
"that ability triggers an additional time";
|
||||
}
|
||||
|
||||
private AnnieJoinsUpEffect(final AnnieJoinsUpEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnieJoinsUpEffect copy() {
|
||||
return new AnnieJoinsUpEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.NUMBER_OF_TRIGGERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (!(event instanceof NumberOfTriggersEvent)) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(((NumberOfTriggersEvent) event).getSourceId());
|
||||
return permanent != null
|
||||
&& permanent.isControlledBy(source.getControllerId())
|
||||
&& permanent.isLegendary(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
event.setAmount(CardUtil.overflowInc(event.getAmount(), 1));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
89
Mage.Sets/src/mage/cards/a/AnotherRound.java
Normal file
89
Mage.Sets/src/mage/cards/a/AnotherRound.java
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ExileThenReturnTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class AnotherRound extends CardImpl {
|
||||
|
||||
public AnotherRound(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{2}{W}");
|
||||
|
||||
// Exile any number of creatures you control, then return them to the battlefield under their owner's control. Then repeat this process X times.
|
||||
this.getSpellAbility().addEffect(new AnotherRoundEffect());
|
||||
}
|
||||
|
||||
private AnotherRound(final AnotherRound card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnotherRound copy() {
|
||||
return new AnotherRound(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AnotherRoundEffect extends OneShotEffect {
|
||||
|
||||
public AnotherRoundEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Exile any number of creatures you control, "
|
||||
+ "then return them to the battlefield under their owner's control. "
|
||||
+ "Then repeat this process X more times.";
|
||||
}
|
||||
|
||||
private AnotherRoundEffect(final AnotherRoundEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int xValue = ManacostVariableValue.REGULAR.calculate(game, source, this);
|
||||
TargetControlledCreaturePermanent target =
|
||||
new TargetControlledCreaturePermanent(
|
||||
0, Integer.MAX_VALUE,
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURE, true
|
||||
);
|
||||
|
||||
for (int i = 0; i <= xValue; ++i) {
|
||||
target.clearChosen();
|
||||
controller.chooseTarget(Outcome.Benefit, target, source, game);
|
||||
new ExileThenReturnTargetEffect(false, true)
|
||||
.setTargetPointer(new FixedTargets(
|
||||
target.getTargets()
|
||||
.stream()
|
||||
.map(id -> new MageObjectReference(id, game))
|
||||
.collect(Collectors.toList())
|
||||
)).apply(game, source);
|
||||
game.getState().processAction(game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnotherRoundEffect copy() {
|
||||
return new AnotherRoundEffect(this);
|
||||
}
|
||||
}
|
||||
184
Mage.Sets/src/mage/cards/a/AnzragsRampage.java
Normal file
184
Mage.Sets/src/mage/cards/a/AnzragsRampage.java
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DestroyAllEffect;
|
||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterArtifactPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
* @author Cguy7777
|
||||
*/
|
||||
public final class AnzragsRampage extends CardImpl {
|
||||
|
||||
private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("artifacts you don't control");
|
||||
|
||||
static {
|
||||
filter.add(TargetController.NOT_YOU.getControllerPredicate());
|
||||
}
|
||||
|
||||
private static final ValueHint hint = new ValueHint(
|
||||
"Artifacts put into graveyards from the battlefield this turn", AnzragsRampageValue.instance);
|
||||
|
||||
public AnzragsRampage(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}{R}");
|
||||
|
||||
// Destroy all artifacts you don't control, then exile the top X cards of your library, where X is the number of artifacts that were put into graveyards from the battlefield this turn.
|
||||
// You may put a creature card exiled this way onto the battlefield. It gains haste. Return it to your hand at the beginning of the next end step.
|
||||
this.getSpellAbility().addEffect(new DestroyAllEffect(filter));
|
||||
this.getSpellAbility().addEffect(new AnzragsRampageEffect().concatBy(", then"));
|
||||
this.getSpellAbility().addWatcher(new AnzragsRampageWatcher());
|
||||
this.getSpellAbility().addHint(hint);
|
||||
}
|
||||
|
||||
private AnzragsRampage(final AnzragsRampage card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnzragsRampage copy() {
|
||||
return new AnzragsRampage(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AnzragsRampageWatcher extends Watcher {
|
||||
|
||||
private int artifactsDied;
|
||||
|
||||
AnzragsRampageWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
if (zEvent.isDiesEvent() && zEvent.getTarget().isArtifact(game)) {
|
||||
artifactsDied++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
artifactsDied = 0;
|
||||
}
|
||||
|
||||
public int getArtifactsDied() {
|
||||
return artifactsDied;
|
||||
}
|
||||
}
|
||||
|
||||
enum AnzragsRampageValue implements DynamicValue {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
AnzragsRampageWatcher watcher = game.getState().getWatcher(AnzragsRampageWatcher.class);
|
||||
if (watcher == null) {
|
||||
return 0;
|
||||
}
|
||||
return watcher.getArtifactsDied();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnzragsRampageValue copy() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
class AnzragsRampageEffect extends OneShotEffect {
|
||||
|
||||
AnzragsRampageEffect() {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
staticText = "exile the top X cards of your library, where X is the number of artifacts " +
|
||||
"that were put into graveyards from the battlefield this turn. " +
|
||||
"You may put a creature card exiled this way onto the battlefield. It gains haste. " +
|
||||
"Return it to your hand at the beginning of the next end step";
|
||||
}
|
||||
|
||||
private AnzragsRampageEffect(final AnzragsRampageEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Exile the top X cards of your library,
|
||||
// where X is the number of artifacts that were put into graveyards from the battlefield this turn.
|
||||
Cards cards = new CardsImpl(controller.getLibrary()
|
||||
.getTopCards(game, AnzragsRampageValue.instance.calculate(game, source, this)));
|
||||
controller.moveCardsToExile(
|
||||
cards.getCards(game), source, game, true,
|
||||
CardUtil.getExileZoneId(game, source),
|
||||
CardUtil.createObjectRealtedWindowTitle(source, game, null));
|
||||
|
||||
// You may put a creature card exiled this way onto the battlefield.
|
||||
TargetCard targetCard = new TargetCardInExile(
|
||||
0, 1, StaticFilters.FILTER_CARD_CREATURE, CardUtil.getExileZoneId(game, source));
|
||||
targetCard.withNotTarget(true);
|
||||
controller.choose(outcome, targetCard, source, game);
|
||||
Card card = game.getCard(targetCard.getFirstTarget());
|
||||
if (card == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) {
|
||||
Permanent permanent = game.getPermanent(card.getId());
|
||||
if (permanent == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// It gains haste.
|
||||
ContinuousEffect hasteEffect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom);
|
||||
hasteEffect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(hasteEffect, source);
|
||||
|
||||
// Return it to your hand at the beginning of the next end step.
|
||||
ReturnToHandTargetEffect returnToHandEffect = new ReturnToHandTargetEffect();
|
||||
returnToHandEffect.setText("return it to your hand");
|
||||
returnToHandEffect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(returnToHandEffect);
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnzragsRampageEffect copy() {
|
||||
return new AnzragsRampageEffect(this);
|
||||
}
|
||||
}
|
||||
83
Mage.Sets/src/mage/cards/a/ArcadeGannon.java
Normal file
83
Mage.Sets/src/mage/cards/a/ArcadeGannon.java
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CastFromGraveyardOnceEachTurnAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author justinjohnson14
|
||||
*/
|
||||
public final class ArcadeGannon extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("an artifact or Human spell from your graveyard with mana value less than or equal to the number of quest counters on {this}");
|
||||
|
||||
static{
|
||||
filter.add(Predicates.or(
|
||||
CardType.ARTIFACT.getPredicate(),
|
||||
SubType.HUMAN.getPredicate()
|
||||
));
|
||||
filter.add(ArcadeGannonPredicate.instance);
|
||||
}
|
||||
|
||||
public ArcadeGannon(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.DOCTOR);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// {T}: Draw a card, then discard a card. Put a quest counter on Arcade Gannon.
|
||||
Ability ability = (new SimpleActivatedAbility(new DrawDiscardControllerEffect(1,1), new TapSourceCost()));
|
||||
ability.addEffect(new AddCountersSourceEffect(CounterType.QUEST.createInstance(1)));
|
||||
this.addAbility(ability);
|
||||
|
||||
// For Auld Lang Syne -- Once during each of your turns, you may cast an artifact or Human spell from your graveyard with mana value less than or equal to the number of quest counters on Arcade Gannon.
|
||||
this.addAbility(new CastFromGraveyardOnceEachTurnAbility(filter).withFlavorWord("For Auld Lang Syne"));
|
||||
}
|
||||
|
||||
private ArcadeGannon(final ArcadeGannon card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArcadeGannon copy() {
|
||||
return new ArcadeGannon(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum ArcadeGannonPredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
|
||||
Permanent sourcePermanent = input.getSource().getSourcePermanentOrLKI(game);
|
||||
return sourcePermanent != null && input.getObject().getManaValue() <= sourcePermanent.getCounters(game).getCount(CounterType.QUEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "mana value less than or equal to {this}'s power";
|
||||
}
|
||||
}
|
||||
51
Mage.Sets/src/mage/cards/a/ArcaneHeist.java
Normal file
51
Mage.Sets/src/mage/cards/a/ArcaneHeist.java
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.effects.common.CipherEffect;
|
||||
import mage.abilities.effects.common.MayCastTargetCardEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.CastManaAdjustment;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.target.common.TargetCardInOpponentsGraveyard;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class ArcaneHeist extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("instant or sorcery card from an opponent's graveyard");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.INSTANT.getPredicate(),
|
||||
CardType.SORCERY.getPredicate()));
|
||||
}
|
||||
|
||||
public ArcaneHeist(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}{U}");
|
||||
|
||||
// You may cast target instant or sorcery card from an opponent's graveyard without paying its mana cost. If that spell would be put into their graveyard, exile it instead.
|
||||
this.getSpellAbility().addEffect(
|
||||
new MayCastTargetCardEffect(CastManaAdjustment.WITHOUT_PAYING_MANA_COST, true)
|
||||
.setText("You may cast target instant or sorcery card from an opponent's graveyard without paying its mana cost. "
|
||||
+ "If that spell would be put into their graveyard, exile it instead.")
|
||||
);
|
||||
this.getSpellAbility().addTarget(new TargetCardInOpponentsGraveyard(filter));
|
||||
|
||||
// Cipher
|
||||
this.getSpellAbility().addEffect(new CipherEffect());
|
||||
}
|
||||
|
||||
private ArcaneHeist(final ArcaneHeist card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArcaneHeist copy() {
|
||||
return new ArcaneHeist(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ class ArcbondDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT;
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PERMANENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
96
Mage.Sets/src/mage/cards/a/ArchmagesNewt.java
Normal file
96
Mage.Sets/src/mage/cards/a/ArchmagesNewt.java
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.condition.common.SaddledCondition;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.keyword.FlashbackAbility;
|
||||
import mage.abilities.keyword.SaddleAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class ArchmagesNewt extends CardImpl {
|
||||
|
||||
public ArchmagesNewt(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
|
||||
|
||||
this.subtype.add(SubType.SALAMANDER);
|
||||
this.subtype.add(SubType.MOUNT);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Whenever Archmage's Newt deals combat damage to a player, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. That card gains flashback {0} until end of turn instead if Archmage's Newt is saddled.
|
||||
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ArchmagesNewtEffect(), false);
|
||||
ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Saddle 3
|
||||
this.addAbility(new SaddleAbility(3));
|
||||
}
|
||||
|
||||
private ArchmagesNewt(final ArchmagesNewt card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArchmagesNewt copy() {
|
||||
return new ArchmagesNewt(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ArchmagesNewtEffect extends ContinuousEffectImpl {
|
||||
|
||||
private boolean saddled = false;
|
||||
|
||||
ArchmagesNewtEffect() {
|
||||
super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
|
||||
this.staticText = "target instant or sorcery card in your graveyard gains flashback until end of turn. " +
|
||||
"The flashback cost is equal to its mana cost. That card gains flashback {0} until end of turn instead if {this} is saddled";
|
||||
}
|
||||
|
||||
private ArchmagesNewtEffect(final ArchmagesNewtEffect effect) {
|
||||
super(effect);
|
||||
this.saddled = effect.saddled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArchmagesNewtEffect copy() {
|
||||
return new ArchmagesNewtEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
this.saddled = SaddledCondition.instance.apply(game, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Card card = game.getCard(getTargetPointer().getFirst(game, source));
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
FlashbackAbility ability;
|
||||
if (saddled) {
|
||||
ability = new FlashbackAbility(card, new GenericManaCost(0));
|
||||
} else {
|
||||
ability = new FlashbackAbility(card, card.getManaCost());
|
||||
}
|
||||
ability.setSourceId(card.getId());
|
||||
ability.setControllerId(card.getOwnerId());
|
||||
game.getState().addOtherAbility(card, ability);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import mage.MageInt;
|
|||
import mage.abilities.common.CantBlockAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.PayLifeCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.keyword.IndestructibleAbility;
|
||||
import mage.abilities.keyword.SquadAbility;
|
||||
|
|
@ -28,7 +29,7 @@ public final class ArcoFlagellant extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Squad {2}
|
||||
this.addAbility(new SquadAbility());
|
||||
this.addAbility(new SquadAbility(new GenericManaCost(2)));
|
||||
|
||||
// Arco-Flagellant can't block.
|
||||
this.addAbility(new CantBlockAbility());
|
||||
|
|
|
|||
96
Mage.Sets/src/mage/cards/a/AridArchway.java
Normal file
96
Mage.Sets/src/mage/cards/a/AridArchway.java
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageObjectReference;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTappedAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AridArchway extends CardImpl {
|
||||
|
||||
public AridArchway(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||
|
||||
this.subtype.add(SubType.DESERT);
|
||||
|
||||
// Arid Archway enters the battlefield tapped.
|
||||
this.addAbility(new EntersBattlefieldTappedAbility());
|
||||
|
||||
// When Arid Archway enters the battlefield, return a land you control to its owner's hand. If another Desert was returned this way, surveil 1.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new AridArchwayEffect()));
|
||||
|
||||
// {T}: Add {C}{C}.
|
||||
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.ColorlessMana(2), new TapSourceCost()));
|
||||
}
|
||||
|
||||
private AridArchway(final AridArchway card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AridArchway copy() {
|
||||
return new AridArchway(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AridArchwayEffect extends OneShotEffect {
|
||||
|
||||
AridArchwayEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "return a land you control to its owner's hand. If another Desert was returned this way, surveil 1";
|
||||
}
|
||||
|
||||
private AridArchwayEffect(final AridArchwayEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AridArchwayEffect copy() {
|
||||
return new AridArchwayEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (!game.getBattlefield().contains(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, source, game, 1)) {
|
||||
return false;
|
||||
}
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
TargetPermanent target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND);
|
||||
target.withNotTarget(true);
|
||||
player.choose(outcome, target, source, game);
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
boolean flag = permanent.hasSubtype(SubType.DESERT, game)
|
||||
&& !new MageObjectReference(permanent, game)
|
||||
.refersTo(source, game);
|
||||
player.moveCards(permanent, Zone.HAND, source, game);
|
||||
if (flag) {
|
||||
player.surveil(1, source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
49
Mage.Sets/src/mage/cards/a/ArmoredArmadillo.java
Normal file
49
Mage.Sets/src/mage/cards/a/ArmoredArmadillo.java
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.SourcePermanentToughnessValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.abilities.keyword.WardAbility;
|
||||
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 ArmoredArmadillo extends CardImpl {
|
||||
|
||||
public ArmoredArmadillo(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
|
||||
|
||||
this.subtype.add(SubType.ARMADILLO);
|
||||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Ward {1}
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{1}")));
|
||||
|
||||
// {3}{W}: Armored Armadillo gets +X/+0 until end of turn, where X is its toughness.
|
||||
this.addAbility(new SimpleActivatedAbility(
|
||||
new BoostSourceEffect(
|
||||
SourcePermanentToughnessValue.getInstance(), StaticValue.get(0), Duration.EndOfTurn
|
||||
).setText("{this} gets +X/+0 until end of turn, where X is its toughness."),
|
||||
new ManaCostsImpl<>("{3}{W}")));
|
||||
}
|
||||
|
||||
private ArmoredArmadillo(final ArmoredArmadillo card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArmoredArmadillo copy() {
|
||||
return new ArmoredArmadillo(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ class AsLuckWouldHaveItTriggeredAbility extends TriggeredAbilityImpl {
|
|||
// Any die roll with a numerical result will add luck counters to As Luck Would Have It.
|
||||
// Rolling the planar die will not cause the second ability to trigger.
|
||||
// (2018-01-19)
|
||||
if (this.isControlledBy(event.getPlayerId()) && drEvent.getRollDieType() == RollDieType.NUMERICAL) {
|
||||
if (this.isControlledBy(event.getTargetId()) && drEvent.getRollDieType() == RollDieType.NUMERICAL) {
|
||||
// silver border card must look for "result" instead "natural result"
|
||||
this.getEffects().setValue("rolled", drEvent.getResult());
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -3,21 +3,23 @@ package mage.cards.a;
|
|||
import mage.MageIdentifier;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.OnceEachTurnCastWatcher;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author xenohedron
|
||||
|
|
@ -33,9 +35,9 @@ public final class AssembleThePlayers extends CardImpl {
|
|||
// Once each turn, you may cast a creature spell with power 2 or less from the top of your library.
|
||||
this.addAbility(
|
||||
new SimpleStaticAbility(new AssembleThePlayersPlayTopEffect())
|
||||
.setIdentifier(MageIdentifier.AssembleThePlayersWatcher)
|
||||
.addHint(AssembleThePlayersHint.instance),
|
||||
new AssembleThePlayersWatcher()
|
||||
.setIdentifier(MageIdentifier.OnceEachTurnCastWatcher)
|
||||
.addHint(OnceEachTurnCastWatcher.getHint()),
|
||||
new OnceEachTurnCastWatcher()
|
||||
// all based on Johann, Apprentice Sorcerer
|
||||
);
|
||||
|
||||
|
|
@ -51,30 +53,6 @@ public final class AssembleThePlayers extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
enum AssembleThePlayersHint implements Hint {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public String getText(Game game, Ability ability) {
|
||||
AssembleThePlayersWatcher watcher = game.getState().getWatcher(AssembleThePlayersWatcher.class);
|
||||
if (watcher != null) {
|
||||
boolean used = watcher.isAbilityUsed(ability.getControllerId(), new MageObjectReference(ability.getSourceId(), game));
|
||||
if (used) {
|
||||
Player player = game.getPlayer(ability.getControllerId());
|
||||
if (player != null) {
|
||||
return "A spell has been cast by " + player.getLogName() + " with {this} this turn.";
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssembleThePlayersHint copy() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class AssembleThePlayersPlayTopEffect extends AsThoughEffectImpl {
|
||||
|
||||
AssembleThePlayersPlayTopEffect() {
|
||||
|
|
@ -98,62 +76,41 @@ class AssembleThePlayersPlayTopEffect extends AsThoughEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
// Only applies for the controller of the ability.
|
||||
if (!affectedControllerId.equals(source.getControllerId())) {
|
||||
return false;
|
||||
}
|
||||
throw new IllegalArgumentException("Wrong code usage: can't call applies method on empty affectedAbility");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
AssembleThePlayersWatcher watcher = game.getState().getWatcher(AssembleThePlayersWatcher.class);
|
||||
Permanent sourceObject = game.getPermanent(source.getSourceId());
|
||||
if (controller == null || watcher == null || sourceObject == null) {
|
||||
OnceEachTurnCastWatcher watcher = game.getState().getWatcher(OnceEachTurnCastWatcher.class);
|
||||
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (controller == null || sourcePermanent == null || watcher == null) {
|
||||
return false;
|
||||
}
|
||||
// Only applies for the controller of the ability.
|
||||
if (!playerId.equals(source.getControllerId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Has the ability already been used this turn by the player?
|
||||
if (watcher.isAbilityUsed(controller.getId(), new MageObjectReference(sourceObject, game))) {
|
||||
if (watcher.isAbilityUsed(controller.getId(), new MageObjectReference(sourcePermanent, game))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Card card = game.getCard(objectId);
|
||||
Card topCard = controller.getLibrary().getFromTop(game);
|
||||
// Is the card attempted to be played the top card of the library?
|
||||
if (card == null || topCard == null || !topCard.getId().equals(card.getMainCard().getId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only works for creatures with power 2 or less
|
||||
return card.isCreature(game) && card.getPower().getValue() <=2;
|
||||
}
|
||||
}
|
||||
|
||||
class AssembleThePlayersWatcher extends Watcher {
|
||||
|
||||
// player -> set of all permanent's mor that already used their once per turn Approval.
|
||||
private final Map<UUID, Set<MageObjectReference>> usedFrom = new HashMap<>();
|
||||
|
||||
public AssembleThePlayersWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
UUID playerId = event.getPlayerId();
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST
|
||||
&& event.hasApprovingIdentifier(MageIdentifier.AssembleThePlayersWatcher)
|
||||
&& playerId != null) {
|
||||
usedFrom.computeIfAbsent(playerId, k -> new HashSet<>())
|
||||
.add(event.getAdditionalReference().getApprovingMageObjectReference());
|
||||
if (affectedAbility instanceof SpellAbility) {
|
||||
SpellAbility spellAbility = (SpellAbility) affectedAbility;
|
||||
if (spellAbility.getManaCosts().isEmpty()
|
||||
|| !spellAbility.spellCanBeActivatedRegularlyNow(playerId, game)) {
|
||||
return false;
|
||||
}
|
||||
Card cardToCheck = spellAbility.getCharacteristics(game);
|
||||
// Only works for creatures with power 2 or less
|
||||
return cardToCheck.isCreature(game) && cardToCheck.getPower().getValue() <= 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
usedFrom.clear();
|
||||
}
|
||||
|
||||
public boolean isAbilityUsed(UUID playerId, MageObjectReference mor) {
|
||||
return usedFrom.getOrDefault(playerId, Collections.emptySet()).contains(mor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
134
Mage.Sets/src/mage/cards/a/AssimilationAegis.java
Normal file
134
Mage.Sets/src/mage/cards/a/AssimilationAegis.java
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttachedToCreatureSourceTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CopyEffect;
|
||||
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class AssimilationAegis extends CardImpl {
|
||||
|
||||
public AssimilationAegis(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{W}{U}");
|
||||
|
||||
this.subtype.add(SubType.EQUIPMENT);
|
||||
|
||||
// When Assimilation Aegis enters the battlefield, exile up to one target creature until Assimilation Aegis leaves the battlefield.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect());
|
||||
ability.addTarget(new TargetCreaturePermanent(0, 1));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Whenever Assimilation Aegis becomes attached to a creature, for as long as Assimilation Aegis remains attached to it, that creature becomes a copy of a creature card exiled with Assimilation Aegis.
|
||||
this.addAbility(new AttachedToCreatureSourceTriggeredAbility(new AssimilationAegisEffect(), false));
|
||||
|
||||
// Equip {2}
|
||||
this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2)));
|
||||
}
|
||||
|
||||
private AssimilationAegis(final AssimilationAegis card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssimilationAegis copy() {
|
||||
return new AssimilationAegis(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Similar to Blade of Shared Souls.
|
||||
class AssimilationAegisEffect extends OneShotEffect {
|
||||
|
||||
AssimilationAegisEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "for as long as {this} remains attached to it, " +
|
||||
"that creature becomes a copy of a creature card exiled with {this}";
|
||||
}
|
||||
|
||||
private AssimilationAegisEffect(final AssimilationAegisEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssimilationAegisEffect copy() {
|
||||
return new AssimilationAegisEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent attachedPermanent = (Permanent) getValue("attachedPermanent");
|
||||
Permanent equipment = source.getSourcePermanentIfItStillExists(game);
|
||||
if (attachedPermanent == null
|
||||
|| equipment == null
|
||||
|| !equipment.isAttachedTo(attachedPermanent.getId())) {
|
||||
return false;
|
||||
}
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source);
|
||||
TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD_CREATURE, exileId);
|
||||
target.withNotTarget(true);
|
||||
if (!target.choose(Outcome.Benefit, player.getId(), source.getId(), source, game)) {
|
||||
return false;
|
||||
}
|
||||
Card copyCard = game.getCard(target.getFirstTarget());
|
||||
if (copyCard == null) {
|
||||
return false;
|
||||
}
|
||||
game.addEffect(new AssimilationAegisCopyEffect(copyCard, attachedPermanent), source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Similar to Blade of Shared Souls.
|
||||
class AssimilationAegisCopyEffect extends CopyEffect {
|
||||
|
||||
AssimilationAegisCopyEffect(Card copyCard, Permanent attachedPermanent) {
|
||||
super(Duration.Custom, copyCard, attachedPermanent.getId());
|
||||
}
|
||||
|
||||
private AssimilationAegisCopyEffect(final AssimilationAegisCopyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssimilationAegisCopyEffect copy() {
|
||||
return new AssimilationAegisCopyEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInactive(Ability source, Game game) {
|
||||
if (super.isInactive(source, game)) {
|
||||
return true;
|
||||
}
|
||||
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (sourcePermanent == null || !sourcePermanent.isAttachedTo(this.copyToObjectId)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
52
Mage.Sets/src/mage/cards/a/AtKnifepoint.java
Normal file
52
Mage.Sets/src/mage/cards/a/AtKnifepoint.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.abilities.common.CommittedCrimeTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.MyTurnCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||
import mage.abilities.keyword.FirstStrikeAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.mageobject.OutlawPredicate;
|
||||
import mage.game.permanent.token.MercenaryToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class AtKnifepoint extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent();
|
||||
|
||||
static {
|
||||
filter.add(OutlawPredicate.instance);
|
||||
}
|
||||
|
||||
public AtKnifepoint(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{R}");
|
||||
|
||||
// As long as it's your turn, outlaws you control have first strike.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filter),
|
||||
MyTurnCondition.instance, "as long as it's your turn, outlaws you control have first strike"
|
||||
)));
|
||||
|
||||
// Whenever you commit a crime, create a 1/1 red Mercenary creature token with "{T}: Target creature you control gets +1/+0 until end of turn. Activate only as a sorcery." This ability triggers only once each turn.
|
||||
this.addAbility(new CommittedCrimeTriggeredAbility(new CreateTokenEffect(new MercenaryToken())).setTriggersOnceEachTurn(true));
|
||||
}
|
||||
|
||||
private AtKnifepoint(final AtKnifepoint card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AtKnifepoint copy() {
|
||||
return new AtKnifepoint(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import mage.abilities.condition.common.CovenCondition;
|
|||
import mage.abilities.decorator.ConditionalAsThoughEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect;
|
||||
import mage.abilities.effects.common.continuous.PlayTheTopCardEffect;
|
||||
import mage.abilities.effects.common.continuous.PlayFromTopOfLibraryEffect;
|
||||
import mage.abilities.hint.common.CovenHint;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.SubType;
|
||||
|
|
@ -41,11 +41,11 @@ public final class AugurOfAutumn extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(new LookAtTopCardOfLibraryAnyTimeEffect()));
|
||||
|
||||
// You may play lands from the top of your library.
|
||||
this.addAbility(new SimpleStaticAbility(new PlayTheTopCardEffect(TargetController.YOU, filter, false)));
|
||||
this.addAbility(new SimpleStaticAbility(new PlayFromTopOfLibraryEffect(filter)));
|
||||
|
||||
// Coven — As long as you control three or more creatures with different powers, you may cast creature spells from the top of your library.
|
||||
Effect effect = new ConditionalAsThoughEffect(
|
||||
new PlayTheTopCardEffect(TargetController.YOU, filter2, false),
|
||||
new PlayFromTopOfLibraryEffect(filter2),
|
||||
CovenCondition.instance
|
||||
);
|
||||
effect.setText("As long as you control three or more creatures with different powers, you may cast creature spells from the top of your library");
|
||||
|
|
|
|||
85
Mage.Sets/src/mage/cards/a/AureliasVindicator.java
Normal file
85
Mage.Sets/src/mage/cards/a/AureliasVindicator.java
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.MorphManacostVariableValue;
|
||||
import mage.abilities.effects.common.ExileTargetForSourceEffect;
|
||||
import mage.abilities.effects.common.ReturnFromExileForSourceEffect;
|
||||
import mage.abilities.keyword.DisguiseAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.abilities.keyword.WardAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInGraveyardBattlefieldOrStack;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class AureliasVindicator extends CardImpl {
|
||||
|
||||
public AureliasVindicator(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
|
||||
|
||||
this.subtype.add(SubType.ANGEL);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Lifelink
|
||||
this.addAbility(LifelinkAbility.getInstance());
|
||||
|
||||
// Ward {2}
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}")));
|
||||
|
||||
// Disguise {X}{3}{W}
|
||||
this.addAbility(new DisguiseAbility(this, new ManaCostsImpl<>("{X}{3}{W}")));
|
||||
|
||||
// When Aurelia's Vindicator is turned face up, exile up to X other target creatures from the battlefield and/or creature cards from graveyards.
|
||||
Ability ability = new TurnedFaceUpSourceTriggeredAbility(new ExileTargetForSourceEffect()
|
||||
.setText("exile up to X other target creatures from the battlefield and/or creature cards from graveyards"));
|
||||
ability.setTargetAdjuster(AureliasVindicatorAdjuster.instance);
|
||||
this.addAbility(ability);
|
||||
|
||||
// When Aurelia's Vindicator leaves the battlefield, return the exiled cards to their owners' hands.
|
||||
this.addAbility(new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.HAND)
|
||||
.withText(true, true, false), false));
|
||||
}
|
||||
|
||||
private AureliasVindicator(final AureliasVindicator card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AureliasVindicator copy() {
|
||||
return new AureliasVindicator(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum AureliasVindicatorAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
ability.getTargets().clear();
|
||||
int xValue = MorphManacostVariableValue.instance.calculate(game, ability, null);
|
||||
Target target = new TargetCardInGraveyardBattlefieldOrStack(
|
||||
0, xValue, StaticFilters.FILTER_CARD_CREATURE, StaticFilters.FILTER_PERMANENT_CREATURES
|
||||
);
|
||||
ability.addTarget(target);
|
||||
}
|
||||
}
|
||||
104
Mage.Sets/src/mage/cards/a/AvenInterrupter.java
Normal file
104
Mage.Sets/src/mage/cards/a/AvenInterrupter.java
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.PlotAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.card.CastFromZonePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class AvenInterrupter extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("spells your opponents cast from graveyards or from exile");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
new CastFromZonePredicate(Zone.GRAVEYARD),
|
||||
new CastFromZonePredicate(Zone.EXILED)
|
||||
));
|
||||
}
|
||||
|
||||
public AvenInterrupter(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}");
|
||||
|
||||
this.subtype.add(SubType.BIRD);
|
||||
this.subtype.add(SubType.ROGUE);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Flash
|
||||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// When Aven Interrupter enters the battlefield, exile target spell. It becomes plotted.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new AvenInterrupterEffect());
|
||||
ability.addTarget(new TargetSpell());
|
||||
this.addAbility(ability);
|
||||
|
||||
// Spells your opponents cast from graveyards or from exile cost 2 more to cast.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
new SpellsCostIncreasingAllEffect(2, filter, TargetController.OPPONENT)
|
||||
));
|
||||
}
|
||||
|
||||
private AvenInterrupter(final AvenInterrupter card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AvenInterrupter copy() {
|
||||
return new AvenInterrupter(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AvenInterrupterEffect extends OneShotEffect {
|
||||
|
||||
AvenInterrupterEffect() {
|
||||
super(Outcome.Detriment);
|
||||
staticText = "exile target spell. It becomes plotted";
|
||||
}
|
||||
|
||||
private AvenInterrupterEffect(final AvenInterrupterEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AvenInterrupterEffect copy() {
|
||||
return new AvenInterrupterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (controller == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source));
|
||||
if (spell == null) {
|
||||
return false;
|
||||
}
|
||||
return PlotAbility.doExileAndPlotCard(spell, game, source);
|
||||
}
|
||||
}
|
||||
53
Mage.Sets/src/mage/cards/b/BackInTown.java
Normal file
53
Mage.Sets/src/mage/cards/b/BackInTown.java
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.OutlawPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BackInTown extends CardImpl {
|
||||
|
||||
public BackInTown(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{2}{B}");
|
||||
|
||||
// Return X target outlaw creature cards from your graveyard to the battlefield.
|
||||
this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()
|
||||
.setText("return X target outlaw creature cards from your graveyard to the battlefield"));
|
||||
this.getSpellAbility().setTargetAdjuster(BackInTownAdjuster.instance);
|
||||
}
|
||||
|
||||
private BackInTown(final BackInTown card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BackInTown copy() {
|
||||
return new BackInTown(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum BackInTownAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
private static final FilterCard filter = new FilterCard("outlaw cards");
|
||||
|
||||
static {
|
||||
filter.add(OutlawPredicate.instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
ability.getTargets().clear();
|
||||
ability.addTarget(new TargetCardInYourGraveyard(ability.getManaCostsToPay().getX(), filter));
|
||||
}
|
||||
}
|
||||
41
Mage.Sets/src/mage/cards/b/BadlandsRevival.java
Normal file
41
Mage.Sets/src/mage/cards/b/BadlandsRevival.java
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterPermanentCard;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.targetpointer.SecondTargetPointer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BadlandsRevival extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterPermanentCard("permanent card from your graveyard");
|
||||
|
||||
public BadlandsRevival(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{G}");
|
||||
|
||||
// Return up to one target creature card from your graveyard to the battlefield. Return up to one target permanent card from your graveyard to your hand.
|
||||
this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect());
|
||||
this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect().setTargetPointer(new SecondTargetPointer()));
|
||||
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 1, StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD));
|
||||
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 1, filter));
|
||||
}
|
||||
|
||||
private BadlandsRevival(final BadlandsRevival card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BadlandsRevival copy() {
|
||||
return new BadlandsRevival(this);
|
||||
}
|
||||
}
|
||||
52
Mage.Sets/src/mage/cards/b/BanditsHaul.java
Normal file
52
Mage.Sets/src/mage/cards/b/BanditsHaul.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CommittedCrimeTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.mana.AnyColorManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.counters.CounterType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BanditsHaul extends CardImpl {
|
||||
|
||||
public BanditsHaul(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
// Whenever you commit a crime, put a loot counter on Bandit's Haul. This ability triggers only once each turn.
|
||||
this.addAbility(new CommittedCrimeTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.LOOT.createInstance())
|
||||
).setTriggersOnceEachTurn(true));
|
||||
|
||||
// {T}: Add one mana of any color.
|
||||
this.addAbility(new AnyColorManaAbility());
|
||||
|
||||
// {2}, {T}, Remove two loot counters from Bandit's Haul: Draw a card.
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
new DrawCardSourceControllerEffect(1), new GenericManaCost(2)
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new RemoveCountersSourceCost(CounterType.LOOT.createInstance(2)));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BanditsHaul(final BanditsHaul card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BanditsHaul copy() {
|
||||
return new BanditsHaul(this);
|
||||
}
|
||||
}
|
||||
63
Mage.Sets/src/mage/cards/b/BaronBertramGraywater.java
Normal file
63
Mage.Sets/src/mage/cards/b/BaronBertramGraywater.java
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldOneOrMoreTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.permanent.TokenPredicate;
|
||||
import mage.game.permanent.token.VampireRogueToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BaronBertramGraywater extends CardImpl {
|
||||
|
||||
static final FilterPermanent filter = new FilterPermanent("tokens");
|
||||
|
||||
static {
|
||||
filter.add(TokenPredicate.TRUE);
|
||||
}
|
||||
|
||||
public BaronBertramGraywater(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.VAMPIRE);
|
||||
this.subtype.add(SubType.NOBLE);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Whenever one or more tokens enter the battlefield under your control, create a 1/1 black Vampire Rogue creature token with lifelink. This ability triggers only once each turn.
|
||||
this.addAbility(new EntersBattlefieldOneOrMoreTriggeredAbility(
|
||||
new CreateTokenEffect(new VampireRogueToken()), filter, TargetController.YOU
|
||||
).setTriggersOnceEachTurn(true));
|
||||
|
||||
// {1}{B}, Sacrifice another creature or artifact: Draw a card.
|
||||
Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{1}{B}"));
|
||||
ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE_OR_ARTIFACT_SHORT_TEXT));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BaronBertramGraywater(final BaronBertramGraywater card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaronBertramGraywater copy() {
|
||||
return new BaronBertramGraywater(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ public final class BasandraBattleSeraph extends CardImpl {
|
|||
class BasandraBattleSeraphEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
public BasandraBattleSeraphEffect() {
|
||||
super(Duration.EndOfTurn, Outcome.Neutral);
|
||||
super(Duration.WhileOnBattlefield, Outcome.Neutral);
|
||||
staticText = "Players can't cast spells during combat";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,10 +99,11 @@ enum BatColonyValue implements DynamicValue {
|
|||
|
||||
/**
|
||||
* Inspired by {@link mage.watchers.common.ManaPaidSourceWatcher}
|
||||
* If more cards like Bat Colony care for mana spent by Caves in the future, best to refactor the tracking there.
|
||||
* If more cards like Bat Colony care for mana produced by Caves in the future, best to refactor the tracking there.
|
||||
* For now the assumption is that it is a 1of, so don't want to track it in any game.
|
||||
*/
|
||||
class BatColonyWatcher extends Watcher {
|
||||
|
||||
private static final class CaveManaPaidTracker implements Serializable, Copyable<CaveManaPaidTracker> {
|
||||
private int caveMana = 0;
|
||||
|
||||
|
|
|
|||
78
Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java
Normal file
78
Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.abilities.common.DiesCreatureTriggeredAbility;
|
||||
import mage.abilities.condition.common.ModeChoiceSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.ChooseModeEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldWithCounterTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
/**
|
||||
* @author Cguy7777
|
||||
*/
|
||||
public final class BattleOfHooverDam extends CardImpl {
|
||||
|
||||
private static final FilterCreatureCard filter = new FilterCreatureCard();
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
|
||||
}
|
||||
|
||||
public BattleOfHooverDam(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
|
||||
|
||||
// As Battle of Hoover Dam enters the battlefield, choose NCR or Legion.
|
||||
this.addAbility(new AsEntersBattlefieldAbility(
|
||||
new ChooseModeEffect("NCR or Legion?", "NCR", "Legion")));
|
||||
|
||||
// * NCR -- At the beginning of your end step, return target creature card with mana value 3 or less
|
||||
// from your graveyard to the battlefield with a finality counter on it.
|
||||
Ability ncrAbility = new ConditionalTriggeredAbility(
|
||||
new BeginningOfEndStepTriggeredAbility(
|
||||
new ReturnFromGraveyardToBattlefieldWithCounterTargetEffect(CounterType.FINALITY.createInstance()),
|
||||
TargetController.YOU,
|
||||
false),
|
||||
new ModeChoiceSourceCondition("NCR"),
|
||||
"&bull NCR — At the beginning of your end step, return target creature card with " +
|
||||
"mana value 3 or less from your graveyard to the battlefield with a finality counter on it.");
|
||||
ncrAbility.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
this.addAbility(ncrAbility);
|
||||
|
||||
// * Legion -- Whenever a creature you control dies, put two +1/+1 counters on target creature you control.
|
||||
Ability legionAbility = new ConditionalTriggeredAbility(
|
||||
new DiesCreatureTriggeredAbility(
|
||||
new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)),
|
||||
false,
|
||||
StaticFilters.FILTER_CONTROLLED_A_CREATURE),
|
||||
new ModeChoiceSourceCondition("Legion"),
|
||||
"&bull Legion — Whenever a creature you control dies, " +
|
||||
"put two +1/+1 counters on target creature you control.");
|
||||
legionAbility.addTarget(new TargetControlledCreaturePermanent());
|
||||
this.addAbility(legionAbility);
|
||||
}
|
||||
|
||||
private BattleOfHooverDam(final BattleOfHooverDam card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BattleOfHooverDam copy() {
|
||||
return new BattleOfHooverDam(this);
|
||||
}
|
||||
}
|
||||
49
Mage.Sets/src/mage/cards/b/BeastbondOutcaster.java
Normal file
49
Mage.Sets/src/mage/cards/b/BeastbondOutcaster.java
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.FerociousCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.hint.common.FerociousHint;
|
||||
import mage.abilities.keyword.PlotAbility;
|
||||
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 BeastbondOutcaster extends CardImpl {
|
||||
|
||||
public BeastbondOutcaster(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
|
||||
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.DRUID);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// When Beastbond Outcaster enters the battlefield, if you control a creature with power 4 or greater, draw a card.
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)),
|
||||
FerociousCondition.instance, "When {this} enters the battlefield, " +
|
||||
"if you control a creature with power 4 or greater, draw a card."
|
||||
).addHint(FerociousHint.instance));
|
||||
|
||||
// Plot {1}{G}
|
||||
this.addAbility(new PlotAbility("{1}{G}"));
|
||||
}
|
||||
|
||||
private BeastbondOutcaster(final BeastbondOutcaster card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeastbondOutcaster copy() {
|
||||
return new BeastbondOutcaster(this);
|
||||
}
|
||||
}
|
||||
112
Mage.Sets/src/mage/cards/b/BehemothOfVault.java
Normal file
112
Mage.Sets/src/mage/cards/b/BehemothOfVault.java
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DiesSourceTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.common.PayEnergyCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetNonlandPermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author notgreat
|
||||
*/
|
||||
public final class BehemothOfVault extends CardImpl {
|
||||
|
||||
public BehemothOfVault(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}");
|
||||
|
||||
this.subtype.add(SubType.ROBOT);
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// When Behemoth of Vault 0 enters the battlefield, you get {E}{E}{E}{E}.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(4)));
|
||||
|
||||
// When Behemoth of Vault 0 dies, you may pay an amount of {E} equal to target nonland permanent's mana value. When you do, destroy that permanent.
|
||||
Ability ability = new DiesSourceTriggeredAbility(new BehemothOfVaultDoWhenCostPaid(
|
||||
new ReflexiveTriggeredAbility(new DestroyTargetEffect().setText("destroy that permanent"), false)));
|
||||
ability.addTarget(new TargetNonlandPermanent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BehemothOfVault(final BehemothOfVault card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehemothOfVault copy() {
|
||||
return new BehemothOfVault(this);
|
||||
}
|
||||
}
|
||||
|
||||
//Based on DoWhenCostPaid but constructs the cost itself and uses a fixed target for the effect
|
||||
class BehemothOfVaultDoWhenCostPaid extends OneShotEffect {
|
||||
|
||||
private final ReflexiveTriggeredAbility ability;
|
||||
|
||||
BehemothOfVaultDoWhenCostPaid(ReflexiveTriggeredAbility ability) {
|
||||
super(Outcome.Benefit);
|
||||
this.ability = ability;
|
||||
this.staticText = "you may pay an amount of {E} equal to target nonland permanent's mana value. When you do, destroy that permanent.";
|
||||
}
|
||||
|
||||
BehemothOfVaultDoWhenCostPaid(final BehemothOfVaultDoWhenCostPaid effect) {
|
||||
super(effect);
|
||||
this.ability = effect.ability.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent targetPermanent = game.getPermanent(source.getFirstTarget());
|
||||
if (targetPermanent == null || player == null) {
|
||||
return false;
|
||||
}
|
||||
Cost cost = new PayEnergyCost(targetPermanent.getManaValue());
|
||||
if (!cost.canPay(source, source, player.getId(), game)
|
||||
|| !player.chooseUse(Outcome.DestroyPermanent, cost.getText(), source, game)) {
|
||||
return true;
|
||||
}
|
||||
cost.clearPaid();
|
||||
int bookmark = game.bookmarkState();
|
||||
if (cost.pay(source, game, source, player.getId(), false)) {
|
||||
ability.getEffects().setTargetPointer(new FixedTarget(targetPermanent, game));
|
||||
game.fireReflexiveTriggeredAbility(ability, source);
|
||||
player.resetStoredBookmark(game);
|
||||
return true;
|
||||
}
|
||||
player.restoreState(bookmark, BehemothOfVaultDoWhenCostPaid.class.getName(), game);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String key, Object value) {
|
||||
super.setValue(key, value);
|
||||
ability.getEffects().setValue(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehemothOfVaultDoWhenCostPaid copy() {
|
||||
return new BehemothOfVaultDoWhenCostPaid(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,27 +2,24 @@ package mage.cards.b;
|
|||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.common.DealtDamageToSourceTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.common.SavedDamageValue;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedEvent;
|
||||
import mage.game.events.DamagedBatchForPermanentsEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.target.common.TargetPlayerOrPlaneswalker;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Merlingilb
|
||||
*/
|
||||
public class BenSolo extends CardImpl {
|
||||
|
||||
public BenSolo(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R/W}{W}");
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
|
|
@ -31,11 +28,14 @@ public class BenSolo extends CardImpl {
|
|||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
//Vigilance
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
//Whenever Ben Solo is dealt damage, it deals that much damage to target player or planeswalker.
|
||||
this.addAbility(new BenSoloTriggeredAbility());
|
||||
// Whenever Ben Solo is dealt damage, it deals that much damage to target player or planeswalker.
|
||||
Ability ability = new DealtDamageToSourceTriggeredAbility(
|
||||
new DamageTargetEffect(SavedDamageValue.MUCH, "it"), false);
|
||||
ability.addTarget(new TargetPlayerOrPlaneswalker());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BenSolo(final BenSolo card) {
|
||||
|
|
@ -47,103 +47,3 @@ public class BenSolo extends CardImpl {
|
|||
return new BenSolo(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BenSoloTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
UUID benSoloID;
|
||||
|
||||
BenSoloTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new BenSoloEffect(), false);
|
||||
this.addTarget(new TargetPlayerOrPlaneswalker());
|
||||
benSoloID = this.getSourceId();
|
||||
}
|
||||
|
||||
private BenSoloTriggeredAbility(final BenSoloTriggeredAbility ability) {
|
||||
super(ability);
|
||||
benSoloID = ability.benSoloID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BenSoloTriggeredAbility copy() {
|
||||
return new BenSoloTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_PERMANENTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (benSoloID == null) {
|
||||
benSoloID = this.getSourceId();
|
||||
if (benSoloID == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int damage = 0;
|
||||
DamagedBatchForPermanentsEvent dEvent = (DamagedBatchForPermanentsEvent) event;
|
||||
Set<DamagedEvent> set = dEvent.getEvents();
|
||||
for (DamagedEvent damagedEvent : set) {
|
||||
UUID targetID = damagedEvent.getTargetId();
|
||||
if (targetID == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (targetID == benSoloID) {
|
||||
damage += damagedEvent.getAmount();
|
||||
}
|
||||
}
|
||||
|
||||
if (damage > 0) {
|
||||
this.getEffects().setValue("damage", damage);
|
||||
this.getEffects().setValue("benSoloID", benSoloID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever Ben Solo is dealt damage, it deals that much damage to target player or planeswalker.";
|
||||
}
|
||||
}
|
||||
|
||||
class BenSoloEffect extends OneShotEffect {
|
||||
|
||||
BenSoloEffect() {
|
||||
super(Outcome.Benefit);
|
||||
}
|
||||
|
||||
private BenSoloEffect(final BenSoloEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BenSoloEffect copy() {
|
||||
return new BenSoloEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Integer damage = (Integer)getValue("damage");
|
||||
UUID benSoloID = (UUID)getValue("benSoloID");
|
||||
|
||||
if (benSoloID == null || damage == null || damage < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.damage(damage, benSoloID, source, game);
|
||||
return true;
|
||||
}
|
||||
Player player = game.getPlayer(source.getFirstTarget());
|
||||
if (player != null) {
|
||||
player.damage(damage, benSoloID, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
84
Mage.Sets/src/mage/cards/b/BetrayalAtTheVault.java
Normal file
84
Mage.Sets/src/mage/cards/b/BetrayalAtTheVault.java
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.other.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BetrayalAtTheVault extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other target creatures");
|
||||
|
||||
static {
|
||||
filter.add(new AnotherTargetPredicate(2));
|
||||
}
|
||||
|
||||
public BetrayalAtTheVault(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{G}{G}");
|
||||
|
||||
// Target creature you control deals damage equal to its power to each of two other target creatures.
|
||||
this.getSpellAbility().addEffect(new BetrayalAtTheVaultEffect());
|
||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(2, 2, filter, false).setTargetTag(2));
|
||||
}
|
||||
|
||||
private BetrayalAtTheVault(final BetrayalAtTheVault card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetrayalAtTheVault copy() {
|
||||
return new BetrayalAtTheVault(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BetrayalAtTheVaultEffect extends OneShotEffect {
|
||||
|
||||
BetrayalAtTheVaultEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Target creature you control deals damage equal to its power "
|
||||
+ "to each of two other target creatures";
|
||||
}
|
||||
|
||||
private BetrayalAtTheVaultEffect(final BetrayalAtTheVaultEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetrayalAtTheVaultEffect copy() {
|
||||
return new BetrayalAtTheVaultEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent creature = game.getPermanent(source.getFirstTarget());
|
||||
if (creature == null) {
|
||||
return false;
|
||||
}
|
||||
source.getTargets()
|
||||
.stream()
|
||||
.filter(t -> t.getTargetTag() == 2)
|
||||
.map(Target::getTargets)
|
||||
.flatMap(List::stream)
|
||||
.map(game::getPermanent)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(p -> p.damage(creature.getPower().getValue(), creature.getId(), source, game));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
106
Mage.Sets/src/mage/cards/b/BiggerOnTheInside.java
Normal file
106
Mage.Sets/src/mage/cards/b/BiggerOnTheInside.java
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
||||
import mage.abilities.effects.common.continuous.NextSpellCastHasAbilityEffect;
|
||||
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
|
||||
import mage.abilities.effects.mana.ManaEffect;
|
||||
import mage.abilities.keyword.CascadeAbility;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.TargetPlayer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author notgreat
|
||||
*/
|
||||
public final class BiggerOnTheInside extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterPermanent("artifact or land");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.ARTIFACT.getPredicate(),
|
||||
CardType.LAND.getPredicate()
|
||||
));
|
||||
}
|
||||
|
||||
public BiggerOnTheInside(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{G}");
|
||||
this.subtype.add(SubType.AURA);
|
||||
|
||||
// Enchant artifact or land
|
||||
TargetPermanent auraTarget = new TargetPermanent(filter);
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility));
|
||||
this.addAbility(new EnchantAbility(auraTarget));
|
||||
|
||||
// Enchanted permanent has "{T}: Target player adds two mana of any one color. The next spell they cast this turn has cascade."
|
||||
Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BiggerOnTheInsideEffect(), new TapSourceCost());
|
||||
gainedAbility.addTarget(new TargetPlayer());
|
||||
Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA, Duration.WhileOnBattlefield, null, "permanent");
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||
}
|
||||
|
||||
private BiggerOnTheInside(final BiggerOnTheInside card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiggerOnTheInside copy() {
|
||||
return new BiggerOnTheInside(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BiggerOnTheInsideEffect extends OneShotEffect { //Not a mana ability since it targets
|
||||
|
||||
BiggerOnTheInsideEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Target player adds two mana of any one color. The next spell they cast this turn has cascade";
|
||||
}
|
||||
|
||||
private BiggerOnTheInsideEffect(final BiggerOnTheInsideEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiggerOnTheInsideEffect copy() {
|
||||
return new BiggerOnTheInsideEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
ContinuousEffect cascadeEffect = new NextSpellCastHasAbilityEffect(new CascadeAbility(), StaticFilters.FILTER_CARD, TargetController.SOURCE_TARGETS);
|
||||
game.addEffect(cascadeEffect, source);
|
||||
|
||||
ManaEffect manaEffect = new AddManaOfAnyColorEffect(2);
|
||||
Mana manaToAdd = manaEffect.produceMana(game, source);
|
||||
if (manaToAdd != null && manaToAdd.count() > 0) {
|
||||
player.getManaPool().addMana(manaToAdd, game, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
57
Mage.Sets/src/mage/cards/b/BighornerRancher.java
Normal file
57
Mage.Sets/src/mage/cards/b/BighornerRancher.java
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue;
|
||||
import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.abilities.mana.DynamicManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author notgreat
|
||||
*/
|
||||
public final class BighornerRancher extends CardImpl {
|
||||
|
||||
public BighornerRancher(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}");
|
||||
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.RANGER);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// {T}: Add an amount of {G} equal to the greatest power among creatures you control.
|
||||
this.addAbility(new DynamicManaAbility(
|
||||
Mana.GreenMana(1), GreatestPowerAmongControlledCreaturesValue.instance, new TapSourceCost(),
|
||||
"Add an amount of {G} equal to the greatest power among creatures you control."
|
||||
));
|
||||
|
||||
// Sacrifice Bighorner Rancher: You gain life equal to the greatest toughness among other creatures you control.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new GainLifeEffect(GreatestToughnessAmongControlledCreaturesValue.instance).setText("You gain life equal to the greatest toughness among other creatures you control."),
|
||||
new SacrificeSourceCost()));
|
||||
}
|
||||
|
||||
private BighornerRancher(final BighornerRancher card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BighornerRancher copy() {
|
||||
return new BighornerRancher(this);
|
||||
}
|
||||
}
|
||||
106
Mage.Sets/src/mage/cards/b/BindingNegotiation.java
Normal file
106
Mage.Sets/src/mage/cards/b/BindingNegotiation.java
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterNonlandCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.card.FaceDownPredicate;
|
||||
import mage.filter.predicate.card.OwnerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.common.TargetOpponent;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BindingNegotiation extends CardImpl {
|
||||
|
||||
public BindingNegotiation(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
|
||||
|
||||
// Target opponent reveals their hand. You may choose a nonland card from it. If you do, they discard it. Otherwise, you may put a face-up exiled card they own into their graveyard.
|
||||
this.getSpellAbility().addEffect(new BindingNegotiationEffect());
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
}
|
||||
|
||||
private BindingNegotiation(final BindingNegotiation card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindingNegotiation copy() {
|
||||
return new BindingNegotiation(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BindingNegotiationEffect extends OneShotEffect {
|
||||
|
||||
BindingNegotiationEffect() {
|
||||
super(Outcome.Discard);
|
||||
staticText = "Target opponent reveals their hand. You may choose a nonland card from it. "
|
||||
+ "If you do, they discard it. Otherwise, you may put a face-up exiled card they own into their graveyard";
|
||||
}
|
||||
|
||||
private BindingNegotiationEffect(final BindingNegotiationEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (player == null || controller == null) {
|
||||
return false;
|
||||
}
|
||||
// Target opponent reveals their hand
|
||||
Cards revealedCards = new CardsImpl();
|
||||
revealedCards.addAll(player.getHand());
|
||||
player.revealCards(source, revealedCards, game);
|
||||
|
||||
// You may choose a nonland card from it.
|
||||
TargetCard target = new TargetCard(0, 1, Zone.HAND, new FilterNonlandCard());
|
||||
controller.choose(outcome, revealedCards, target, source, game);
|
||||
|
||||
UUID chosenId = target.getFirstTarget();
|
||||
if (chosenId != null) {
|
||||
// If you do, they discard it.
|
||||
Card card = revealedCards.get(target.getFirstTarget(), game);
|
||||
player.discard(card, false, source, game);
|
||||
} else {
|
||||
// Otherwise, you may put a face-up exiled card they own into their graveyard.
|
||||
FilterCard filter = new FilterCard("face-up exiled card owned by " + player.getName());
|
||||
filter.add(Predicates.not(FaceDownPredicate.instance));
|
||||
filter.add(new OwnerIdPredicate(player.getId()));
|
||||
TargetCard targetExiled = new TargetCardInExile(0, 1, filter, null);
|
||||
controller.choose(outcome, targetExiled, source, game);
|
||||
Set<Card> chosenExiledCard = targetExiled
|
||||
.getTargets()
|
||||
.stream()
|
||||
.map(game::getCard)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
if (!chosenExiledCard.isEmpty()) {
|
||||
player.moveCards(chosenExiledCard, Zone.GRAVEYARD, source, game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindingNegotiationEffect copy() {
|
||||
return new BindingNegotiationEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
69
Mage.Sets/src/mage/cards/b/BiteDownOnCrime.java
Normal file
69
Mage.Sets/src/mage/cards/b/BiteDownOnCrime.java
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.CollectedEvidenceCondition;
|
||||
import mage.abilities.costs.CostAdjuster;
|
||||
import mage.abilities.costs.OptionalAdditionalCost;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.abilities.keyword.CollectEvidenceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author notgreat
|
||||
*/
|
||||
public final class BiteDownOnCrime extends CardImpl {
|
||||
|
||||
public BiteDownOnCrime(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}");
|
||||
|
||||
// As an additional cost to cast this spell, you may collect evidence 6. This spell costs {2} less to cast if evidence was collected.
|
||||
this.addAbility(new CollectEvidenceAbility(6,"This spell costs {2} less to cast if evidence was collected"));
|
||||
this.getSpellAbility().setCostAdjuster(BiteDownOnCrimeAdjuster.instance);
|
||||
|
||||
// Target creature you control gets +2/+0 until end of turn.
|
||||
Effect effect = new BoostTargetEffect(2, 0, Duration.EndOfTurn);
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
|
||||
|
||||
// It deals damage equal to its power to target creature you don't control.
|
||||
this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("It"));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL));
|
||||
}
|
||||
|
||||
private BiteDownOnCrime(final BiteDownOnCrime card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiteDownOnCrime copy() {
|
||||
return new BiteDownOnCrime(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum BiteDownOnCrimeAdjuster implements CostAdjuster {
|
||||
instance;
|
||||
|
||||
private static final OptionalAdditionalCost collectEvidenceCost = CollectEvidenceAbility.makeCost(6);
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
if (CollectedEvidenceCondition.instance.apply(game, ability)
|
||||
|| (game.inCheckPlayableState() && collectEvidenceCost.canPay(ability, null, ability.getControllerId(), game))) {
|
||||
CardUtil.reduceCost(ability, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
51
Mage.Sets/src/mage/cards/b/BlacksnagBuzzard.java
Normal file
51
Mage.Sets/src/mage/cards/b/BlacksnagBuzzard.java
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.PlotAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BlacksnagBuzzard extends CardImpl {
|
||||
|
||||
public BlacksnagBuzzard(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
|
||||
|
||||
this.subtype.add(SubType.BIRD);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Blacksnag Buzzard enters the battlefield with a +1/+1 counter on it if a creature died this turn.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance()), MorbidCondition.instance, ""
|
||||
), "with a +1/+1 counter on it if a creature died this turn").addHint(MorbidHint.instance));
|
||||
|
||||
// Plot {1}{B}
|
||||
this.addAbility(new PlotAbility("{1}{B}"));
|
||||
}
|
||||
|
||||
private BlacksnagBuzzard(final BlacksnagBuzzard card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlacksnagBuzzard copy() {
|
||||
return new BlacksnagBuzzard(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,12 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster;
|
||||
import mage.target.targetpointer.EachTargetPointer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -29,7 +23,7 @@ public final class BlatantThievery extends CardImpl {
|
|||
this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom, true)
|
||||
.setTargetPointer(new EachTargetPointer())
|
||||
.setText("for each opponent, gain control of target permanent that player controls"));
|
||||
this.getSpellAbility().setTargetAdjuster(BlatantThieveryAdjuster.instance);
|
||||
this.getSpellAbility().setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetPermanent()));
|
||||
}
|
||||
|
||||
private BlatantThievery(final BlatantThievery card) {
|
||||
|
|
@ -41,25 +35,3 @@ public final class BlatantThievery extends CardImpl {
|
|||
return new BlatantThievery(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum BlatantThieveryAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
ability.getTargets().clear();
|
||||
for (UUID opponentId : game.getOpponents(ability.getControllerId())) {
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
if (opponent == null || game.getBattlefield().count(
|
||||
StaticFilters.FILTER_CONTROLLED_PERMANENT,
|
||||
opponentId, ability, game
|
||||
) < 1) {
|
||||
continue;
|
||||
}
|
||||
FilterPermanent filter = new FilterPermanent("Permanent controlled by " + opponent.getName());
|
||||
filter.add(new ControllerIdPredicate(opponentId));
|
||||
TargetPermanent targetPermanent = new TargetPermanent(filter);
|
||||
ability.addTarget(targetPermanent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class BloodHoundTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_BATCH_FOR_ONE_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
53
Mage.Sets/src/mage/cards/b/BloodHustler.java
Normal file
53
Mage.Sets/src/mage/cards/b/BloodHustler.java
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CommittedCrimeTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||
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.target.common.TargetOpponent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BloodHustler extends CardImpl {
|
||||
|
||||
public BloodHustler(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
|
||||
|
||||
this.subtype.add(SubType.VAMPIRE);
|
||||
this.subtype.add(SubType.ROGUE);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Whenever you commit a crime, put a +1/+1 counter on Blood Hustler. This ability triggers only once each turn.
|
||||
this.addAbility(new CommittedCrimeTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance())
|
||||
).setTriggersOnceEachTurn(true));
|
||||
|
||||
// {3}{B}: Target opponent loses 1 life and you gain 1 life.
|
||||
Ability ability = new SimpleActivatedAbility(new LoseLifeTargetEffect(1), new ManaCostsImpl<>("{3}{B}"));
|
||||
ability.addEffect(new GainLifeEffect(1).concatBy("and"));
|
||||
ability.addTarget(new TargetOpponent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BloodHustler(final BloodHustler card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BloodHustler copy() {
|
||||
return new BloodHustler(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -85,9 +85,7 @@ class BloodSpatterAnalysisTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
ZoneChangeBatchEvent zBatchEvent = (ZoneChangeBatchEvent) event;
|
||||
|
||||
for (ZoneChangeEvent zEvent : zBatchEvent.getEvents()) {
|
||||
for (ZoneChangeEvent zEvent : ((ZoneChangeBatchEvent) event).getEvents()) {
|
||||
if (zEvent.isDiesEvent()) {
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(zEvent.getTargetId());
|
||||
if (permanent != null && permanent.isCreature(game)) {
|
||||
|
|
|
|||
104
Mage.Sets/src/mage/cards/b/BoneyardDesecrator.java
Normal file
104
Mage.Sets/src/mage/cards/b/BoneyardDesecrator.java
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.mageobject.OutlawPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.TreasureToken;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BoneyardDesecrator extends CardImpl {
|
||||
|
||||
public BoneyardDesecrator(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
||||
|
||||
this.subtype.add(SubType.ZOMBIE);
|
||||
this.subtype.add(SubType.MERCENARY);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Menace
|
||||
this.addAbility(new MenaceAbility(false));
|
||||
|
||||
// {1}{B}, Sacrifice another creature: Put a +1/+1 counter on Boneyard Desecrator. If an outlaw was sacrificed this way, create a Treasure token.
|
||||
Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance());
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{1}{B}"));
|
||||
ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE));
|
||||
ability.addEffect(new BoneyardDesecratorEffect());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BoneyardDesecrator(final BoneyardDesecrator card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoneyardDesecrator copy() {
|
||||
return new BoneyardDesecrator(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Inspired by Thallid Omnivore
|
||||
class BoneyardDesecratorEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("an outlaw");
|
||||
|
||||
static {
|
||||
filter.add(OutlawPredicate.instance);
|
||||
}
|
||||
|
||||
BoneyardDesecratorEffect() {
|
||||
super(Outcome.GainLife);
|
||||
this.staticText = "If an outlaw was sacrificed this way, create a Treasure token";
|
||||
}
|
||||
|
||||
private BoneyardDesecratorEffect(final BoneyardDesecratorEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoneyardDesecratorEffect copy() {
|
||||
return new BoneyardDesecratorEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (Cost cost : source.getCosts()) {
|
||||
if (cost instanceof SacrificeTargetCost) {
|
||||
SacrificeTargetCost sacrificeCost = (SacrificeTargetCost) cost;
|
||||
List<Permanent> permanents = sacrificeCost.getPermanents();
|
||||
for (Permanent permanent : permanents) {
|
||||
if (!filter.match(permanent, source.getControllerId(), source, game)) {
|
||||
continue;
|
||||
}
|
||||
return new CreateTokenEffect(new TreasureToken()).apply(game, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
55
Mage.Sets/src/mage/cards/b/BonnyPallClearcutter.java
Normal file
55
Mage.Sets/src/mage/cards/b/BonnyPallClearcutter.java
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.PutCardFromHandOrGraveyardOntoBattlefieldEffect;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.permanent.token.BeauToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BonnyPallClearcutter extends CardImpl {
|
||||
|
||||
public BonnyPallClearcutter(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{U}{U}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.GIANT);
|
||||
this.subtype.add(SubType.SCOUT);
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Reach
|
||||
this.addAbility(ReachAbility.getInstance());
|
||||
|
||||
// When Bonny Pall, Clearcutter enters the battlefield, create Beau, a legendary blue Ox creature token with "This creature's power and toughness are each equal to the number of lands you control."
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BeauToken())));
|
||||
|
||||
// Whenever you attack, draw a card, then you may put a land card from your hand or graveyard onto the battlefield.
|
||||
Ability ability = new AttacksWithCreaturesTriggeredAbility(new DrawCardSourceControllerEffect(1), 1);
|
||||
ability.addEffect(new PutCardFromHandOrGraveyardOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A, false).concatBy(", then"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BonnyPallClearcutter(final BonnyPallClearcutter card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BonnyPallClearcutter copy() {
|
||||
return new BonnyPallClearcutter(this);
|
||||
}
|
||||
}
|
||||
50
Mage.Sets/src/mage/cards/b/BoomBox.java
Normal file
50
Mage.Sets/src/mage/cards/b/BoomBox.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.target.common.TargetArtifactPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.common.TargetLandPermanent;
|
||||
import mage.target.targetpointer.EachTargetPointer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BoomBox extends CardImpl {
|
||||
|
||||
public BoomBox(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
// {6}, {T}, Sacrifice Boom Box: Destroy up to one target artifact, up to one target creature, and up to one target land.
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
new DestroyTargetEffect("")
|
||||
.setText("Destroy up to one target artifact, up to one target creature, and up to one target land")
|
||||
.setTargetPointer(new EachTargetPointer()),
|
||||
new GenericManaCost(6)
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
ability.addTarget(new TargetArtifactPermanent(0, 1));
|
||||
ability.addTarget(new TargetCreaturePermanent(0, 1));
|
||||
ability.addTarget(new TargetLandPermanent(0, 1));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BoomBox(final BoomBox card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoomBox copy() {
|
||||
return new BoomBox(this);
|
||||
}
|
||||
}
|
||||
84
Mage.Sets/src/mage/cards/b/BottleCapBlast.java
Normal file
84
Mage.Sets/src/mage/cards/b/BottleCapBlast.java
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.ImproviseAbility;
|
||||
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.game.permanent.token.TreasureToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author notgreat
|
||||
*/
|
||||
public final class BottleCapBlast extends CardImpl {
|
||||
|
||||
public BottleCapBlast(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}");
|
||||
|
||||
|
||||
// Improvise
|
||||
this.addAbility(new ImproviseAbility());
|
||||
|
||||
// Bottle-Cap Blast deals 5 damage to any target. If excess damage was dealt to a permanent this way, create that many tapped Treasure tokens.
|
||||
this.getSpellAbility().addEffect(new BottleCapBlastEffect());
|
||||
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
||||
}
|
||||
|
||||
private BottleCapBlast(final BottleCapBlast card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BottleCapBlast copy() {
|
||||
return new BottleCapBlast(this);
|
||||
}
|
||||
}
|
||||
|
||||
//Based on Hell to Pay
|
||||
class BottleCapBlastEffect extends OneShotEffect {
|
||||
|
||||
BottleCapBlastEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "{this} deals 5 damage to any target. " +
|
||||
"If excess damage was dealt to a permanent this way, create that many tapped Treasure tokens.";
|
||||
}
|
||||
|
||||
private BottleCapBlastEffect(final BottleCapBlastEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BottleCapBlastEffect copy() {
|
||||
return new BottleCapBlastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
UUID target = getTargetPointer().getFirst(game, source);
|
||||
Player player = game.getPlayer(target);
|
||||
if (player != null) {
|
||||
player.damage(5, source, game);
|
||||
return true;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 5);
|
||||
permanent.damage(5, source.getSourceId(), source, game);
|
||||
if (lethal < 5) {
|
||||
new TreasureToken().putOntoBattlefield(
|
||||
5 - lethal, game, source, source.getControllerId(), true, false
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
65
Mage.Sets/src/mage/cards/b/BoundingFelidar.java
Normal file
65
Mage.Sets/src/mage/cards/b/BoundingFelidar.java
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksWhileSaddledTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersAllEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.abilities.keyword.SaddleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BoundingFelidar extends CardImpl {
|
||||
|
||||
private final static FilterPermanent filter = new FilterControlledCreaturePermanent("other creature you control");
|
||||
|
||||
static {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
private final static DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
|
||||
private final static Hint hint = new ValueHint("Other creatures you control", xValue);
|
||||
|
||||
public BoundingFelidar(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}");
|
||||
|
||||
this.subtype.add(SubType.CAT);
|
||||
this.subtype.add(SubType.BEAST);
|
||||
this.subtype.add(SubType.MOUNT);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(7);
|
||||
|
||||
// Whenever Bounding Felidar attacks while saddled, put a +1/+1 counter on each other creature you control. You gain 1 life for each of those creatures.
|
||||
Ability ability = new AttacksWhileSaddledTriggeredAbility(new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter));
|
||||
ability.addEffect(new GainLifeEffect(xValue).setText("You gain 1 life for each of those creatures"));
|
||||
ability.addHint(hint);
|
||||
this.addAbility(ability);
|
||||
|
||||
// Saddle 2
|
||||
this.addAbility(new SaddleAbility(2));
|
||||
}
|
||||
|
||||
private BoundingFelidar(final BoundingFelidar card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoundingFelidar copy() {
|
||||
return new BoundingFelidar(this);
|
||||
}
|
||||
}
|
||||
46
Mage.Sets/src/mage/cards/b/BovineIntervention.java
Normal file
46
Mage.Sets/src/mage/cards/b/BovineIntervention.java
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.effects.common.CreateTokenControllerTargetPermanentEffect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.permanent.token.Ox22Token;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BovineIntervention extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("artifact or creature");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.ARTIFACT.getPredicate(),
|
||||
CardType.CREATURE.getPredicate())
|
||||
);
|
||||
}
|
||||
|
||||
public BovineIntervention(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
|
||||
|
||||
// Destroy target artifact or creature. Its controller creates a 2/2 white Ox creature token.
|
||||
this.getSpellAbility().addTarget(new TargetPermanent(filter));
|
||||
this.getSpellAbility().addEffect(new DestroyTargetEffect());
|
||||
this.getSpellAbility().addEffect(new CreateTokenControllerTargetPermanentEffect(new Ox22Token()));
|
||||
}
|
||||
|
||||
private BovineIntervention(final BovineIntervention card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BovineIntervention copy() {
|
||||
return new BovineIntervention(this);
|
||||
}
|
||||
}
|
||||
111
Mage.Sets/src/mage/cards/b/BreakOut.java
Normal file
111
Mage.Sets/src/mage/cards/b/BreakOut.java
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.PutCards;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author DominionSpy
|
||||
*/
|
||||
public final class BreakOut extends CardImpl {
|
||||
|
||||
public BreakOut(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}{G}");
|
||||
|
||||
// Look at the top six cards of your library. You may reveal a creature card from among them.
|
||||
// If that card has mana value 2 or less, you may put it onto the battlefield and it gains haste until end of turn.
|
||||
// If you didn't put the revealed card onto the battlefield this way, put it into your hand.
|
||||
// Put the rest on the bottom of your library in a random order.
|
||||
this.getSpellAbility().addEffect(new BreakOutEffect());
|
||||
}
|
||||
|
||||
private BreakOut(final BreakOut card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakOut copy() {
|
||||
return new BreakOut(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BreakOutEffect extends OneShotEffect {
|
||||
|
||||
BreakOutEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Look at the top six cards of your library. You may reveal a creature card from among them. " +
|
||||
"If that card has mana value 2 or less, you may put it onto the battlefield and it gains haste until end of turn. " +
|
||||
"If you didn't put the revealed card onto the battlefield this way, put it into your hand. " +
|
||||
"Put the rest on the bottom of your library in a random order.";
|
||||
}
|
||||
|
||||
private BreakOutEffect(final BreakOutEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreakOutEffect copy() {
|
||||
return new BreakOutEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 6));
|
||||
controller.lookAtCards(source, null, cards, game);
|
||||
|
||||
TargetCard target = new TargetCard(0, 1, Zone.LIBRARY, StaticFilters.FILTER_CARD_CREATURE);
|
||||
target.withChooseHint("Reveal a creature card?");
|
||||
if (!controller.chooseTarget(outcome, cards, target, source, game)) {
|
||||
return PutCards.BOTTOM_RANDOM.moveCards(controller, cards, source, game);
|
||||
}
|
||||
|
||||
Card pickedCard = game.getCard(target.getFirstTarget());
|
||||
if (pickedCard != null) {
|
||||
controller.revealCards(source, new CardsImpl(pickedCard), game);
|
||||
cards.remove(pickedCard);
|
||||
|
||||
if (pickedCard.getManaValue() <= 2 &&
|
||||
controller.chooseUse(Outcome.PutCardInPlay, "Put it onto the battlefield?", source, game) &&
|
||||
controller.moveCards(pickedCard, Zone.BATTLEFIELD, source, game)) {
|
||||
Permanent permanent = game.getPermanent(pickedCard.getId());
|
||||
if (permanent != null) {
|
||||
ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn);
|
||||
effect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
} else {
|
||||
controller.moveCards(pickedCard, Zone.HAND, source, game);
|
||||
}
|
||||
}
|
||||
|
||||
PutCards.BOTTOM_RANDOM.moveCards(controller, cards, source, game);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,8 +9,8 @@ import mage.abilities.keyword.PartnerAbility;
|
|||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedEvent;
|
||||
import mage.game.events.DamagedBatchForPlayersEvent;
|
||||
import mage.game.events.DamagedEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
|
@ -72,9 +72,8 @@ class BreechesBrazenPlundererTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
DamagedBatchForPlayersEvent dEvent = (DamagedBatchForPlayersEvent) event;
|
||||
Set<UUID> opponents = new HashSet<>();
|
||||
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
|
||||
for (DamagedEvent damagedEvent : ((DamagedBatchForPlayersEvent) event).getEvents()) {
|
||||
Permanent permanent = game.getPermanent(damagedEvent.getSourceId());
|
||||
if (permanent == null
|
||||
|| !permanent.isControlledBy(getControllerId())
|
||||
|
|
@ -84,7 +83,7 @@ class BreechesBrazenPlundererTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
opponents.add(damagedEvent.getTargetId());
|
||||
}
|
||||
if (opponents.size() < 1) {
|
||||
if (opponents.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().clear();
|
||||
|
|
@ -148,4 +147,4 @@ class BreechesBrazenPlundererEffect extends OneShotEffect {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
103
Mage.Sets/src/mage/cards/b/BreechesTheBlastmaker.java
Normal file
103
Mage.Sets/src/mage/cards/b/BreechesTheBlastmaker.java
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CastSecondSpellTriggeredAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CopyStackObjectEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BreechesTheBlastmaker extends CardImpl {
|
||||
|
||||
public BreechesTheBlastmaker(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.GOBLIN);
|
||||
this.subtype.add(SubType.PIRATE);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Menace
|
||||
this.addAbility(new MenaceAbility(false));
|
||||
|
||||
// Whenever you cast your second spell each turn, you may sacrifice an artifact. If you do, flip a coin. When you win the flip, copy that spell. You may choose new targets for the copy. When you lose the flip, Breeches, the Blastmaker deals damage equal to that spell's mana value to any target.
|
||||
this.addAbility(new CastSecondSpellTriggeredAbility(new DoIfCostPaid(
|
||||
new BreechesTheBlastmakerEffect(), new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_ARTIFACT_AN)
|
||||
)));
|
||||
}
|
||||
|
||||
private BreechesTheBlastmaker(final BreechesTheBlastmaker card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreechesTheBlastmaker copy() {
|
||||
return new BreechesTheBlastmaker(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BreechesTheBlastmakerEffect extends OneShotEffect {
|
||||
|
||||
BreechesTheBlastmakerEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "flip a coin. When you win the flip, copy that spell. You may choose new targets for the copy. " +
|
||||
"When you lose the flip, {this} deals damage equal to that spell's mana value to any target";
|
||||
}
|
||||
|
||||
private BreechesTheBlastmakerEffect(final BreechesTheBlastmakerEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BreechesTheBlastmakerEffect copy() {
|
||||
return new BreechesTheBlastmakerEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Spell spell = (Spell) getValue("spellCast");
|
||||
ReflexiveTriggeredAbility ability;
|
||||
if (player.flipCoin(source, game, true)) {
|
||||
Effect effect = new CopyStackObjectEffect();
|
||||
effect.setText("copy that spell. You may choose new targets for the copy");
|
||||
effect.setValue("stackObject", spell);
|
||||
ability = new ReflexiveTriggeredAbility(effect, false);
|
||||
} else {
|
||||
int mv = Optional
|
||||
.ofNullable(spell)
|
||||
.map(Spell::getManaValue)
|
||||
.orElse(0);
|
||||
ability = new ReflexiveTriggeredAbility(new DamageTargetEffect(mv), false);
|
||||
ability.addTarget(new TargetAnyTarget());
|
||||
}
|
||||
game.fireReflexiveTriggeredAbility(ability, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
47
Mage.Sets/src/mage/cards/b/BridledBighorn.java
Normal file
47
Mage.Sets/src/mage/cards/b/BridledBighorn.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.AttacksWhileSaddledTriggeredAbility;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.keyword.SaddleAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.permanent.token.SheepWhiteToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BridledBighorn extends CardImpl {
|
||||
|
||||
public BridledBighorn(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
|
||||
|
||||
this.subtype.add(SubType.SHEEP);
|
||||
this.subtype.add(SubType.MOUNT);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// Whenever Bridled Bighorn attacks while saddled, create a 1/1 white Sheep creature token.
|
||||
this.addAbility(new AttacksWhileSaddledTriggeredAbility(new CreateTokenEffect(new SheepWhiteToken())));
|
||||
|
||||
// Saddle 2
|
||||
this.addAbility(new SaddleAbility(2));
|
||||
}
|
||||
|
||||
private BridledBighorn(final BridledBighorn card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BridledBighorn copy() {
|
||||
return new BridledBighorn(this);
|
||||
}
|
||||
}
|
||||
36
Mage.Sets/src/mage/cards/b/BrimstoneRoundup.java
Normal file
36
Mage.Sets/src/mage/cards/b/BrimstoneRoundup.java
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.common.CastSecondSpellTriggeredAbility;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.keyword.PlotAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.game.permanent.token.MercenaryToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BrimstoneRoundup extends CardImpl {
|
||||
|
||||
public BrimstoneRoundup(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}");
|
||||
|
||||
// Whenever you cast your second spell each turn, create a 1/1 red Mercenary creature token with "{T}: Target creature you control gets +1/+0 until end of turn. Activate only as a sorcery."
|
||||
this.addAbility(new CastSecondSpellTriggeredAbility(new CreateTokenEffect(new MercenaryToken())));
|
||||
|
||||
// Plot {2}{R}
|
||||
this.addAbility(new PlotAbility("{2}{R}"));
|
||||
}
|
||||
|
||||
private BrimstoneRoundup(final BrimstoneRoundup card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrimstoneRoundup copy() {
|
||||
return new BrimstoneRoundup(this);
|
||||
}
|
||||
}
|
||||
54
Mage.Sets/src/mage/cards/b/BristlebudFarmer.java
Normal file
54
Mage.Sets/src/mage/cards/b/BristlebudFarmer.java
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
import mage.abilities.effects.common.MillThenPutInHandEffect;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.permanent.token.FoodToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BristlebudFarmer extends CardImpl {
|
||||
|
||||
public BristlebudFarmer(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
|
||||
|
||||
this.subtype.add(SubType.PLANT);
|
||||
this.subtype.add(SubType.DRUID);
|
||||
this.power = new MageInt(5);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// When Bristlebud Farmer enters the battlefield, create two Food tokens.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new FoodToken(), 2)));
|
||||
|
||||
// Whenever Bristlebud Farmer attacks, you may sacrifice a Food. If you do, mill three cards. You may put a permanent card from among them into your hand.
|
||||
this.addAbility(new AttacksTriggeredAbility(new DoIfCostPaid(
|
||||
new MillThenPutInHandEffect(3, StaticFilters.FILTER_CARD_A_PERMANENT).withTextOptions("them"),
|
||||
new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_FOOD)
|
||||
)));
|
||||
}
|
||||
|
||||
private BristlebudFarmer(final BristlebudFarmer card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BristlebudFarmer copy() {
|
||||
return new BristlebudFarmer(this);
|
||||
}
|
||||
}
|
||||
47
Mage.Sets/src/mage/cards/b/BristlepackSentry.java
Normal file
47
Mage.Sets/src/mage/cards/b/BristlepackSentry.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.FerociousCondition;
|
||||
import mage.abilities.decorator.ConditionalAsThoughEffect;
|
||||
import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect;
|
||||
import mage.abilities.keyword.DefenderAbility;
|
||||
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 BristlepackSentry extends CardImpl {
|
||||
|
||||
public BristlepackSentry(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
|
||||
|
||||
this.subtype.add(SubType.PLANT);
|
||||
this.subtype.add(SubType.WOLF);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Defender
|
||||
this.addAbility(DefenderAbility.getInstance());
|
||||
|
||||
// As long as you control a creature with power 4 or greater, Bristlepack Sentry can attack as though it didn't have defender.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalAsThoughEffect(
|
||||
new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.WhileOnBattlefield), FerociousCondition.instance
|
||||
).setText("as long as you control a creature with power 4 or greater, {this} can attack as though it didn't have defender")));
|
||||
}
|
||||
|
||||
private BristlepackSentry(final BristlepackSentry card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BristlepackSentry copy() {
|
||||
return new BristlepackSentry(this);
|
||||
}
|
||||
}
|
||||
48
Mage.Sets/src/mage/cards/b/BristlingBackwoods.java
Normal file
48
Mage.Sets/src/mage/cards/b/BristlingBackwoods.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTappedAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.mana.GreenManaAbility;
|
||||
import mage.abilities.mana.RedManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.target.common.TargetOpponent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BristlingBackwoods extends CardImpl {
|
||||
|
||||
public BristlingBackwoods(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||
|
||||
this.subtype.add(SubType.DESERT);
|
||||
|
||||
// Bristling Backwoods enters the battlefield tapped.
|
||||
this.addAbility(new EntersBattlefieldTappedAbility());
|
||||
|
||||
// When Bristling Backwoods enters the battlefield, it deals 1 damage to target opponent.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(1, "it"));
|
||||
ability.addTarget(new TargetOpponent());
|
||||
this.addAbility(ability);
|
||||
|
||||
// {T}: Add {R} or {G}.
|
||||
this.addAbility(new RedManaAbility());
|
||||
this.addAbility(new GreenManaAbility());
|
||||
}
|
||||
|
||||
private BristlingBackwoods(final BristlingBackwoods card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BristlingBackwoods copy() {
|
||||
return new BristlingBackwoods(this);
|
||||
}
|
||||
}
|
||||
54
Mage.Sets/src/mage/cards/b/BristlyBillSpineSower.java
Normal file
54
Mage.Sets/src/mage/cards/b/BristlyBillSpineSower.java
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.LandfallAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.effects.common.counter.DoubleCounterOnEachPermanentEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BristlyBillSpineSower extends CardImpl {
|
||||
|
||||
public BristlyBillSpineSower(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.PLANT);
|
||||
this.subtype.add(SubType.DRUID);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Landfall -- Whenever a land enters the battlefield under your control, put a +1/+1 counter on target creature.
|
||||
Ability ability = new LandfallAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
|
||||
// {3}{G}{G}: Double the number of +1/+1 counters on each creature you control.
|
||||
this.addAbility(new SimpleActivatedAbility(new DoubleCounterOnEachPermanentEffect(
|
||||
CounterType.P1P1, StaticFilters.FILTER_CONTROLLED_CREATURE
|
||||
), new ManaCostsImpl<>("{3}{G}{G}")));
|
||||
}
|
||||
|
||||
private BristlyBillSpineSower(final BristlyBillSpineSower card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BristlyBillSpineSower copy() {
|
||||
return new BristlyBillSpineSower(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
|
|
@ -11,22 +10,22 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.common.TargetNonlandPermanent;
|
||||
import mage.target.targetadjustment.EachOpponentPermanentTargetsAdjuster;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
import mage.target.targetpointer.EachTargetPointer;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jimga150
|
||||
|
|
@ -47,7 +46,7 @@ public final class BronzebeakForagers extends CardImpl {
|
|||
.setTargetPointer(new EachTargetPointer())
|
||||
.setText("for each opponent, exile up to one target nonland permanent that player controls until {this} leaves the battlefield")
|
||||
);
|
||||
etbAbility.setTargetAdjuster(BronzebeakForagerExileAdjuster.instance);
|
||||
etbAbility.setTargetAdjuster(new EachOpponentPermanentTargetsAdjuster(new TargetNonlandPermanent(0, 1)));
|
||||
this.addAbility(etbAbility);
|
||||
|
||||
// {X}{W}: Put target card with mana value X exiled with Bronzebeak Foragers into its owner's graveyard.
|
||||
|
|
@ -72,26 +71,6 @@ public final class BronzebeakForagers extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
enum BronzebeakForagerExileAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
ability.getTargets().clear();
|
||||
for (UUID opponentId : game.getOpponents(ability.getControllerId())) {
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
if (opponent == null) {
|
||||
continue;
|
||||
}
|
||||
FilterPermanent filter = new FilterPermanent("nonland permanent controlled by " + opponent.getLogName());
|
||||
filter.add(new ControllerIdPredicate(opponentId));
|
||||
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
||||
TargetPermanent target = new TargetPermanent(0, 1, filter, false);
|
||||
ability.addTarget(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Based on Gelatinous Cube
|
||||
enum BronzebeakForagerDissolveAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
|
|
|||
48
Mage.Sets/src/mage/cards/b/BrotherhoodVertibird.java
Normal file
48
Mage.Sets/src/mage/cards/b/BrotherhoodVertibird.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
|
||||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.effects.common.continuous.SetBasePowerSourceEffect;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.CrewAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author justinjohnson14
|
||||
*/
|
||||
public final class BrotherhoodVertibird extends CardImpl {
|
||||
public BrotherhoodVertibird(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
this.subtype.add(SubType.VEHICLE);
|
||||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Brotherhood Vertibird's power is equal to the number of artifacts you control.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerSourceEffect(ArtifactYouControlCount.instance)));
|
||||
// Crew 2
|
||||
this.addAbility(new CrewAbility(2));
|
||||
|
||||
}
|
||||
|
||||
private BrotherhoodVertibird(final BrotherhoodVertibird card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrotherhoodVertibird copy() {
|
||||
return new BrotherhoodVertibird(this);
|
||||
}
|
||||
}
|
||||
108
Mage.Sets/src/mage/cards/b/BruseTarlRovingRancher.java
Normal file
108
Mage.Sets/src/mage/cards/b/BruseTarlRovingRancher.java
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||
import mage.abilities.keyword.DoubleStrikeAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.Ox22Token;
|
||||
import mage.players.Library;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BruseTarlRovingRancher extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent(SubType.OX, "Oxen");
|
||||
|
||||
public BruseTarlRovingRancher(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{W}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WARRIOR);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Oxen you control have double strike.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
new GainAbilityControlledEffect(
|
||||
DoubleStrikeAbility.getInstance(),
|
||||
Duration.WhileOnBattlefield, filter
|
||||
)
|
||||
));
|
||||
|
||||
// Whenever Bruse Tarl, Roving Rancher enters the battlefield or attacks, exile the top card of your library. If it's a land card, create a 2/2 white Ox creature token. Otherwise, you may cast it until the end of your next turn.
|
||||
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new BruseTarlRovingRancherEffect()));
|
||||
}
|
||||
|
||||
private BruseTarlRovingRancher(final BruseTarlRovingRancher card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BruseTarlRovingRancher copy() {
|
||||
return new BruseTarlRovingRancher(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BruseTarlRovingRancherEffect extends OneShotEffect {
|
||||
|
||||
BruseTarlRovingRancherEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "exile the top card of your library. "
|
||||
+ "If it's a land card, create a 2/2 white Ox creature token. "
|
||||
+ "Otherwise, you may cast it until the end of your next turn.";
|
||||
}
|
||||
|
||||
private BruseTarlRovingRancherEffect(final BruseTarlRovingRancherEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BruseTarlRovingRancherEffect copy() {
|
||||
return new BruseTarlRovingRancherEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Library library = player.getLibrary();
|
||||
if (library == null || !library.hasCards()) {
|
||||
return false;
|
||||
}
|
||||
Card card = library.getFromTop(game);
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (card.isLand(game)) {
|
||||
player.moveCards(card, Zone.EXILED, source, game);
|
||||
new CreateTokenEffect(new Ox22Token()).apply(game, source);
|
||||
} else {
|
||||
PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(
|
||||
game, source, card, TargetController.YOU,
|
||||
Duration.UntilEndOfYourNextTurn,
|
||||
false, false, true
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
52
Mage.Sets/src/mage/cards/b/BubbleSmuggler.java
Normal file
52
Mage.Sets/src/mage/cards/b/BubbleSmuggler.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.AsTurnedFaceUpEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.keyword.DisguiseAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author notgreat
|
||||
*/
|
||||
public final class BubbleSmuggler extends CardImpl {
|
||||
|
||||
public BubbleSmuggler(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
|
||||
|
||||
this.subtype.add(SubType.OCTOPUS);
|
||||
this.subtype.add(SubType.FISH);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Disguise {5}{U}
|
||||
this.addAbility(new DisguiseAbility(this, new ManaCostsImpl<>("{5}{U}")));
|
||||
|
||||
// As Bubble Smuggler is turned face up, put four +1/+1 counters on it.
|
||||
Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(4));
|
||||
effect.setText("put four +1/+1 counters on it");
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new AsTurnedFaceUpEffect(effect, false));
|
||||
ability.setWorksFaceDown(true);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BubbleSmuggler(final BubbleSmuggler card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BubbleSmuggler copy() {
|
||||
return new BubbleSmuggler(this);
|
||||
}
|
||||
}
|
||||
115
Mage.Sets/src/mage/cards/b/BucolicRanch.java
Normal file
115
Mage.Sets/src/mage/cards/b/BucolicRanch.java
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.abilities.mana.ConditionalAnyColorManaAbility;
|
||||
import mage.abilities.mana.conditional.ConditionalSpellManaBuilder;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class BucolicRanch extends CardImpl {
|
||||
|
||||
private static final FilterSpell filter = new FilterSpell("a Mount spell");
|
||||
|
||||
static {
|
||||
filter.add(SubType.MOUNT.getPredicate());
|
||||
}
|
||||
|
||||
public BucolicRanch(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||
|
||||
this.subtype.add(SubType.DESERT);
|
||||
|
||||
// {T}: Add {C}.
|
||||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
// {T}: Add one mana of any color. Spend this mana only to cast a Mount spell.
|
||||
this.addAbility(new ConditionalAnyColorManaAbility(
|
||||
new TapSourceCost(), 1,
|
||||
new ConditionalSpellManaBuilder(filter), true
|
||||
));
|
||||
|
||||
// {3}, {T}: Look at the top card of your library. If it's a Mount card, you may reveal it and put it into your hand. If you don't put it into your hand, you may put it on the bottom of your library.
|
||||
Ability ability = new SimpleActivatedAbility(new BucolicRanchEffect(), new GenericManaCost(3));
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private BucolicRanch(final BucolicRanch card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BucolicRanch copy() {
|
||||
return new BucolicRanch(this);
|
||||
}
|
||||
}
|
||||
|
||||
class BucolicRanchEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("a Mount card");
|
||||
|
||||
static {
|
||||
filter.add(SubType.MOUNT.getPredicate());
|
||||
}
|
||||
|
||||
BucolicRanchEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "look at the top card of your library. If it's a Mount card, " +
|
||||
"you may reveal it and put it into your hand. If you don't put it " +
|
||||
"into your hand, you may put it on the bottom of your library";
|
||||
}
|
||||
|
||||
private BucolicRanchEffect(final BucolicRanchEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BucolicRanchEffect copy() {
|
||||
return new BucolicRanchEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Card card = player.getLibrary().getFromTop(game);
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
player.lookAtCards("Top card of library", card, game);
|
||||
if (filter.match(card, player.getId(), source, game) && player.chooseUse(
|
||||
outcome, "Put " + card.getName() + " into your hand?", source, game
|
||||
)) {
|
||||
player.revealCards(source, new CardsImpl(card), game);
|
||||
player.moveCards(card, Zone.HAND, source, game);
|
||||
}
|
||||
if (Zone.LIBRARY.equals(game.getState().getZone(card.getId())) && player.chooseUse(
|
||||
outcome, "Put " + card.getName() + " on the bottom of your library?", source, game
|
||||
)) {
|
||||
player.putCardsOnBottomOfLibrary(card, game, source, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
69
Mage.Sets/src/mage/cards/c/Cactarantula.java
Normal file
69
Mage.Sets/src/mage/cards/c/Cactarantula.java
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.BecomesTargetSourceTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
|
||||
import mage.abilities.hint.ConditionHint;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class Cactarantula extends CardImpl {
|
||||
|
||||
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(
|
||||
new FilterPermanent(SubType.DESERT, "you control a Desert")
|
||||
);
|
||||
|
||||
private static final Hint hint = new ConditionHint(condition);
|
||||
|
||||
public Cactarantula(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}");
|
||||
|
||||
this.subtype.add(SubType.PLANT);
|
||||
this.subtype.add(SubType.SPIDER);
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// This spell costs {1} less to cast if you control a Desert.
|
||||
this.addAbility(
|
||||
new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(1, condition))
|
||||
.setRuleAtTheTop(true)
|
||||
.addHint(hint)
|
||||
);
|
||||
|
||||
// Reach
|
||||
this.addAbility(ReachAbility.getInstance());
|
||||
|
||||
// Whenever Cactarantula becomes the target of a spell or ability an opponent controls, you may draw a card.
|
||||
this.addAbility(new BecomesTargetSourceTriggeredAbility(
|
||||
new DrawCardSourceControllerEffect(1),
|
||||
StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS,
|
||||
SetTargetPointer.NONE, true
|
||||
));
|
||||
}
|
||||
|
||||
private Cactarantula(final Cactarantula card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cactarantula copy() {
|
||||
return new Cactarantula(this);
|
||||
}
|
||||
}
|
||||
79
Mage.Sets/src/mage/cards/c/CactusPreserve.java
Normal file
79
Mage.Sets/src/mage/cards/c/CactusPreserve.java
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTappedAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.CommanderGreatestManaValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.abilities.mana.AnyColorLandsProduceManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class CactusPreserve extends CardImpl {
|
||||
|
||||
public CactusPreserve(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||
|
||||
this.subtype.add(SubType.DESERT);
|
||||
|
||||
// Cactus Preserve enters the battlefield tapped.
|
||||
this.addAbility(new EntersBattlefieldTappedAbility());
|
||||
|
||||
// {T}: Add one mana of any type that a land you control could produce.
|
||||
this.addAbility(new AnyColorLandsProduceManaAbility(TargetController.YOU, false));
|
||||
|
||||
// {3}: Until end of turn, Cactus Preserve becomes an X/X green Plant creature with reach, where X is the greatest mana value among your commanders. It's still a land.
|
||||
this.addAbility(new SimpleActivatedAbility(new CactusPreserveEffect(), new ManaCostsImpl<>("{3}")));
|
||||
}
|
||||
|
||||
private CactusPreserve(final CactusPreserve card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CactusPreserve copy() {
|
||||
return new CactusPreserve(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CactusPreserveEffect extends OneShotEffect {
|
||||
|
||||
CactusPreserveEffect() {
|
||||
super(Outcome.BecomeCreature);
|
||||
this.staticText = "Until end of turn, {this} becomes an X/X green Plant creature with reach, "
|
||||
+ "where X is the greatest mana value among your commanders. It's still a land.";
|
||||
}
|
||||
|
||||
private CactusPreserveEffect(final CactusPreserveEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CactusPreserveEffect copy() {
|
||||
return new CactusPreserveEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int xValue = CommanderGreatestManaValue.instance.calculate(game, source, this);
|
||||
game.addEffect(new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(xValue, xValue,
|
||||
"X/X green Plant creature with reach, where X is the greatest mana value among your commanders")
|
||||
.withColor("G").withSubType(SubType.PLANT)
|
||||
.withAbility(ReachAbility.getInstance()),
|
||||
CardType.LAND, Duration.EndOfTurn), source
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
64
Mage.Sets/src/mage/cards/c/CactusfolkSureshot.java
Normal file
64
Mage.Sets/src/mage/cards/c/CactusfolkSureshot.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.abilities.keyword.WardAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.PowerPredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class CactusfolkSureshot extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterCreaturePermanent();
|
||||
|
||||
static {
|
||||
filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3));
|
||||
}
|
||||
|
||||
public CactusfolkSureshot(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}");
|
||||
|
||||
this.subtype.add(SubType.PLANT);
|
||||
this.subtype.add(SubType.MERCENARY);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Reach
|
||||
this.addAbility(ReachAbility.getInstance());
|
||||
|
||||
// Ward {2}
|
||||
this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}")));
|
||||
|
||||
// At the beginning of combat on your turn, other creatures you control with power 4 or greater gain trample and haste until end of turn.
|
||||
Ability ability = new BeginningOfCombatTriggeredAbility(new GainAbilityControlledEffect(
|
||||
TrampleAbility.getInstance(), Duration.EndOfTurn, filter, true
|
||||
).setText("other creatures you control with power 4 or greater gain trample"), TargetController.YOU, false);
|
||||
ability.addEffect(new GainAbilityControlledEffect(
|
||||
HasteAbility.getInstance(), Duration.EndOfTurn, filter, true
|
||||
).setText("and haste until end of turn"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private CactusfolkSureshot(final CactusfolkSureshot card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CactusfolkSureshot copy() {
|
||||
return new CactusfolkSureshot(this);
|
||||
}
|
||||
}
|
||||
109
Mage.Sets/src/mage/cards/c/CalamityGallopingInferno.java
Normal file
109
Mage.Sets/src/mage/cards/c/CalamityGallopingInferno.java
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksWhileSaddledTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.abilities.keyword.SaddleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.permanent.SaddledSourceThisTurnPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class CalamityGallopingInferno extends CardImpl {
|
||||
|
||||
public CalamityGallopingInferno(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HORSE);
|
||||
this.subtype.add(SubType.MOUNT);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
// Haste
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
|
||||
// Whenever Calamity, Galloping Inferno attacks while saddled, choose a nonlegendary creature that saddled it this turn and create a tapped and attacking token that's a copy of it. Sacrifice that token at the beginning of the next end step. Repeat this process once.
|
||||
this.addAbility(new AttacksWhileSaddledTriggeredAbility(new CalamityGallopingInfernoEffect()));
|
||||
|
||||
// Saddle 1
|
||||
this.addAbility(new SaddleAbility(1));
|
||||
}
|
||||
|
||||
private CalamityGallopingInferno(final CalamityGallopingInferno card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalamityGallopingInferno copy() {
|
||||
return new CalamityGallopingInferno(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CalamityGallopingInfernoEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterCreaturePermanent("nonlegendary creature that saddled it this turn");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate()));
|
||||
filter.add(SaddledSourceThisTurnPredicate.instance);
|
||||
}
|
||||
|
||||
CalamityGallopingInfernoEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "choose a nonlegendary creature that saddled it this turn " +
|
||||
"and create a tapped and attacking token that's a copy of it. " +
|
||||
"Sacrifice that token at the beginning of the next end step. Repeat this process once";
|
||||
}
|
||||
|
||||
private CalamityGallopingInfernoEffect(final CalamityGallopingInfernoEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalamityGallopingInfernoEffect copy() {
|
||||
return new CalamityGallopingInfernoEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null || !game.getBattlefield().contains(filter, source, game, 1)) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
TargetPermanent target = new TargetPermanent(filter);
|
||||
target.withNotTarget(true);
|
||||
player.choose(outcome, target, source, game);
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
if (permanent == null) {
|
||||
continue;
|
||||
}
|
||||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(
|
||||
null, null, false, 1, true, true
|
||||
);
|
||||
effect.apply(game, source);
|
||||
effect.sacrificeTokensCreatedAtNextEndStep(game, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
51
Mage.Sets/src/mage/cards/c/CallASurpriseWitness.java
Normal file
51
Mage.Sets/src/mage/cards/c/CallASurpriseWitness.java
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.AddCreatureTypeAdditionEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
|
||||
/**
|
||||
* @author Cguy7777
|
||||
*/
|
||||
public final class CallASurpriseWitness extends CardImpl {
|
||||
|
||||
private static final FilterCreatureCard filter
|
||||
= new FilterCreatureCard("creature card with mana value 3 or less from your graveyard");
|
||||
|
||||
static {
|
||||
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
|
||||
}
|
||||
|
||||
public CallASurpriseWitness(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{W}");
|
||||
|
||||
// Return target creature card with mana value 3 or less from your graveyard to the battlefield.
|
||||
// Put a flying counter on it. It's a Spirit in addition to its other types.
|
||||
this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect());
|
||||
this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.FLYING.createInstance())
|
||||
.setText("put a flying counter on it"));
|
||||
this.getSpellAbility().addEffect(new AddCreatureTypeAdditionEffect(SubType.SPIRIT, false)
|
||||
.setText("it's a Spirit in addition to its other types"));
|
||||
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(filter));
|
||||
}
|
||||
|
||||
private CallASurpriseWitness(final CallASurpriseWitness card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallASurpriseWitness copy() {
|
||||
return new CallASurpriseWitness(this);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue