This commit is contained in:
brodee 2018-11-28 23:01:47 -08:00
commit 4c94938c14
146 changed files with 4424 additions and 1541 deletions

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-root</artifactId> <artifactId>mage-root</artifactId>
<version>1.4.31</version> <version>1.4.32</version>
</parent> </parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>

View file

@ -1,6 +0,0 @@
XMage.de 1 (Europe/Germany) fast :xmage.de:17171
old xmage.de (Europe/Germany) :185.3.232.200:17171
XMage Players MTG:xmageplayersmtg.ddns.net:17171
XMage.tahiti :xmage.tahiti.one:443
Seedds Server (Asia) :115.29.203.80:17171
localhost -> connect to your local server (must be started):localhost:17171

View file

@ -1,4 +1,3 @@
package mage.client.deck.generator; package mage.client.deck.generator;
import java.util.ArrayList; import java.util.ArrayList;
@ -7,6 +6,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.cards.repository.CardCriteria; import mage.cards.repository.CardCriteria;
@ -368,7 +368,6 @@ public final class DeckGenerator {
private static Card getBasicLand(ColoredManaSymbol color, Map<String, List<CardInfo>> basicLands) { private static Card getBasicLand(ColoredManaSymbol color, Map<String, List<CardInfo>> basicLands) {
String landName = DeckGeneratorPool.getBasicLandName(color.toString()); String landName = DeckGeneratorPool.getBasicLandName(color.toString());
List<CardInfo> basicLandsInfo = basicLands.get(landName); List<CardInfo> basicLandsInfo = basicLands.get(landName);
return basicLandsInfo.get(RandomUtil.nextInt(basicLandsInfo.size() - 1)).getMockCard().copy(); return basicLandsInfo.get(RandomUtil.nextInt(basicLandsInfo.size())).getMockCard().copy();
} }
} }

View file

@ -3,15 +3,28 @@ package mage.client.deckeditor;
import mage.util.StreamUtils; import mage.util.StreamUtils;
import java.awt.*; import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.*; import java.awt.event.*;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.Optional;
import javax.swing.*; import javax.swing.*;
public class DeckImportFromClipboardDialog extends JDialog { public class DeckImportFromClipboardDialog extends JDialog {
private static final String FORMAT_TEXT =
"// Example:\n" +
"//1 Library of Congress\n" +
"//1 Cryptic Gateway\n" +
"//1 Azami, Lady of Scrolls\n" +
"// NB: This is slow as, and will lock your screen :)\n" +
"\n" +
"// Your current clipboard:\n";
private JPanel contentPane; private JPanel contentPane;
private JButton buttonOK; private JButton buttonOK;
private JButton buttonCancel; private JButton buttonCancel;
@ -21,6 +34,9 @@ public class DeckImportFromClipboardDialog extends JDialog {
public DeckImportFromClipboardDialog() { public DeckImportFromClipboardDialog() {
initComponents(); initComponents();
onRefreshClipboard();
setContentPane(contentPane); setContentPane(contentPane);
setModal(true); setModal(true);
getRootPane().setDefaultButton(buttonOK); getRootPane().setDefaultButton(buttonOK);
@ -40,6 +56,15 @@ public class DeckImportFromClipboardDialog extends JDialog {
contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
} }
private Optional<String> getClipboardStringData() {
try {
return Optional.of((String)Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor));
} catch (HeadlessException | UnsupportedFlavorException | IOException e) {
//e.printStackTrace();
}
return Optional.empty();
}
private void onOK() { private void onOK() {
BufferedWriter bw = null; BufferedWriter bw = null;
try { try {
@ -60,6 +85,10 @@ public class DeckImportFromClipboardDialog extends JDialog {
dispose(); dispose();
} }
private void onRefreshClipboard() {
txtDeckList.setText(FORMAT_TEXT + getClipboardStringData().orElse(""));
}
public String getTmpPath() { public String getTmpPath() {
return tmpPath; return tmpPath;
} }
@ -143,7 +172,7 @@ public class DeckImportFromClipboardDialog extends JDialog {
txtDeckList.setMinimumSize(new Dimension(250, 400)); txtDeckList.setMinimumSize(new Dimension(250, 400));
txtDeckList.setPreferredSize(new Dimension(550, 400)); txtDeckList.setPreferredSize(new Dimension(550, 400));
txtDeckList.setText("// Example:\n//1 Library of Congress\n//1 Cryptic Gateway\n//1 Azami, Lady of Scrolls\n// NB: This is slow as, and will lock your screen :)"); txtDeckList.setText(FORMAT_TEXT);
JScrollPane txtScrollableDeckList = new JScrollPane(txtDeckList); JScrollPane txtScrollableDeckList = new JScrollPane(txtDeckList);
panel3.add(txtScrollableDeckList, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, panel3.add(txtScrollableDeckList, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, GridBagConstraints.CENTER, GridBagConstraints.BOTH,

View file

@ -340,8 +340,8 @@
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/flags/us.png"/> <Image iconType="3" name="/flags/us.png"/>
</Property> </Property>
<Property name="text" type="java.lang.String" value="W"/> <Property name="text" type="java.lang.String" value="P"/>
<Property name="toolTipText" type="java.lang.String" value="Connect to vaporservermtg.com (USA)"/> <Property name="toolTipText" type="java.lang.String" value="Connect to mtg.powersofwar.com (USA)"/>
<Property name="actionCommand" type="java.lang.String" value="connectXmageus"/> <Property name="actionCommand" type="java.lang.String" value="connectXmageus"/>
<Property name="alignmentY" type="float" value="0.0"/> <Property name="alignmentY" type="float" value="0.0"/>
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor"> <Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">

View file

@ -270,8 +270,8 @@ public class ConnectDialog extends MageDialog {
}); });
btnFind3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N btnFind3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N
btnFind3.setText("W"); btnFind3.setText("P");
btnFind3.setToolTipText("Connect to vaporservermtg.com (USA)"); btnFind3.setToolTipText("Connect to mtg.powersofwar.com (USA)");
btnFind3.setActionCommand("connectXmageus"); btnFind3.setActionCommand("connectXmageus");
btnFind3.setAlignmentY(0.0F); btnFind3.setAlignmentY(0.0F);
btnFind3.setMargin(new java.awt.Insets(2, 2, 2, 2)); btnFind3.setMargin(new java.awt.Insets(2, 2, 2, 2));
@ -688,7 +688,7 @@ public class ConnectDialog extends MageDialog {
}//GEN-LAST:event_btnFind2findPublicServerActionPerformed }//GEN-LAST:event_btnFind2findPublicServerActionPerformed
private void connectXmageus(java.awt.event.ActionEvent evt) { private void connectXmageus(java.awt.event.ActionEvent evt) {
String serverAddress = "vapormtgserver.com"; String serverAddress = "mtg.powersofwar.com";
this.txtServer.setText(serverAddress); this.txtServer.setText(serverAddress);
this.txtPort.setText("17171"); this.txtPort.setText("17171");
// Update userName and password according to the chosen server. // Update userName and password according to the chosen server.

View file

@ -51,6 +51,7 @@ public class NewTableDialog extends MageDialog {
this.spnNumWins.setModel(new SpinnerNumberModel(1, 1, 5, 1)); this.spnNumWins.setModel(new SpinnerNumberModel(1, 1, 5, 1));
this.spnFreeMulligans.setModel(new SpinnerNumberModel(0, 0, 5, 1)); this.spnFreeMulligans.setModel(new SpinnerNumberModel(0, 0, 5, 1));
this.spnQuitRatio.setModel(new SpinnerNumberModel(100, 0, 100, 5)); this.spnQuitRatio.setModel(new SpinnerNumberModel(100, 0, 100, 5));
this.spnMinimumRating.setModel(new SpinnerNumberModel(0, 0, 3000, 10));
this.spnEdhPowerLevel.setModel(new SpinnerNumberModel(100, 0, 100, 5)); this.spnEdhPowerLevel.setModel(new SpinnerNumberModel(100, 0, 100, 5));
MageFrame.getUI().addButton(MageComponents.NEW_TABLE_OK_BUTTON, btnOK); MageFrame.getUI().addButton(MageComponents.NEW_TABLE_OK_BUTTON, btnOK);
} }
@ -102,8 +103,10 @@ public class NewTableDialog extends MageDialog {
btnPreviousConfiguration2 = new javax.swing.JButton(); btnPreviousConfiguration2 = new javax.swing.JButton();
btnCancel = new javax.swing.JButton(); btnCancel = new javax.swing.JButton();
lblQuitRatio = new javax.swing.JLabel(); lblQuitRatio = new javax.swing.JLabel();
lblMinimumRating = new javax.swing.JLabel();
lblEdhPowerLevel = new javax.swing.JLabel(); lblEdhPowerLevel = new javax.swing.JLabel();
spnQuitRatio = new javax.swing.JSpinner(); spnQuitRatio = new javax.swing.JSpinner();
spnMinimumRating = new javax.swing.JSpinner();
spnEdhPowerLevel = new javax.swing.JSpinner(); spnEdhPowerLevel = new javax.swing.JSpinner();
setTitle("New Table"); setTitle("New Table");
@ -186,9 +189,11 @@ public class NewTableDialog extends MageDialog {
btnCancel.addActionListener(evt -> btnCancelActionPerformed(evt)); btnCancel.addActionListener(evt -> btnCancelActionPerformed(evt));
lblQuitRatio.setText("Allowed quit %"); lblQuitRatio.setText("Allowed quit %");
lblMinimumRating.setText("Minimum rating");
lblEdhPowerLevel.setText("EDH power level"); lblEdhPowerLevel.setText("EDH power level");
spnQuitRatio.setToolTipText("Players with quit % more than this value can't join this table"); spnQuitRatio.setToolTipText("Players with quit % more than this value can't join this table");
spnMinimumRating.setToolTipText("Players with rating less than this value can't join this table");
spnEdhPowerLevel.setToolTipText("Players with decks with a higher power level can't join this table"); spnEdhPowerLevel.setToolTipText("Players with decks with a higher power level can't join this table");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
@ -239,9 +244,10 @@ public class NewTableDialog extends MageDialog {
.addComponent(lblQuitRatio) .addComponent(lblQuitRatio)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblEdhPowerLevel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lblMinimumRating)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spnEdhPowerLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addComponent(spnMinimumRating, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
@ -270,7 +276,11 @@ public class NewTableDialog extends MageDialog {
.addGap(18, 18, 18) .addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblNumWins) .addComponent(lblNumWins)
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblEdhPowerLevel)
.addComponent(spnEdhPowerLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addComponent(jSeparator2) .addComponent(jSeparator2)
.addComponent(player1Panel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(player1Panel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
@ -297,14 +307,13 @@ public class NewTableDialog extends MageDialog {
.addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lbDeckType) .addComponent(lbDeckType)
.addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(chkRated)
.addComponent(lblQuitRatio) .addComponent(lblQuitRatio)
.addComponent(chkRated)
.addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblEdhPowerLevel) .addComponent(lblMinimumRating)
.addComponent(chkRated) .addComponent(spnMinimumRating, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(spnEdhPowerLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
@ -326,6 +335,7 @@ public class NewTableDialog extends MageDialog {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblSkillLevel) .addComponent(lblSkillLevel)
.addComponent(lblNumWins) .addComponent(lblNumWins)
.addComponent(lblEdhPowerLevel)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblRange) .addComponent(lblRange)
.addComponent(lblAttack))) .addComponent(lblAttack)))
@ -334,7 +344,8 @@ public class NewTableDialog extends MageDialog {
.addComponent(cbRange, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cbRange, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(cbAttackOption, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cbAttackOption, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(cbSkillLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cbSkillLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(spnEdhPowerLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -394,6 +405,7 @@ public class NewTableDialog extends MageDialog {
options.setFreeMulligans((Integer) this.spnFreeMulligans.getValue()); options.setFreeMulligans((Integer) this.spnFreeMulligans.getValue());
options.setPassword(this.txtPassword.getText()); options.setPassword(this.txtPassword.getText());
options.setQuitRatio((Integer) this.spnQuitRatio.getValue()); options.setQuitRatio((Integer) this.spnQuitRatio.getValue());
options.setMinimumRating((Integer) this.spnMinimumRating.getValue());
options.setEdhPowerLevel((Integer) this.spnEdhPowerLevel.getValue()); options.setEdhPowerLevel((Integer) this.spnEdhPowerLevel.getValue());
String serverAddress = SessionHandler.getSession().getServerHostname().orElseGet(() -> ""); String serverAddress = SessionHandler.getSession().getServerHostname().orElseGet(() -> "");
options.setBannedUsers(IgnoreList.ignoreList(serverAddress)); options.setBannedUsers(IgnoreList.ignoreList(serverAddress));
@ -695,6 +707,7 @@ public class NewTableDialog extends MageDialog {
} }
this.spnQuitRatio.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_QUIT_RATIO, "100"))); this.spnQuitRatio.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_QUIT_RATIO, "100")));
this.spnMinimumRating.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_MINIMUM_RATING + versionStr, "0")));
this.spnEdhPowerLevel.setValue(0); this.spnEdhPowerLevel.setValue(0);
} }
@ -729,6 +742,7 @@ public class NewTableDialog extends MageDialog {
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_SPECTATORS_ALLOWED + versionStr, options.isSpectatorsAllowed() ? "Yes" : "No"); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_SPECTATORS_ALLOWED + versionStr, options.isSpectatorsAllowed() ? "Yes" : "No");
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_PLANECHASE + versionStr, options.isPlaneChase() ? "Yes" : "No"); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_PLANECHASE + versionStr, options.isPlaneChase() ? "Yes" : "No");
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_QUIT_RATIO + versionStr, Integer.toString(options.getQuitRatio())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_QUIT_RATIO + versionStr, Integer.toString(options.getQuitRatio()));
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_MINIMUM_RATING + versionStr, Integer.toString(options.getMinimumRating()));
StringBuilder playerTypesString = new StringBuilder(); StringBuilder playerTypesString = new StringBuilder();
for (Object player : players) { for (Object player : players) {
if (playerTypesString.length() > 0) { if (playerTypesString.length() > 0) {
@ -770,6 +784,7 @@ public class NewTableDialog extends MageDialog {
private javax.swing.JLabel lblNumWins; private javax.swing.JLabel lblNumWins;
private javax.swing.JLabel lblPassword; private javax.swing.JLabel lblPassword;
private javax.swing.JLabel lblQuitRatio; private javax.swing.JLabel lblQuitRatio;
private javax.swing.JLabel lblMinimumRating;
private javax.swing.JLabel lblEdhPowerLevel; private javax.swing.JLabel lblEdhPowerLevel;
private javax.swing.JLabel lblRange; private javax.swing.JLabel lblRange;
private javax.swing.JLabel lblSkillLevel; private javax.swing.JLabel lblSkillLevel;
@ -779,6 +794,7 @@ public class NewTableDialog extends MageDialog {
private javax.swing.JSpinner spnNumPlayers; private javax.swing.JSpinner spnNumPlayers;
private javax.swing.JSpinner spnNumWins; private javax.swing.JSpinner spnNumWins;
private javax.swing.JSpinner spnQuitRatio; private javax.swing.JSpinner spnQuitRatio;
private javax.swing.JSpinner spnMinimumRating;
private javax.swing.JSpinner spnEdhPowerLevel; private javax.swing.JSpinner spnEdhPowerLevel;
private javax.swing.JTextField txtName; private javax.swing.JTextField txtName;
private javax.swing.JTextField txtPassword; private javax.swing.JTextField txtPassword;

View file

@ -75,6 +75,7 @@ public class NewTournamentDialog extends MageDialog {
this.spnConstructTime.setModel(new SpinnerNumberModel(10, CONSTRUCTION_TIME_MIN, CONSTRUCTION_TIME_MAX, 2)); this.spnConstructTime.setModel(new SpinnerNumberModel(10, CONSTRUCTION_TIME_MIN, CONSTRUCTION_TIME_MAX, 2));
this.spnNumRounds.setModel(new SpinnerNumberModel(2, 2, 10, 1)); this.spnNumRounds.setModel(new SpinnerNumberModel(2, 2, 10, 1));
this.spnQuitRatio.setModel(new SpinnerNumberModel(100, 0, 100, 5)); this.spnQuitRatio.setModel(new SpinnerNumberModel(100, 0, 100, 5));
this.spnMinimumRating.setModel(new SpinnerNumberModel(0, 0, 3000, 10));
} }
public void showDialog(UUID roomId) { public void showDialog(UUID roomId) {
@ -165,6 +166,8 @@ public class NewTournamentDialog extends MageDialog {
pnlRandomPacks = new javax.swing.JPanel(); pnlRandomPacks = new javax.swing.JPanel();
lblQuitRatio = new javax.swing.JLabel(); lblQuitRatio = new javax.swing.JLabel();
spnQuitRatio = new javax.swing.JSpinner(); spnQuitRatio = new javax.swing.JSpinner();
lblMinimumRating = new javax.swing.JLabel();
spnMinimumRating = new javax.swing.JSpinner();
setTitle("New Tournament"); setTitle("New Tournament");
@ -315,8 +318,10 @@ public class NewTournamentDialog extends MageDialog {
pnlRandomPacks.setLayout(new javax.swing.BoxLayout(pnlRandomPacks, javax.swing.BoxLayout.Y_AXIS)); pnlRandomPacks.setLayout(new javax.swing.BoxLayout(pnlRandomPacks, javax.swing.BoxLayout.Y_AXIS));
lblQuitRatio.setText("Allowed quit %:"); lblQuitRatio.setText("Allowed quit %:");
lblMinimumRating.setText("Minimum rating:");
spnQuitRatio.setToolTipText("Players with quit % more than this value can't join this table"); spnQuitRatio.setToolTipText("Players with quit % more than this value can't join this table");
spnMinimumRating.setToolTipText("Players with rating less than this value can't join this table");
spnNumSeats.setToolTipText("The number of seats for each duel. If more than 2, will set number of wins to 1"); spnNumSeats.setToolTipText("The number of seats for each duel. If more than 2, will set number of wins to 1");
spnNumPlayers.setToolTipText("The total number of players who will draft"); spnNumPlayers.setToolTipText("The total number of players who will draft");
@ -386,11 +391,15 @@ public class NewTournamentDialog extends MageDialog {
.addComponent(lblNumWins) .addComponent(lblNumWins)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lblQuitRatio) .addComponent(lblQuitRatio)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lblMinimumRating)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spnMinimumRating, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(chkRated)) .addComponent(chkRated))
.addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
@ -444,6 +453,8 @@ public class NewTournamentDialog extends MageDialog {
.addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblQuitRatio) .addComponent(lblQuitRatio)
.addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblMinimumRating)
.addComponent(spnMinimumRating, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(chkRated)) .addComponent(chkRated))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
@ -522,6 +533,7 @@ public class NewTournamentDialog extends MageDialog {
tOptions.setWatchingAllowed(cbAllowSpectators.isSelected()); tOptions.setWatchingAllowed(cbAllowSpectators.isSelected());
tOptions.setPlaneChase(cbPlaneChase.isSelected()); tOptions.setPlaneChase(cbPlaneChase.isSelected());
tOptions.setQuitRatio((Integer) spnQuitRatio.getValue()); tOptions.setQuitRatio((Integer) spnQuitRatio.getValue());
tOptions.setMinimumRating((Integer) spnMinimumRating.getValue());
for (TournamentPlayerPanel player : players) { for (TournamentPlayerPanel player : players) {
tOptions.getPlayerTypes().add((PlayerType) player.getPlayerType().getSelectedItem()); tOptions.getPlayerTypes().add((PlayerType) player.getPlayerType().getSelectedItem());
} }
@ -1065,6 +1077,7 @@ public class NewTournamentDialog extends MageDialog {
this.spnFreeMulligans.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS + versionStr, "0"))); this.spnFreeMulligans.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS + versionStr, "0")));
this.spnNumWins.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_WINS + versionStr, "2"))); this.spnNumWins.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_WINS + versionStr, "2")));
this.spnQuitRatio.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_QUIT_RATIO + versionStr, "100"))); this.spnQuitRatio.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_QUIT_RATIO + versionStr, "100")));
this.spnMinimumRating.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_MINIMUM_RATING + versionStr, "0")));
TournamentTypeView tournamentType = (TournamentTypeView) cbTournamentType.getSelectedItem(); TournamentTypeView tournamentType = (TournamentTypeView) cbTournamentType.getSelectedItem();
activatePanelElements(tournamentType); activatePanelElements(tournamentType);
@ -1150,6 +1163,7 @@ public class NewTournamentDialog extends MageDialog {
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS + versionStr, Integer.toString(tOptions.getMatchOptions().getFreeMulligans())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS + versionStr, Integer.toString(tOptions.getMatchOptions().getFreeMulligans()));
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_WINS + versionStr, Integer.toString(tOptions.getMatchOptions().getWinsNeeded())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_WINS + versionStr, Integer.toString(tOptions.getMatchOptions().getWinsNeeded()));
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_QUIT_RATIO + versionStr, Integer.toString(tOptions.getQuitRatio())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_QUIT_RATIO + versionStr, Integer.toString(tOptions.getQuitRatio()));
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_MINIMUM_RATING + versionStr, Integer.toString(tOptions.getMinimumRating()));
if (tOptions.getTournamentType().startsWith("Sealed")) { if (tOptions.getTournamentType().startsWith("Sealed")) {
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_SEALED + versionStr, tOptions.getLimitedOptions().getSetCodes().toString()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_SEALED + versionStr, tOptions.getLimitedOptions().getSetCodes().toString());
@ -1221,6 +1235,7 @@ public class NewTournamentDialog extends MageDialog {
private javax.swing.JLabel lblPassword; private javax.swing.JLabel lblPassword;
private javax.swing.JLabel lblPlayer1; private javax.swing.JLabel lblPlayer1;
private javax.swing.JLabel lblQuitRatio; private javax.swing.JLabel lblQuitRatio;
private javax.swing.JLabel lblMinimumRating;
private javax.swing.JLabel lblTournamentType; private javax.swing.JLabel lblTournamentType;
private mage.client.table.NewPlayerPanel player1Panel; private mage.client.table.NewPlayerPanel player1Panel;
private javax.swing.JPanel pnlDraftOptions; private javax.swing.JPanel pnlDraftOptions;
@ -1235,6 +1250,7 @@ public class NewTournamentDialog extends MageDialog {
private javax.swing.JSpinner spnNumRounds; private javax.swing.JSpinner spnNumRounds;
private javax.swing.JSpinner spnNumWins; private javax.swing.JSpinner spnNumWins;
private javax.swing.JSpinner spnQuitRatio; private javax.swing.JSpinner spnQuitRatio;
private javax.swing.JSpinner spnMinimumRating;
private javax.swing.JTextField txtName; private javax.swing.JTextField txtName;
private javax.swing.JTextField txtPassword; private javax.swing.JTextField txtPassword;
private org.jdesktop.beansbinding.BindingGroup bindingGroup; private org.jdesktop.beansbinding.BindingGroup bindingGroup;

View file

@ -222,6 +222,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
public static final String KEY_NEW_TABLE_NUMBER_PLAYERS = "newTableNumberPlayers"; public static final String KEY_NEW_TABLE_NUMBER_PLAYERS = "newTableNumberPlayers";
public static final String KEY_NEW_TABLE_PLAYER_TYPES = "newTablePlayerTypes"; public static final String KEY_NEW_TABLE_PLAYER_TYPES = "newTablePlayerTypes";
public static final String KEY_NEW_TABLE_QUIT_RATIO = "newTableQuitRatio"; public static final String KEY_NEW_TABLE_QUIT_RATIO = "newTableQuitRatio";
public static final String KEY_NEW_TABLE_MINIMUM_RATING = "newTableMinimumRating";
public static final String KEY_NEW_TABLE_RATED = "newTableRated"; public static final String KEY_NEW_TABLE_RATED = "newTableRated";
// pref setting for new tournament dialog // pref setting for new tournament dialog
@ -243,6 +244,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
public static final String KEY_NEW_TOURNAMENT_ALLOW_ROLLBACKS = "newTournamentAllowRollbacks"; public static final String KEY_NEW_TOURNAMENT_ALLOW_ROLLBACKS = "newTournamentAllowRollbacks";
public static final String KEY_NEW_TOURNAMENT_DECK_FILE = "newTournamentDeckFile"; public static final String KEY_NEW_TOURNAMENT_DECK_FILE = "newTournamentDeckFile";
public static final String KEY_NEW_TOURNAMENT_QUIT_RATIO = "newTournamentQuitRatio"; public static final String KEY_NEW_TOURNAMENT_QUIT_RATIO = "newTournamentQuitRatio";
public static final String KEY_NEW_TOURNAMENT_MINIMUM_RATING = "newTournamentMinimumRating";
public static final String KEY_NEW_TOURNAMENT_RATED = "newTournamentRated"; public static final String KEY_NEW_TOURNAMENT_RATED = "newTournamentRated";
// pref setting for deck generator // pref setting for deck generator

View file

@ -26,6 +26,8 @@ import mage.view.CardView;
import mage.view.PermanentView; import mage.view.PermanentView;
import net.xeoh.plugins.base.PluginManager; import net.xeoh.plugins.base.PluginManager;
import net.xeoh.plugins.base.impl.PluginManagerFactory; import net.xeoh.plugins.base.impl.PluginManagerFactory;
import net.xeoh.plugins.base.util.uri.ClassURI;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.plugins.card.CardPluginImpl; import org.mage.plugins.card.CardPluginImpl;
import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir;
@ -46,13 +48,15 @@ public enum Plugins implements MagePlugins {
@Override @Override
public void loadPlugins() { public void loadPlugins() {
LOGGER.info("Loading plugins..."); LOGGER.info("Loading plugins...");
pm = PluginManagerFactory.createPluginManager(); pm = PluginManagerFactory.createPluginManager();
pm.addPluginsFrom(new File(PLUGINS_DIRECTORY + File.separator).toURI()); pm.addPluginsFrom(new File(PLUGINS_DIRECTORY + File.separator).toURI());
this.cardPlugin = new CardPluginImpl(); pm.addPluginsFrom(new ClassURI(CardPluginImpl.class).toURI());
pm.addPluginsFrom(new ClassURI(ThemePluginImpl.class).toURI());
this.cardPlugin = pm.getPlugin(CardPlugin.class);
this.counterPlugin = pm.getPlugin(CounterPlugin.class); this.counterPlugin = pm.getPlugin(CounterPlugin.class);
this.themePlugin = new ThemePluginImpl(); this.themePlugin = pm.getPlugin(ThemePlugin.class);
LOGGER.info("Done."); LOGGER.info("Done.");
} }

View file

@ -1,66 +1,58 @@
/* /*
* TablesPanel.java * TablesPanel.java
* *
* Created on 15-Dec-2009, 10:54:01 PM * Created on 15-Dec-2009, 10:54:01 PM
*/ */
package mage.client.table; package mage.client.table;
import java.awt.*; import mage.cards.decks.importer.DeckImporterUtil;
import java.awt.event.ActionEvent; import mage.client.MageFrame;
import java.awt.event.MouseAdapter; import mage.client.SessionHandler;
import java.awt.event.MouseEvent; import mage.client.chat.ChatPanelBasic;
import java.beans.PropertyVetoException; import mage.client.components.MageComponents;
import java.io.File; import mage.client.dialog.*;
import java.text.DateFormat; import mage.client.util.*;
import java.text.SimpleDateFormat; import mage.client.util.gui.GuiDisplayUtil;
import java.util.*; import mage.client.util.gui.TableUtil;
import java.util.concurrent.CancellationException; import mage.constants.*;
import java.util.concurrent.ExecutionException; import mage.game.match.MatchOptions;
import java.util.concurrent.Executors; import mage.players.PlayerType;
import java.util.concurrent.TimeUnit; import mage.remote.MageRemoteException;
import javax.swing.*; import mage.view.MatchView;
import javax.swing.table.AbstractTableModel; import mage.view.RoomUsersView;
import javax.swing.table.DefaultTableCellRenderer; import mage.view.TableView;
import javax.swing.table.TableCellRenderer; import mage.view.UserRequestMessage;
import mage.cards.decks.importer.DeckImporterUtil; import org.apache.log4j.Logger;
import mage.client.MageFrame; import org.mage.card.arcane.CardRendererUtils;
import mage.client.SessionHandler; import org.ocpsoft.prettytime.Duration;
import mage.client.chat.ChatPanelBasic; import org.ocpsoft.prettytime.PrettyTime;
import mage.client.components.MageComponents; import org.ocpsoft.prettytime.units.JustNow;
import mage.client.dialog.*;
import static mage.client.dialog.PreferencesDialog.KEY_TABLES_COLUMNS_ORDER;
import static mage.client.dialog.PreferencesDialog.KEY_TABLES_COLUMNS_WIDTH;
import static mage.client.dialog.PreferencesDialog.KEY_TABLES_FILTER_SETTINGS;
import static mage.client.dialog.PreferencesDialog.KEY_TABLES_DIVIDER_LOCATION_1;
import static mage.client.dialog.PreferencesDialog.KEY_TABLES_DIVIDER_LOCATION_2;
import static mage.client.dialog.PreferencesDialog.KEY_TABLES_DIVIDER_LOCATION_3;
import mage.client.util.ButtonColumn;
import mage.client.util.GUISizeHelper;
import mage.client.util.IgnoreList;
import mage.client.util.MageTableRowSorter;
import mage.client.util.URLHandler;
import mage.client.util.gui.GuiDisplayUtil;
import mage.client.util.gui.TableUtil;
import mage.constants.*;
import mage.game.match.MatchOptions;
import mage.players.PlayerType;
import mage.remote.MageRemoteException;
import mage.view.MatchView;
import mage.view.RoomUsersView;
import mage.view.TableView;
import mage.view.UserRequestMessage;
import org.apache.log4j.Logger;
import org.ocpsoft.prettytime.Duration;
import org.ocpsoft.prettytime.PrettyTime;
import org.ocpsoft.prettytime.units.JustNow;
/** import javax.swing.*;
* import javax.swing.border.EmptyBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyVetoException;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static mage.client.dialog.PreferencesDialog.*;
/**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class TablesPanel extends javax.swing.JPanel { public class TablesPanel extends javax.swing.JPanel {
private static final Logger LOGGER = Logger.getLogger(TablesPanel.class); private static final Logger LOGGER = Logger.getLogger(TablesPanel.class);
private static final int[] DEFAULT_COLUMNS_WIDTH = {35, 150, 120, 180, 80, 120, 80, 60, 40, 40, 60}; private static final int[] DEFAULT_COLUMNS_WIDTH = {35, 150, 120, 180, 80, 120, 80, 60, 40, 40, 60};
@ -134,6 +126,41 @@ public class TablesPanel extends javax.swing.JPanel {
} }
}; };
// skill renderer
TableCellRenderer skillCellRenderer = new DefaultTableCellRenderer() {
// base panel to render
private JPanel renderPanel = new JPanel();
private ImageIcon skillIcon = new ImageIcon(this.getClass().getResource("/info/yellow_star_16.png"));
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
// get table text cell settings
DefaultTableCellRenderer baseRenderer = (DefaultTableCellRenderer) table.getDefaultRenderer(String.class);
JLabel baseComp = (JLabel) baseRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
String skillCode = baseComp.getText();
// apply settings to render panel from parent
renderPanel.setOpaque(baseComp.isOpaque());
renderPanel.setForeground(CardRendererUtils.copyColor(baseComp.getForeground()));
renderPanel.setBackground(CardRendererUtils.copyColor(baseComp.getBackground()));
renderPanel.setBorder(baseComp.getBorder());
// create each skill symbol as child label
renderPanel.removeAll();
renderPanel.setLayout(new BoxLayout(renderPanel, BoxLayout.X_AXIS));
for (char skillSymbol : skillCode.toCharArray()) {
JLabel symbolLabel = new JLabel();
symbolLabel.setBorder(new EmptyBorder(0, 3, 0, 0));
symbolLabel.setIcon(skillIcon);
renderPanel.add(symbolLabel);
}
return renderPanel;
}
};
/** /**
* Creates new form TablesPanel * Creates new form TablesPanel
*/ */
@ -158,6 +185,9 @@ public class TablesPanel extends javax.swing.JPanel {
// time ago // time ago
tableTables.getColumnModel().getColumn(TableTableModel.COLUMN_CREATED).setCellRenderer(timeAgoCellRenderer); tableTables.getColumnModel().getColumn(TableTableModel.COLUMN_CREATED).setCellRenderer(timeAgoCellRenderer);
// skill level
tableTables.getColumnModel().getColumn(TableTableModel.COLUMN_SKILL).setCellRenderer(skillCellRenderer);
/* date sorter (not need, default is good - see getColumnClass) /* date sorter (not need, default is good - see getColumnClass)
activeTablesSorter.setComparator(TableTableModel.COLUMN_CREATED, new Comparator<Date>() { activeTablesSorter.setComparator(TableTableModel.COLUMN_CREATED, new Comparator<Date>() {
@Override @Override
@ -166,6 +196,7 @@ public class TablesPanel extends javax.swing.JPanel {
} }
});*/ });*/
// default sort by created date (last games from above) // default sort by created date (last games from above)
ArrayList list = new ArrayList(); ArrayList list = new ArrayList();
list.add(new RowSorter.SortKey(TableTableModel.COLUMN_CREATED, SortOrder.DESCENDING)); list.add(new RowSorter.SortKey(TableTableModel.COLUMN_CREATED, SortOrder.DESCENDING));
@ -326,9 +357,14 @@ public class TablesPanel extends javax.swing.JPanel {
table.addMouseListener(new MouseAdapter() { table.addMouseListener(new MouseAdapter() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
int row = table.convertRowIndexToModel(table.getSelectedRow()); if (e.getClickCount() == 2) {
if (e.getClickCount() == 2 && row != -1) { int selRow = table.getSelectedRow();
action.actionPerformed(new ActionEvent(e.getSource(), e.getID(), "" + row)); if (selRow != -1) {
int dataRow = table.convertRowIndexToModel(selRow);
if (dataRow != -1) {
action.actionPerformed(new ActionEvent(e.getSource(), e.getID(), "" + dataRow));
}
}
} }
} }
}); });
@ -620,15 +656,16 @@ public class TablesPanel extends javax.swing.JPanel {
formatFilterList.add(RowFilter.regexFilter("^Momir Basic|^Constructed - Pauper|^Constructed - Frontier|^Constructed - Extended|^Constructed - Eternal|^Constructed - Historical|^Constructed - Super|^Constructed - Freeform|^Australian Highlander|^Canadian Highlander|^Constructed - Old", TableTableModel.COLUMN_DECK_TYPE)); formatFilterList.add(RowFilter.regexFilter("^Momir Basic|^Constructed - Pauper|^Constructed - Frontier|^Constructed - Extended|^Constructed - Eternal|^Constructed - Historical|^Constructed - Super|^Constructed - Freeform|^Australian Highlander|^Canadian Highlander|^Constructed - Old", TableTableModel.COLUMN_DECK_TYPE));
} }
// skill
java.util.List<RowFilter<Object, Object>> skillFilterList = new ArrayList<>(); java.util.List<RowFilter<Object, Object>> skillFilterList = new ArrayList<>();
if (btnSkillBeginner.isSelected()) { if (btnSkillBeginner.isSelected()) {
skillFilterList.add(RowFilter.regexFilter(SkillLevel.BEGINNER.toString(), TableTableModel.COLUMN_SKILL)); skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.BEGINNER, true), TableTableModel.COLUMN_SKILL));
} }
if (btnSkillCasual.isSelected()) { if (btnSkillCasual.isSelected()) {
skillFilterList.add(RowFilter.regexFilter(SkillLevel.CASUAL.toString(), TableTableModel.COLUMN_SKILL)); skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.CASUAL, true), TableTableModel.COLUMN_SKILL));
} }
if (btnSkillSerious.isSelected()) { if (btnSkillSerious.isSelected()) {
skillFilterList.add(RowFilter.regexFilter(SkillLevel.SERIOUS.toString(), TableTableModel.COLUMN_SKILL)); skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.SERIOUS, true), TableTableModel.COLUMN_SKILL));
} }
String ratedMark = TableTableModel.RATED_VALUE_YES; String ratedMark = TableTableModel.RATED_VALUE_YES;
@ -1221,6 +1258,7 @@ public class TablesPanel extends javax.swing.JPanel {
options.setSkillLevel(SkillLevel.CASUAL); options.setSkillLevel(SkillLevel.CASUAL);
options.setRollbackTurnsAllowed(true); options.setRollbackTurnsAllowed(true);
options.setQuitRatio(100); options.setQuitRatio(100);
options.setMinimumRating(0);
String serverAddress = SessionHandler.getSession().getServerHostname().orElseGet(() -> ""); String serverAddress = SessionHandler.getSession().getServerHostname().orElseGet(() -> "");
options.setBannedUsers(IgnoreList.ignoreList(serverAddress)); options.setBannedUsers(IgnoreList.ignoreList(serverAddress));
table = SessionHandler.createTable(roomId, options); table = SessionHandler.createTable(roomId, options);
@ -1335,14 +1373,15 @@ class TableTableModel extends AbstractTableModel {
public static final int COLUMN_SKILL = 8; public static final int COLUMN_SKILL = 8;
public static final int COLUMN_RATING = 9; public static final int COLUMN_RATING = 9;
public static final int COLUMN_QUIT_RATIO = 10; public static final int COLUMN_QUIT_RATIO = 10;
public static final int ACTION_COLUMN = 11; // column the action is located (starting with 0) public static final int COLUMN_MINIMUM_RATING = 11;
public static final int ACTION_COLUMN = 12; // column the action is located (starting with 0)
public static final String RATED_VALUE_YES = "YES"; public static final String RATED_VALUE_YES = "YES";
public static final String RATED_VALUE_NO = ""; public static final String RATED_VALUE_NO = "";
public static final String PASSWORD_VALUE_YES = "YES"; public static final String PASSWORD_VALUE_YES = "YES";
private final String[] columnNames = new String[]{"M/T", "Deck Type", "Owner / Players", "Game Type", "Info", "Status", "Password", "Created / Started", "Skill Level", "Rating", "Quit %", "Action"}; private final String[] columnNames = new String[]{"M/T", "Deck Type", "Owner / Players", "Game Type", "Info", "Status", "Password", "Created / Started", "Skill Level", "Rated", "Quit %", "Min Rating", "Action"};
private TableView[] tables = new TableView[0]; private TableView[] tables = new TableView[0];
@ -1354,6 +1393,31 @@ class TableTableModel extends AbstractTableModel {
this.fireTableDataChanged(); this.fireTableDataChanged();
} }
public String getSkillLevelAsCode(SkillLevel skill, boolean asRegExp) {
String res;
switch (skill) {
case BEGINNER:
res = "*";
break;
case CASUAL:
res = "**";
break;
case SERIOUS:
res = "***";
break;
default:
res = "";
break;
}
// regexp format for search table rows
if (asRegExp) {
res = String.format("^%s$", res.replace("*", "\\*"));
}
return res;
}
@Override @Override
public int getRowCount() { public int getRowCount() {
return tables.length; return tables.length;
@ -1384,12 +1448,14 @@ class TableTableModel extends AbstractTableModel {
case 7: case 7:
return tables[arg0].getCreateTime(); // use cell render, not format here return tables[arg0].getCreateTime(); // use cell render, not format here
case 8: case 8:
return tables[arg0].getSkillLevel(); return this.getSkillLevelAsCode(tables[arg0].getSkillLevel(), false);
case 9: case 9:
return tables[arg0].isRated() ? RATED_VALUE_YES : RATED_VALUE_NO; return tables[arg0].isRated() ? RATED_VALUE_YES : RATED_VALUE_NO;
case 10: case 10:
return tables[arg0].getQuitRatio(); return tables[arg0].getQuitRatio();
case 11: case 11:
return tables[arg0].getMinimumRating();
case 12:
switch (tables[arg0].getTableState()) { switch (tables[arg0].getTableState()) {
case WAITING: case WAITING:
@ -1419,14 +1485,14 @@ class TableTableModel extends AbstractTableModel {
default: default:
return ""; return "";
} }
case 12:
return tables[arg0].isTournament();
case 13: case 13:
return tables[arg0].isTournament();
case 14:
if (!tables[arg0].getGames().isEmpty()) { if (!tables[arg0].getGames().isEmpty()) {
return tables[arg0].getGames().get(0); return tables[arg0].getGames().get(0);
} }
return null; return null;
case 14: case 15:
return tables[arg0].getTableId(); return tables[arg0].getTableId();
} }
return ""; return "";

View file

@ -1,8 +1,3 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.mage.card.arcane; package org.mage.card.arcane;
import java.awt.*; import java.awt.*;
@ -74,9 +69,9 @@ public final class CardRendererUtils {
int b = c.getBlue(); int b = c.getBlue();
int alpha = c.getAlpha(); int alpha = c.getAlpha();
int plus_r = (int) (Math.min (255 - r, r) / 2); int plus_r = (int) (Math.min(255 - r, r) / 2);
int plus_g = (int) (Math.min (255 - g, g) / 2); int plus_g = (int) (Math.min(255 - g, g) / 2);
int plus_b = (int) (Math.min (255 - b, b) / 2); int plus_b = (int) (Math.min(255 - b, b) / 2);
return new Color(r - plus_r, return new Color(r - plus_r,
g - plus_g, g - plus_g,
@ -192,4 +187,12 @@ public final class CardRendererUtils {
.replaceAll("<i>", "") .replaceAll("<i>", "")
.replaceAll("</i>", ""); .replaceAll("</i>", "");
} }
public static Color copyColor(Color color) {
if (color != null) {
return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
} else {
return null;
}
}
} }

View file

@ -9,10 +9,13 @@ import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.StringTokenizer; import java.util.StringTokenizer;
/**
* @author JayDi85
*/
public final class ManaSymbolsCellRenderer extends DefaultTableCellRenderer { public final class ManaSymbolsCellRenderer extends DefaultTableCellRenderer {
// base panel to render // base panel to render
private JPanel manaPanel = new JPanel(); private JPanel renderPanel = new JPanel();
@Override @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
@ -20,47 +23,47 @@ public final class ManaSymbolsCellRenderer extends DefaultTableCellRenderer {
// get table text cell settings // get table text cell settings
DefaultTableCellRenderer baseRenderer = (DefaultTableCellRenderer) table.getDefaultRenderer(String.class); DefaultTableCellRenderer baseRenderer = (DefaultTableCellRenderer) table.getDefaultRenderer(String.class);
JLabel baseLabel = (JLabel)baseRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); JLabel baseComp = (JLabel) baseRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
// apply settings to mana panel from parent // apply settings to mana panel from parent
manaPanel.setOpaque(baseLabel.isOpaque()); renderPanel.setOpaque(baseComp.isOpaque());
manaPanel.setForeground(baseLabel.getForeground()); renderPanel.setForeground(CardRendererUtils.copyColor(baseComp.getForeground()));
manaPanel.setBackground(baseLabel.getBackground()); renderPanel.setBackground(CardRendererUtils.copyColor(baseComp.getBackground()));
renderPanel.setBorder(baseComp.getBorder());
// icons size with margin // icons size with margin
int symbolWidth = GUISizeHelper.symbolTableSize; int symbolWidth = GUISizeHelper.symbolTableSize;
int symbolHorizontalMargin = 2; int symbolHorizontalMargin = 2;
// create each mana symbol as child label // create each mana symbol as child label
String manaCost = (String)value; String manaCost = (String) value;
manaPanel.removeAll(); renderPanel.removeAll();
manaPanel.setLayout(new BoxLayout(manaPanel, BoxLayout.X_AXIS)); renderPanel.setLayout(new BoxLayout(renderPanel, BoxLayout.X_AXIS));
if(manaCost != null){ if (manaCost != null) {
StringTokenizer tok = new StringTokenizer(manaCost, " "); StringTokenizer tok = new StringTokenizer(manaCost, " ");
while (tok.hasMoreTokens()) { while (tok.hasMoreTokens()) {
String symbol = tok.nextToken(); String symbol = tok.nextToken();
JLabel symbolLabel = new JLabel(); JLabel symbolLabel = new JLabel();
//symbolLabel.setBorder(new LineBorder(new Color(150, 150, 150))); // debug //symbolLabel.setBorder(new LineBorder(new Color(150, 150, 150))); // debug
symbolLabel.setBorder(new EmptyBorder(0, symbolHorizontalMargin,0, 0)); symbolLabel.setBorder(new EmptyBorder(0, symbolHorizontalMargin, 0, 0));
BufferedImage image = ManaSymbols.getSizedManaSymbol(symbol, symbolWidth); BufferedImage image = ManaSymbols.getSizedManaSymbol(symbol, symbolWidth);
if (image != null){ if (image != null) {
// icon // icon
symbolLabel.setIcon(new ImageIcon(image)); symbolLabel.setIcon(new ImageIcon(image));
}else } else {
{
// text // text
symbolLabel.setText("{" + symbol + "}"); symbolLabel.setText("{" + symbol + "}");
symbolLabel.setOpaque(baseLabel.isOpaque()); symbolLabel.setOpaque(baseComp.isOpaque());
symbolLabel.setForeground(baseLabel.getForeground()); symbolLabel.setForeground(baseComp.getForeground());
symbolLabel.setBackground(baseLabel.getBackground()); symbolLabel.setBackground(baseComp.getBackground());
} }
manaPanel.add(symbolLabel); renderPanel.add(symbolLabel);
} }
} }
return manaPanel; return renderPanel;
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

View file

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

View file

@ -13,8 +13,8 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
*/ */
public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MAJOR = 1;
public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_MINOR = 4;
public final static int MAGE_VERSION_PATCH = 31; public final static int MAGE_VERSION_PATCH = 32;
public final static String MAGE_VERSION_MINOR_PATCH = "V4"; public final static String MAGE_VERSION_MINOR_PATCH = "V0";
public final static String MAGE_VERSION_INFO = ""; public final static String MAGE_VERSION_INFO = "";
private final int major; private final int major;

View file

@ -36,6 +36,7 @@ public class TableView implements Serializable {
private List<SeatView> seats = new ArrayList<>(); private List<SeatView> seats = new ArrayList<>();
private List<UUID> games = new ArrayList<>(); private List<UUID> games = new ArrayList<>();
private final String quitRatio; private final String quitRatio;
private final String minimumRating;
private final boolean limited; private final boolean limited;
private final boolean rated; private final boolean rated;
private final boolean passworded; private final boolean passworded;
@ -111,6 +112,7 @@ public class TableView implements Serializable {
this.additionalInfo = addInfo.toString(); this.additionalInfo = addInfo.toString();
this.skillLevel = table.getMatch().getOptions().getSkillLevel(); this.skillLevel = table.getMatch().getOptions().getSkillLevel();
this.quitRatio = Integer.toString(table.getMatch().getOptions().getQuitRatio()); this.quitRatio = Integer.toString(table.getMatch().getOptions().getQuitRatio());
this.minimumRating = Integer.toString(table.getMatch().getOptions().getMinimumRating());
this.limited = table.getMatch().getOptions().isLimited(); this.limited = table.getMatch().getOptions().isLimited();
this.rated = table.getMatch().getOptions().isRated(); this.rated = table.getMatch().getOptions().isRated();
this.passworded = !table.getMatch().getOptions().getPassword().isEmpty(); this.passworded = !table.getMatch().getOptions().getPassword().isEmpty();
@ -159,6 +161,7 @@ public class TableView implements Serializable {
this.deckType = table.getDeckType() + ' ' + table.getTournament().getBoosterInfo() + (tableNameInfo != null ? tableNameInfo : ""); this.deckType = table.getDeckType() + ' ' + table.getTournament().getBoosterInfo() + (tableNameInfo != null ? tableNameInfo : "");
this.skillLevel = table.getTournament().getOptions().getMatchOptions().getSkillLevel(); this.skillLevel = table.getTournament().getOptions().getMatchOptions().getSkillLevel();
this.quitRatio = Integer.toString(table.getTournament().getOptions().getQuitRatio()); this.quitRatio = Integer.toString(table.getTournament().getOptions().getQuitRatio());
this.minimumRating = Integer.toString(table.getTournament().getOptions().getMinimumRating());
this.limited = table.getTournament().getOptions().getMatchOptions().isLimited(); this.limited = table.getTournament().getOptions().getMatchOptions().isLimited();
this.rated = table.getTournament().getOptions().getMatchOptions().isRated(); this.rated = table.getTournament().getOptions().getMatchOptions().isRated();
this.passworded = !table.getTournament().getOptions().getPassword().isEmpty(); this.passworded = !table.getTournament().getOptions().getPassword().isEmpty();
@ -223,9 +226,9 @@ public class TableView implements Serializable {
return skillLevel; return skillLevel;
} }
public String getQuitRatio() { public String getQuitRatio() { return quitRatio; }
return quitRatio;
} public String getMinimumRating() { return minimumRating; }
public boolean isLimited() { public boolean isLimited() {
return limited; return limited;

View file

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

View file

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

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-root</artifactId> <artifactId>mage-root</artifactId>
<version>1.4.31</version> <version>1.4.32</version>
</parent> </parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>

View file

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

View file

@ -45,6 +45,7 @@ public class CanadianHighlander extends Constructed {
pointMap.put("Personal Tutor", 1); pointMap.put("Personal Tutor", 1);
pointMap.put("Protean Hulk", 3); pointMap.put("Protean Hulk", 3);
pointMap.put("Sol Ring", 3); pointMap.put("Sol Ring", 3);
pointMap.put("Spellseeker", 1);
pointMap.put("Stoneforge Mystic", 1); pointMap.put("Stoneforge Mystic", 1);
pointMap.put("Strip Mine", 2); pointMap.put("Strip Mine", 2);
pointMap.put("Summoner's Pact", 2); pointMap.put("Summoner's Pact", 2);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -862,6 +862,19 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return target.isChosen(); return target.isChosen();
} }
if (target.getOriginalTarget() instanceof TargetCardInGraveyardOrBattlefield) {
List<Card> cards = new ArrayList<>();
for (Player player : game.getPlayers().values()) {
cards.addAll(player.getGraveyard().getCards(game));
cards.addAll(game.getBattlefield().getAllActivePermanents(new FilterPermanent(), player.getId(), game));
}
Card card = pickTarget(cards, outcome, target, source, game);
if (card != null) {
target.addTarget(card.getId(), source, game);
return true;
}
}
throw new IllegalStateException("Target wasn't handled. class:" + target.getClass().toString()); throw new IllegalStateException("Target wasn't handled. class:" + target.getClass().toString());
} //end of chooseTarget method } //end of chooseTarget method

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-root</artifactId> <artifactId>mage-root</artifactId>
<version>1.4.31</version> <version>1.4.32</version>
</parent> </parent>
<artifactId>mage-server-plugins</artifactId> <artifactId>mage-server-plugins</artifactId>

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-root</artifactId> <artifactId>mage-root</artifactId>
<version>1.4.31</version> <version>1.4.32</version>
</parent> </parent>
<artifactId>mage-server</artifactId> <artifactId>mage-server</artifactId>

View file

@ -227,6 +227,20 @@ public class MageServerImpl implements MageServer {
user.showUserMessage("Create tournament", message); user.showUserMessage("Create tournament", message);
throw new MageException("No message"); throw new MageException("No message");
} }
// check if the user satisfies the minimumRating requirement.
int minimumRating = options.getMinimumRating();
int userRating;
if (options.getMatchOptions().isLimited()) {
userRating = user.getUserData().getLimitedRating();
} else {
userRating = user.getUserData().getConstructedRating();
}
if (userRating < minimumRating) {
String message = new StringBuilder("Your rating ").append(userRating)
.append(" is lower than the table requirement ").append(minimumRating).toString();
user.showUserMessage("Create tournament", message);
throw new MageException("No message");
}
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId); Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
if (!room.isPresent()) { if (!room.isPresent()) {
@ -1386,7 +1400,19 @@ public class MageServerImpl implements MageServer {
user.showUserMessage("Create table", "Your quit ratio " + user.getMatchQuitRatio() + "% is higher than the table requirement " + quitRatio + '%'); user.showUserMessage("Create table", "Your quit ratio " + user.getMatchQuitRatio() + "% is higher than the table requirement " + quitRatio + '%');
throw new MageException("No message"); throw new MageException("No message");
} }
// check if the user satisfies the minimumRating requirement.
int minimumRating = options.getMinimumRating();
int userRating;
if (options.isLimited()) {
userRating = user.getUserData().getLimitedRating();
} else {
userRating = user.getUserData().getConstructedRating();
}
if (userRating < minimumRating) {
String message = new StringBuilder("Your rating ").append(userRating).append(" is lower than the table requirement ").append(minimumRating).toString();
user.showUserMessage("Create table", message);
throw new MageException("No message");
}
Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId); Optional<GamesRoom> room = GamesRoomManager.instance.getRoom(roomId);
if (room.isPresent()) { if (room.isPresent()) {
TableView table = room.get().createTable(userId, options); TableView table = room.get().createTable(userId, options);

View file

@ -172,6 +172,21 @@ public class TableController {
return false; return false;
} }
// Check minimum rating.
int minimumRating = table.getTournament().getOptions().getMinimumRating();
int userRating;
if (table.getTournament().getOptions().getMatchOptions().isLimited()) {
userRating = user.getUserData().getLimitedRating();
} else {
userRating = user.getUserData().getConstructedRating();
}
if (userRating < minimumRating) {
String message = new StringBuilder("Your rating ").append(userRating)
.append(" is lower than the table requirement ").append(minimumRating).toString();
user.showUserMessage("Join Table", message);
return false;
}
Optional<Player> playerOptional = createPlayer(name, seat.getPlayerType(), skill); Optional<Player> playerOptional = createPlayer(name, seat.getPlayerType(), skill);
if (playerOptional.isPresent()) { if (playerOptional.isPresent()) {
Player player = playerOptional.get(); Player player = playerOptional.get();
@ -272,6 +287,21 @@ public class TableController {
return false; return false;
} }
// Check minimum rating.
int minimumRating = table.getMatch().getOptions().getMinimumRating();
int userRating;
if (table.getMatch().getOptions().isLimited()) {
userRating = user.getUserData().getLimitedRating();
} else {
userRating = user.getUserData().getConstructedRating();
}
if (userRating < minimumRating) {
String message = new StringBuilder("Your rating ").append(userRating)
.append(" is lower than the table requirement ").append(minimumRating).toString();
user.showUserMessage("Join Table", message);
return false;
}
// Check power level for table (currently only used for EDH/Commander table) // Check power level for table (currently only used for EDH/Commander table)
int edhPowerLevel = table.getMatch().getOptions().getEdhPowerLevel(); int edhPowerLevel = table.getMatch().getOptions().getEdhPowerLevel();
if (edhPowerLevel > 0 && table.getValidator().getName().toLowerCase(Locale.ENGLISH).equals("commander")) { if (edhPowerLevel > 0 && table.getValidator().getName().toLowerCase(Locale.ENGLISH).equals("commander")) {

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>
<artifactId>mage-root</artifactId> <artifactId>mage-root</artifactId>
<version>1.4.31</version> <version>1.4.32</version>
</parent> </parent>
<groupId>org.mage</groupId> <groupId>org.mage</groupId>

View file

@ -1,10 +1,9 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.effects.common.LoseLifeAllPlayersEffect;
import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.MenaceAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -18,7 +17,7 @@ import mage.constants.SubType;
public final class AdroitHateflayer extends CardImpl { public final class AdroitHateflayer extends CardImpl {
public AdroitHateflayer(UUID ownerId, CardSetInfo setInfo) { public AdroitHateflayer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{U}{B}{R}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{B}{R}");
this.subtype.add(SubType.NAUTOLAN); this.subtype.add(SubType.NAUTOLAN);
this.subtype.add(SubType.SITH); this.subtype.add(SubType.SITH);
this.power = new MageInt(3); this.power = new MageInt(3);
@ -27,8 +26,8 @@ public final class AdroitHateflayer extends CardImpl {
// Menace // Menace
this.addAbility(new MenaceAbility()); this.addAbility(new MenaceAbility());
// Whenever Adroit Hateflayer attacks, each opponent loses 2 life. // Whenever Adroit Hateflayer attacks, each player loses 2 life.
this.addAbility(new AttacksTriggeredAbility(new LoseLifeOpponentsEffect(2), false)); this.addAbility(new AttacksTriggeredAbility(new LoseLifeAllPlayersEffect(2), false));
} }
public AdroitHateflayer(final AdroitHateflayer card) { public AdroitHateflayer(final AdroitHateflayer card) {

View file

@ -44,7 +44,7 @@ public class AminatouTheFateShifter extends CardImpl {
} }
public AminatouTheFateShifter(UUID ownerId, CardSetInfo setInfo) { public AminatouTheFateShifter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{W}{U}{B}"); super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{W}{U}{B}");
this.addSuperType(SuperType.LEGENDARY); this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.AMINATOU); this.subtype.add(SubType.AMINATOU);
@ -56,7 +56,7 @@ public class AminatouTheFateShifter extends CardImpl {
// -1: Exile another target permanent you own, then return it to the battlefield under your control. // -1: Exile another target permanent you own, then return it to the battlefield under your control.
ability = new LoyaltyAbility(new ExileTargetForSourceEffect(), -1); ability = new LoyaltyAbility(new ExileTargetForSourceEffect(), -1);
ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect()); ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(true));
ability.addTarget(new TargetPermanent(filter)); ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability); this.addAbility(ability);
@ -68,6 +68,7 @@ public class AminatouTheFateShifter extends CardImpl {
// Aminatou, the Fateshifter can be your commander. // Aminatou, the Fateshifter can be your commander.
this.addAbility(CanBeYourCommanderAbility.getInstance()); this.addAbility(CanBeYourCommanderAbility.getInstance());
} }
public AminatouTheFateShifter(final AminatouTheFateShifter card) { public AminatouTheFateShifter(final AminatouTheFateShifter card) {
super(card); super(card);
} }
@ -79,6 +80,7 @@ public class AminatouTheFateShifter extends CardImpl {
} }
class AminatouPlusEffect extends OneShotEffect { class AminatouPlusEffect extends OneShotEffect {
public AminatouPlusEffect() { public AminatouPlusEffect() {
super(Outcome.DrawCard); super(Outcome.DrawCard);
staticText = "draw a card, then put a card from your hand on top of your library"; staticText = "draw a card, then put a card from your hand on top of your library";
@ -118,10 +120,11 @@ class AminatouPlusEffect extends OneShotEffect {
} }
class AminatouUltimateEffect extends OneShotEffect { class AminatouUltimateEffect extends OneShotEffect {
public AminatouUltimateEffect (){
public AminatouUltimateEffect() {
super(Outcome.Benefit); super(Outcome.Benefit);
staticText = "Choose left or right. Each player gains control of all nonland permanents other than Aminatou," + staticText = "Choose left or right. Each player gains control of all nonland permanents other than Aminatou,"
" the Fateshifter controlled by the next player in the chosen direction."; + " the Fateshifter controlled by the next player in the chosen direction.";
} }
public AminatouUltimateEffect(final AminatouUltimateEffect effect) { public AminatouUltimateEffect(final AminatouUltimateEffect effect) {
@ -129,7 +132,9 @@ class AminatouUltimateEffect extends OneShotEffect {
} }
@Override @Override
public AminatouUltimateEffect copy(){return new AminatouUltimateEffect(this);} public AminatouUltimateEffect copy() {
return new AminatouUltimateEffect(this);
}
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
@ -154,7 +159,7 @@ class AminatouUltimateEffect extends OneShotEffect {
return false; return false;
} }
// skip players out of range // skip players out of range
if (!game.getState().getPlayersInRange(controller.getId(), game).contains(nextPlayer)){ if (!game.getState().getPlayersInRange(controller.getId(), game).contains(nextPlayer)) {
continue; continue;
} }
// save first next player to check for iteration stop // save first next player to check for iteration stop
@ -164,7 +169,7 @@ class AminatouUltimateEffect extends OneShotEffect {
FilterNonlandPermanent nextPlayerNonlandPermanentsFilter = new FilterNonlandPermanent(); FilterNonlandPermanent nextPlayerNonlandPermanentsFilter = new FilterNonlandPermanent();
nextPlayerNonlandPermanentsFilter.add(new ControllerIdPredicate(nextPlayer)); nextPlayerNonlandPermanentsFilter.add(new ControllerIdPredicate(nextPlayer));
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(nextPlayerNonlandPermanentsFilter, game)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(nextPlayerNonlandPermanentsFilter, game)) {
if (permanent.getId().equals(source.getSourceId())){ if (permanent.getId().equals(source.getSourceId())) {
continue; continue;
} }
ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfGame, currentPlayer); ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfGame, currentPlayer);
@ -188,4 +193,3 @@ class AminatouUltimateEffect extends OneShotEffect {
return nextPlayerId; return nextPlayerId;
} }
} }

View file

@ -1,34 +1,23 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
import mage.abilities.common.ZoneChangeTriggeredAbility; import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromExileForSourceEffect; import mage.abilities.effects.common.ReturnFromExileForSourceEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.AnotherPredicate; import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target; import mage.target.Target;
import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInGraveyardOrBattlefield;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
/** /**
* *
@ -36,8 +25,10 @@ import mage.util.CardUtil;
*/ */
public final class AngelOfSerenity extends CardImpl { public final class AngelOfSerenity extends CardImpl {
private static final String rule = "you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards.";
public AngelOfSerenity(UUID ownerId, CardSetInfo setInfo) { public AngelOfSerenity(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{W}{W}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}{W}");
this.subtype.add(SubType.ANGEL); this.subtype.add(SubType.ANGEL);
this.power = new MageInt(5); this.power = new MageInt(5);
@ -47,7 +38,12 @@ public final class AngelOfSerenity extends CardImpl {
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// When Angel of Serenity enters the battlefield, you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards. // When Angel of Serenity enters the battlefield, you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards.
this.addAbility(new AngelOfSerenityTriggeredAbility()); FilterCreatureCard filter = new FilterCreatureCard("creatures from the battlefield and/or a graveyard");
filter.add(Predicates.not(new CardIdPredicate(this.getId())));
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect().setText(rule), true);
Target target = new TargetCardInGraveyardOrBattlefield(0, 3, filter);
ability.addTarget(target);
this.addAbility(ability);
// When Angel of Serenity leaves the battlefield, return the exiled cards to their owners' hands. // When Angel of Serenity leaves the battlefield, return the exiled cards to their owners' hands.
this.addAbility(new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.HAND, false, true), false)); this.addAbility(new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.HAND, false, true), false));
@ -62,92 +58,3 @@ public final class AngelOfSerenity extends CardImpl {
return new AngelOfSerenity(this); return new AngelOfSerenity(this);
} }
} }
class AngelOfSerenityTriggeredAbility extends ZoneChangeTriggeredAbility {
public AngelOfSerenityTriggeredAbility() {
super(Zone.BATTLEFIELD, new AngelOfSerenityEnterEffect(), "When {this} enters the battlefield, ", true);
}
public AngelOfSerenityTriggeredAbility(AngelOfSerenityTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (super.checkTrigger(event, game)) {
getTargets().clear();
FilterCreaturePermanent filter = new FilterCreaturePermanent("up to three other target creatures");
filter.add(new AnotherPredicate());
TargetCreaturePermanent target1 = new TargetCreaturePermanent(0, 3, filter, false);
game.getPlayer(getControllerId()).chooseTarget(Outcome.Exile, target1, this, game);
if (!target1.getTargets().isEmpty()) {
getTargets().add(target1);
}
int leftTargets = 3 - target1.getTargets().size();
if (leftTargets > 0) {
FilterCard filter2 = new FilterCreatureCard("up to " + leftTargets + " target creature card" + (leftTargets > 1 ? "s" : "") + " from graveyards");
TargetCardInGraveyard target2 = new TargetCardInGraveyard(0, leftTargets, filter2);
game.getPlayer(getControllerId()).chooseTarget(Outcome.Exile, target2, this, game);
if (!target2.getTargets().isEmpty()) {
getTargets().add(target2);
}
}
return true;
}
return false;
}
@Override
public AngelOfSerenityTriggeredAbility copy() {
return new AngelOfSerenityTriggeredAbility(this);
}
}
class AngelOfSerenityEnterEffect extends OneShotEffect {
public AngelOfSerenityEnterEffect() {
super(Outcome.ReturnToHand);
this.staticText = "you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards";
}
public AngelOfSerenityEnterEffect(final AngelOfSerenityEnterEffect effect) {
super(effect);
}
@Override
public AngelOfSerenityEnterEffect copy() {
return new AngelOfSerenityEnterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
boolean result = true;
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller != null && sourceObject != null && !source.getTargets().isEmpty()) {
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
for (Target target : source.getTargets()) {
if (target instanceof TargetCreaturePermanent) {
for (UUID permanentId : target.getTargets()) {
Permanent permanent = game.getPermanent(permanentId);
if (permanent != null) {
result |= controller.moveCardToExileWithInfo(permanent, exileZoneId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true);
}
}
} else if (target instanceof TargetCardInGraveyard) {
for (UUID cardId : target.getTargets()) {
Card card = game.getCard(cardId);
if (card != null) {
result |= controller.moveCardToExileWithInfo(card, exileZoneId, sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true);
}
}
}
}
}
return result;
}
}

View file

@ -0,0 +1,67 @@
package mage.cards.a;
import java.util.UUID;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.target.common.TargetAttackingOrBlockingCreature;
/**
*
* @author jeffwadsworth
*/
public final class ArcheryTraining extends CardImpl {
private static final String rule = "This creature deals X damage to target attacking or blocking creature, where X is the number of arrow counters on {this}.";
public ArcheryTraining(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// At the beginning of your upkeep, you may put an arrow counter on Archery Training.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD,
new AddCountersSourceEffect(CounterType.ARROW.createInstance(), true), TargetController.YOU, true));
// Enchanted creature has "{tap}: This creature deals X damage to target attacking or blocking creature, where X is the number of arrow counters on Archery Training."
Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.ARROW)).setText(rule), new TapSourceCost());
gainedAbility.addTarget(new TargetAttackingOrBlockingCreature());
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA)));
}
public ArcheryTraining(final ArcheryTraining card) {
super(card);
}
@Override
public ArcheryTraining copy() {
return new ArcheryTraining(this);
}
}

View file

@ -1,14 +1,14 @@
package mage.cards.b; package mage.cards.b;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.common.SkipNextCombatEffect; import mage.abilities.effects.common.SkipCombatStepEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
/** /**
@ -18,7 +18,7 @@ import mage.constants.SubType;
public final class BlindingAngel extends CardImpl { public final class BlindingAngel extends CardImpl {
public BlindingAngel(UUID ownerId, CardSetInfo setInfo) { public BlindingAngel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
this.subtype.add(SubType.ANGEL); this.subtype.add(SubType.ANGEL);
this.power = new MageInt(2); this.power = new MageInt(2);
@ -26,8 +26,10 @@ public final class BlindingAngel extends CardImpl {
// Flying // Flying
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// Whenever Blinding Angel deals combat damage to a player, that player skips their next combat phase. // Whenever Blinding Angel deals combat damage to a player, that player skips their next combat phase.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new SkipNextCombatEffect(), false, true)); this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new SkipCombatStepEffect(Duration.OneUse).setText("that player skips their next combat phase."), false, true));
} }
public BlindingAngel(final BlindingAngel card) { public BlindingAngel(final BlindingAngel card) {

View file

@ -0,0 +1,91 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalReplacementEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventAllDamageToSourceEffect;
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.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.target.Target;
/**
*
* @author L_J
*/
public final class BronzeHorse extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
static {
filter.add(new AnotherPredicate());
}
public BronzeHorse(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT, CardType.CREATURE},"{7}");
this.subtype.add(SubType.HORSE);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Trample
this.addAbility(TrampleAbility.getInstance());
// As long as you control another creature, prevent all damage that would be dealt to Bronze Horse by spells that target it.
Effect effect = new ConditionalReplacementEffect(new PreventDamageToSourceBySpellsThatTargetIt(), new PermanentsOnTheBattlefieldCondition(filter));
effect.setText("As long as you control another creature, prevent all damage that would be dealt to {this} by spells that target it.");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public BronzeHorse(final BronzeHorse card) {
super(card);
}
@Override
public BronzeHorse copy() {
return new BronzeHorse(this);
}
}
class PreventDamageToSourceBySpellsThatTargetIt extends PreventAllDamageToSourceEffect {
public PreventDamageToSourceBySpellsThatTargetIt() {
super(Duration.WhileOnBattlefield);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (super.applies(event, source, game)) {
if (event.getTargetId().equals(source.getSourceId())) {
Spell spell = game.getStack().getSpell(event.getSourceId());
if (spell != null) {
for (UUID modeId : spell.getStackAbility().getModes().getSelectedModes()) {
Mode mode = spell.getStackAbility().getModes().get(modeId);
for (Target target : mode.getTargets()) {
for (UUID targetId : target.getTargets()) {
if (targetId.equals(source.getSourceId())) {
return true;
}
}
}
}
}
}
}
return false;
}
}

View file

@ -0,0 +1,52 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.PutOnLibraryTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.target.common.TargetCardInYourGraveyard;
/**
*
* @author L_J
*/
public final class CanalDredger extends CardImpl {
public CanalDredger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}");
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(1);
this.toughness = new MageInt(5);
// TODO: Draft specific abilities not implemented
// Draft Canal Dredger face up.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft Canal Dredger face up.")));
// Each player passes the last card from each booster pack to a player who drafted a card named Canal Dredger.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Each player passes the last card from each booster pack to a player who drafted a card named Canal Dredger.")));
// {T}: Put target card from your graveyard on the bottom of your library.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutOnLibraryTargetEffect(false), new TapSourceCost());
ability.addTarget(new TargetCardInYourGraveyard());
this.addAbility(ability);
}
public CanalDredger(final CanalDredger card) {
super(card);
}
@Override
public CanalDredger copy() {
return new CanalDredger(this);
}
}

View file

@ -0,0 +1,93 @@
package mage.cards.c;
import java.util.UUID;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.AttacksAttachedTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author jeffwadsworth
*/
public final class Contempt extends CardImpl {
public Contempt(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Whenever enchanted creature attacks, return it and Contempt to their owners' hands at end of combat.
this.addAbility(new AttacksAttachedTriggeredAbility(new ContemptEffect()));
}
public Contempt(final Contempt card) {
super(card);
}
@Override
public Contempt copy() {
return new Contempt(this);
}
}
class ContemptEffect extends OneShotEffect {
ContemptEffect() {
super(Outcome.Detriment);
this.staticText = "return it and {this} to their owners' hands at end of combat.";
}
ContemptEffect(final ContemptEffect effect) {
super(effect);
}
@Override
public ContemptEffect copy() {
return new ContemptEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent contempt = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (contempt != null) {
Permanent attachedToPermanent = game.getPermanent(contempt.getAttachedTo());
if (attachedToPermanent != null) {
Effect effect = new ReturnToHandTargetEffect();
effect.setTargetPointer(new FixedTarget(
attachedToPermanent.getId())).setText("return "
+ attachedToPermanent.getName() + " to owner's hand.");
AtTheEndOfCombatDelayedTriggeredAbility ability = new AtTheEndOfCombatDelayedTriggeredAbility(effect);
game.addDelayedTriggeredAbility(ability, source);
}
Effect effect = new ReturnToHandSourceEffect();
AtTheEndOfCombatDelayedTriggeredAbility ability = new AtTheEndOfCombatDelayedTriggeredAbility(effect);
game.addDelayedTriggeredAbility(ability, source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,50 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
/**
*
* @author L_J
*/
public final class DealBroker extends CardImpl {
public DealBroker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT, CardType.CREATURE},"{3}");
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// TODO: Draft specific abilities not implemented
// Draft Deal Broker face up.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft Deal Broker face up.")));
// Immediately after the draft, you may reveal a card in your card pool. Each other player may offer you one card in their card pool in exchange. You may accept any one offer.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Immediately after the draft, you may reveal a card in your card pool. "
+ "Each other player may offer you one card in their card pool in exchange. You may accept any one offer.")));
// {T}: Draw a card, then discard a card.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawDiscardControllerEffect(), new TapSourceCost()));
}
public DealBroker(final DealBroker card) {
super(card);
}
@Override
public DealBroker copy() {
return new DealBroker(this);
}
}

View file

@ -0,0 +1,87 @@
package mage.cards.d;
import java.util.UUID;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author jeffwadsworth
*/
public final class Disappear extends CardImpl {
public Disappear(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// {U}: Return enchanted creature and Disappear to their owners' hands.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DisappearEffect(), new ManaCostsImpl("{U}")));
}
public Disappear(final Disappear card) {
super(card);
}
@Override
public Disappear copy() {
return new Disappear(this);
}
}
class DisappearEffect extends OneShotEffect {
public DisappearEffect() {
super(Outcome.ReturnToHand);
staticText = "Return enchanted creature and {this} to their owners' hands";
}
public DisappearEffect(final DisappearEffect effect) {
super(effect);
}
@Override
public DisappearEffect copy() {
return new DisappearEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent aura = (Permanent) game.getPermanentOrLKIBattlefield(source.getSourceId());
Player controller = game.getPlayer(source.getControllerId());
if (controller != null
&& aura != null
&& aura.getAttachedTo() != null) {
Permanent enchantedCreature = game.getPermanent(aura.getAttachedTo());
controller.moveCards(aura, Zone.HAND, source, game);
if (enchantedCreature != null) {
controller.moveCards(enchantedCreature, Zone.HAND, source, game);
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,200 @@
package mage.cards.d;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.discard.DiscardControllerEffect;
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.TargetController;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
* @author jeffwadsworth
*/
public final class Duplicity extends CardImpl {
public Duplicity(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}");
// When Duplicity enters the battlefield, exile the top five cards of your library face down.
this.addAbility(new EntersBattlefieldTriggeredAbility(new DuplicityEffect(), false));
// At the beginning of your upkeep, you may exile all cards from your hand face down. If you do, put all other cards you own exiled with Duplicity into your hand.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DuplicityExileHandEffect(), TargetController.YOU, true));
// At the beginning of your end step, discard a card.
this.addAbility(new BeginningOfYourEndStepTriggeredAbility(new DiscardControllerEffect(1), false));
// When you lose control of Duplicity, put all cards exiled with Duplicity into their owner's graveyard.
this.addAbility(new LoseControlDuplicity());
}
public Duplicity(final Duplicity card) {
super(card);
}
@Override
public Duplicity copy() {
return new Duplicity(this);
}
}
class DuplicityEffect extends OneShotEffect {
public DuplicityEffect() {
super(Outcome.Exile);
staticText = "exile the top five cards of your library face down";
}
public DuplicityEffect(final DuplicityEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller != null
&& sourceObject != null) {
if (controller.getLibrary().hasCards()) {
UUID exileId = CardUtil.getCardExileZoneId(game, source);
Set<Card> cardsToExile = controller.getLibrary().getTopCards(game, 5);
for (Card card : cardsToExile) {
controller.moveCardsToExile(card, source, game, true, exileId, sourceObject.getName());
card.setFaceDown(true, game);
}
}
return true;
}
return false;
}
@Override
public DuplicityEffect copy() {
return new DuplicityEffect(this);
}
}
class DuplicityExileHandEffect extends OneShotEffect {
public DuplicityExileHandEffect() {
super(Outcome.Exile);
staticText = "you may exile all cards from your hand face down. If you do, put all other cards you own exiled with {this} into your hand";
}
public DuplicityExileHandEffect(final DuplicityExileHandEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller != null
&& sourceObject != null) {
if (!controller.getHand().isEmpty()) {
UUID exileId = CardUtil.getCardExileZoneId(game, source);
Set<Card> cardsFromHandToExile = controller.getHand().getCards(game);
for (Card card : cardsFromHandToExile) {
controller.moveCardsToExile(card, source, game, true, exileId, sourceObject.getName());
card.setFaceDown(true, game);
}
Set<Card> cardsInExile = game.getExile().getExileZone(exileId).getCards(game);
Set<Card> cardsToReturnToHandFromExile = new HashSet<>();
for (Card card : cardsInExile) {
if (!cardsFromHandToExile.contains(card)) {
cardsToReturnToHandFromExile.add(card);
}
}
controller.moveCards(cardsToReturnToHandFromExile, Zone.HAND, source, game);
}
return true;
}
return false;
}
@Override
public DuplicityExileHandEffect copy() {
return new DuplicityExileHandEffect(this);
}
}
class LoseControlDuplicity extends DelayedTriggeredAbility {
public LoseControlDuplicity() {
super(new PutExiledCardsInOwnersGraveyard(), Duration.EndOfGame, false);
}
public LoseControlDuplicity(final LoseControlDuplicity ability) {
super(ability);
}
@Override
public LoseControlDuplicity copy() {
return new LoseControlDuplicity(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.LOST_CONTROL;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getPlayerId().equals(controllerId);
}
@Override
public String getRule() {
return "When you lose control of {this}, put all cards exiled with {this} into their owner's graveyard.";
}
}
class PutExiledCardsInOwnersGraveyard extends OneShotEffect {
public PutExiledCardsInOwnersGraveyard() {
super(Outcome.Neutral);
staticText = " put all cards exiled with {this} into their owner's graveyard.";
}
public PutExiledCardsInOwnersGraveyard(final PutExiledCardsInOwnersGraveyard effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller != null
&& sourceObject != null) {
UUID exileId = CardUtil.getCardExileZoneId(game, source);
Set<Card> cardsInExile = game.getExile().getExileZone(exileId).getCards(game);
controller.moveCardsToGraveyardWithInfo(cardsInExile, source, game, Zone.EXILED);
return true;
}
return false;
}
@Override
public PutExiledCardsInOwnersGraveyard copy() {
return new PutExiledCardsInOwnersGraveyard(this);
}
}

View file

@ -0,0 +1,102 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleEvasionAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author L_J
*/
public final class ElderSpawn extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("red creatures");
static {
filter.add(new ColorPredicate(ObjectColor.RED));
}
public ElderSpawn(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}{U}");
this.subtype.add(SubType.SPAWN);
this.power = new MageInt(6);
this.toughness = new MageInt(6);
// At the beginning of your upkeep, unless you sacrifice an Island, sacrifice Elder Spawn and it deals 6 damage to you.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ElderSpawnEffect(), TargetController.YOU, false));
// Elder Spawn can't be blocked by red creatures.
this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield)));
}
public ElderSpawn(final ElderSpawn card) {
super(card);
}
@Override
public ElderSpawn copy() {
return new ElderSpawn(this);
}
}
class ElderSpawnEffect extends OneShotEffect {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("an Island");
static {
filter.add(new SubtypePredicate(SubType.ISLAND));
}
public ElderSpawnEffect() {
super(Outcome.Sacrifice);
staticText = "unless you sacrifice an Island, sacrifice {this} and it deals 6 damage to you";
}
public ElderSpawnEffect(final ElderSpawnEffect effect) {
super(effect);
}
@Override
public ElderSpawnEffect copy() {
return new ElderSpawnEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (controller != null && sourcePermanent != null) {
TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true);
SacrificeTargetCost cost = new SacrificeTargetCost(target);
if (!controller.chooseUse(Outcome.AIDontUseIt, "Do you wish to sacrifice an Island?", source, game)
|| !cost.canPay(source, source.getSourceId(), source.getControllerId(), game)
|| !cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) {
sourcePermanent.sacrifice(source.getSourceId(), game);
controller.damage(6, sourcePermanent.getId(), game, false, true);
}
return true;
}
return false;
}
}

View file

@ -1,11 +1,11 @@
package mage.cards.e; package mage.cards.e;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.common.SkipNextCombatEffect; import mage.abilities.effects.common.SkipCombatStepEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.common.TargetOpponent; import mage.target.common.TargetOpponent;
/** /**
@ -15,10 +15,10 @@ import mage.target.common.TargetOpponent;
public final class EmptyCityRuse extends CardImpl { public final class EmptyCityRuse extends CardImpl {
public EmptyCityRuse(UUID ownerId, CardSetInfo setInfo) { public EmptyCityRuse(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{W}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}");
// Target opponent skips all combat phases of their next turn. // Target opponent skips all combat phases of their next turn.
this.getSpellAbility().addEffect(new SkipNextCombatEffect()); this.getSpellAbility().addEffect(new SkipCombatStepEffect(Duration.UntilYourNextTurn).setText("Target opponent skips all combat phases of their next turn."));
this.getSpellAbility().addTarget(new TargetOpponent()); this.getSpellAbility().addTarget(new TargetOpponent());
} }

View file

@ -0,0 +1,79 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventAllDamageToSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
/**
*
* @author L_J
*/
public final class EnchantedBeing extends CardImpl {
public EnchantedBeing(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}");
this.subtype.add(SubType.HUMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Prevent all damage that would be dealt to Enchanted Being by enchanted creatures.
Effect effect = new PreventDamageToSourceByEnchantedCreatures();
effect.setText("Prevent all damage that would be dealt to {this} by enchanted creatures.");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public EnchantedBeing(final EnchantedBeing card) {
super(card);
}
@Override
public EnchantedBeing copy() {
return new EnchantedBeing(this);
}
}
class PreventDamageToSourceByEnchantedCreatures extends PreventAllDamageToSourceEffect {
public PreventDamageToSourceByEnchantedCreatures() {
super(Duration.WhileOnBattlefield);
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (super.applies(event, source, game)) {
if (isEnchantedCreature(game.getObject(event.getSourceId()), game)) {
if (event.getTargetId().equals(source.getSourceId())) {
return true;
}
}
}
return false;
}
public boolean isEnchantedCreature(MageObject input, Game game) {
if (input == null || input.isCreature()) {
return false;
}
for (UUID attachmentId : ((Permanent) input).getAttachments()) {
Permanent attachment = game.getPermanent(attachmentId);
if (attachment != null && attachment.isEnchantment()) {
return true;
}
}
return false;
}
}

View file

@ -1,11 +1,11 @@
package mage.cards.f; package mage.cards.f;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.common.SkipNextCombatEffect; import mage.abilities.effects.common.SkipCombatStepEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
/** /**
@ -15,10 +15,10 @@ import mage.target.TargetPlayer;
public final class FalsePeace extends CardImpl { public final class FalsePeace extends CardImpl {
public FalsePeace(UUID ownerId, CardSetInfo setInfo) { public FalsePeace(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{W}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}");
// Target player skips all combat phases of their next turn. // Target player skips all combat phases of their next turn.
this.getSpellAbility().addEffect(new SkipNextCombatEffect()); this.getSpellAbility().addEffect(new SkipCombatStepEffect(Duration.UntilYourNextTurn).setText("Target player skips all combat phases of their next turn."));
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
} }

View file

@ -0,0 +1,36 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.effects.common.SkipNextDrawStepTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.TargetPlayer;
/**
*
* @author jeffwadsworth
*/
public final class Fatigue extends CardImpl {
private static final String rule = "Target player skips his or her next draw step.";
public Fatigue(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}");
// Target player skips his or her next draw step.
this.getSpellAbility().addEffect(new SkipNextDrawStepTargetEffect().setText(rule));
this.getSpellAbility().addTarget(new TargetPlayer());
}
public Fatigue(final Fatigue card) {
super(card);
}
@Override
public Fatigue copy() {
return new Fatigue(this);
}
}

View file

@ -0,0 +1,41 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.PreventDamageByTargetEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author jeffwadsworth
*/
public final class FendOff extends CardImpl {
private static final String rule = "Prevent all combat damage that would be dealt by target creature this turn.";
public FendOff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Prevent all combat damage that would be dealt by target creature this turn.
this.getSpellAbility().addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true).setText(rule));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
// Cycling {2}
this.addAbility(new CyclingAbility(new ManaCostsImpl("{2}")));
}
public FendOff(final FendOff card) {
super(card);
}
@Override
public FendOff copy() {
return new FendOff(this);
}
}

View file

@ -156,8 +156,12 @@ class FlickerformReturnEffect extends OneShotEffect {
} }
ExileZone exileZone = game.getExile().getExileZone(exileZoneId); ExileZone exileZone = game.getExile().getExileZone(exileZoneId);
Card enchantedCard = exileZone.get(enchantedCardId, game); Card enchantedCard = exileZone.get(enchantedCardId, game);
//skip if exiled card is missing
if (enchantedCard != null) { if (enchantedCard != null) {
controller.moveCards(enchantedCard, Zone.BATTLEFIELD, source, game); Player owner = game.getPlayer(enchantedCard.getOwnerId());
//skip if card's owner is missing
if (owner != null) {
owner.moveCards(enchantedCard, Zone.BATTLEFIELD, source, game);
Permanent newPermanent = game.getPermanent(enchantedCardId); Permanent newPermanent = game.getPermanent(enchantedCardId);
if (newPermanent != null) { if (newPermanent != null) {
Set<Card> toBattlefieldAttached = new HashSet<Card>(); Set<Card> toBattlefieldAttached = new HashSet<Card>();
@ -190,6 +194,7 @@ class FlickerformReturnEffect extends OneShotEffect {
} }
return true; return true;
} }
}
return false; return false;
} }
} }

View file

@ -0,0 +1,91 @@
package mage.cards.f;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent;
/**
*
* @author L_J
*/
public final class ForethoughtAmulet extends CardImpl {
public ForethoughtAmulet(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
// At the beginning of your upkeep, sacrifice Forethought Amulet unless you pay {3}.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new GenericManaCost(3)), TargetController.YOU, false));
// If an instant or sorcery source would deal 3 or more damage to you, it deals 2 damage to you instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ForethoughtAmuletEffect()));
}
public ForethoughtAmulet(final ForethoughtAmulet card) {
super(card);
}
@Override
public ForethoughtAmulet copy() {
return new ForethoughtAmulet(this);
}
}
class ForethoughtAmuletEffect extends ReplacementEffectImpl {
public ForethoughtAmuletEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
staticText = "If an instant or sorcery source would deal 3 or more damage to you, it deals 2 damage to you instead";
}
public ForethoughtAmuletEffect(final ForethoughtAmuletEffect effect) {
super(effect);
}
@Override
public ForethoughtAmuletEffect copy() {
return new ForethoughtAmuletEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getAmount() >= 3) {
MageObject object = game.getObject(event.getSourceId());
return object != null && (object.isInstant() || object.isSorcery());
}
return false;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
if (event.getTargetId().equals(source.getControllerId())) {
event.setAmount(2);
}
return false;
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.g; package mage.cards.g;
import java.util.UUID; import java.util.UUID;
@ -16,7 +15,6 @@ import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterBasicLandCard;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
@ -30,7 +28,7 @@ import mage.target.common.TargetLandPermanent;
public final class GhostQuarter extends CardImpl { public final class GhostQuarter extends CardImpl {
public GhostQuarter(UUID ownerId, CardSetInfo setInfo) { public GhostQuarter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.LAND},""); super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
// {T}: Add {C}. // {T}: Add {C}.
this.addAbility(new ColorlessManaAbility()); this.addAbility(new ColorlessManaAbility());

View file

@ -77,9 +77,9 @@ class GoblinMachinistEffect extends OneShotEffect {
break; break;
} }
} }
}
controller.revealCards(source, cards, game); controller.revealCards(source, cards, game);
controller.putCardsOnBottomOfLibrary(cards, game, source, true); controller.putCardsOnBottomOfLibrary(cards, game, source, true);
}
return true; return true;
} }
return false; return false;

View file

@ -71,7 +71,10 @@ class HiddenPredatorsStateTriggeredAbility extends StateTriggeredAbility {
@Override @Override
public boolean checkInterveningIfClause(Game game) { public boolean checkInterveningIfClause(Game game) {
return this.getSourcePermanentIfItStillExists(game).getCardType().contains(CardType.ENCHANTMENT); if (getSourcePermanentIfItStillExists(game) != null) {
return getSourcePermanentIfItStillExists(game).isEnchantment();
}
return false;
} }
@Override @Override

View file

@ -59,15 +59,17 @@ class IcequakeEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null && controller != null) { if (permanent != null) {
Player controller = game.getPlayer(permanent.getControllerId());
if(controller != null) {
permanent.destroy(source.getSourceId(), game, false); permanent.destroy(source.getSourceId(), game, false);
if (permanent.isSnow()) { if (permanent.isSnow()) {
controller.damage(1, source.getSourceId(), game, false, true); controller.damage(1, source.getSourceId(), game, false, true);
} }
return true; return true;
} }
}
return false; return false;
} }
} }

View file

@ -0,0 +1,65 @@
package mage.cards.i;
import java.util.UUID;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.DiesAttachedTriggeredAbility;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.target.common.TargetCreatureOrPlayer;
/**
*
* @author jeffwadsworth
*/
public final class Incendiary extends CardImpl {
private static final String rule = "{this} deals X damage to any target, where X is the number of fuse counters on {this}.";
public Incendiary(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// At the beginning of your upkeep, you may put a fuse counter on Incendiary.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD,
new AddCountersSourceEffect(CounterType.FUSE.createInstance(), true), TargetController.YOU, true));
// When enchanted creature dies, Incendiary deals X damage to any target, where X is the number of fuse counters on Incendiary.
Effect effect = new DamageTargetEffect(new CountersSourceCount(CounterType.FUSE)).setText(rule);
Ability ability2 = new DiesAttachedTriggeredAbility(effect, "enchanted creature");
ability.addTarget(new TargetCreatureOrPlayer());
this.addAbility(ability2);
}
public Incendiary(final Incendiary card) {
super(card);
}
@Override
public Incendiary copy() {
return new Incendiary(this);
}
}

View file

@ -1,7 +1,8 @@
package mage.cards.j; package mage.cards.j;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import mage.MageObjectReference; import mage.MageObjectReference;
@ -9,7 +10,6 @@ import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility; import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility; import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.Card; import mage.cards.Card;
@ -24,7 +24,10 @@ import mage.constants.SubType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.FilterPlayer;
import mage.filter.common.FilterNonlandCard; import mage.filter.common.FilterNonlandCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.other.PlayerIdPredicate;
import mage.game.ExileZone; import mage.game.ExileZone;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
@ -32,6 +35,7 @@ import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetCard; import mage.target.TargetCard;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInExile; import mage.target.common.TargetCardInExile;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetOpponent; import mage.target.common.TargetOpponent;
@ -119,9 +123,9 @@ class JaceArchitectOfThoughtDelayedTriggeredAbility extends DelayedTriggeredAbil
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
if (game.getOpponents(getControllerId()).contains(event.getPlayerId())) { if (game.getOpponents(getControllerId()).contains(event.getPlayerId())) {
for (Effect effect : getEffects()) { getEffects().forEach((effect) -> {
effect.setTargetPointer(new FixedTarget(event.getSourceId())); effect.setTargetPointer(new FixedTarget(event.getSourceId()));
} });
return true; return true;
} }
return false; return false;
@ -180,7 +184,6 @@ class JaceArchitectOfThoughtEffect2 extends OneShotEffect {
if (opponent == null) { if (opponent == null) {
opponent = game.getPlayer(opponents.iterator().next()); opponent = game.getPlayer(opponents.iterator().next());
} }
TargetCard target = new TargetCard(0, allCards.size(), Zone.LIBRARY, new FilterCard("cards to put in the first pile")); TargetCard target = new TargetCard(0, allCards.size(), Zone.LIBRARY, new FilterCard("cards to put in the first pile"));
target.setNotTarget(true); target.setNotTarget(true);
opponent.choose(Outcome.Neutral, allCards, target, game); opponent.choose(Outcome.Neutral, allCards, target, game);
@ -206,9 +209,9 @@ class JaceArchitectOfThoughtEffect2 extends OneShotEffect {
private void postPileToLog(String pileName, Set<Card> cards, Game game) { private void postPileToLog(String pileName, Set<Card> cards, Game game) {
StringBuilder message = new StringBuilder(pileName).append(": "); StringBuilder message = new StringBuilder(pileName).append(": ");
for (Card card : cards) { cards.forEach((card) -> {
message.append(card.getName()).append(' '); message.append(card.getName()).append(' ');
} });
if (cards.isEmpty()) { if (cards.isEmpty()) {
message.append(" (empty)"); message.append(" (empty)");
} }
@ -239,30 +242,65 @@ class JaceArchitectOfThoughtEffect3 extends OneShotEffect {
if (controller == null || sourcePermanent == null) { if (controller == null || sourcePermanent == null) {
return false; return false;
} }
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { if (controller.chooseUse(Outcome.Benefit, "Look at all players' libraries before card select?", null, game)) {
game.informPlayers(controller.getLogName() + " is looking at all players' libraries.");
controller.lookAtAllLibraries(source, game);
}
List<UUID> playerList = new ArrayList<>();
playerList.addAll(game.getState().getPlayersInRange(controller.getId(), game));
Set<UUID> checkList = new HashSet<>();
while (!playerList.isEmpty()) {
FilterPlayer filter = new FilterPlayer();
List<PlayerIdPredicate> playerPredicates = new ArrayList<>();
playerList.forEach((playerId) -> {
playerPredicates.add(new PlayerIdPredicate(playerId));
});
filter.add(Predicates.or(playerPredicates));
TargetPlayer targetPlayer = new TargetPlayer(1, 1, true, filter);
targetPlayer.setRequired(!checkList.containsAll(playerList));
if (controller.chooseTarget(outcome, targetPlayer, source, game)) {
UUID playerId = targetPlayer.getFirstTarget();
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null) {
String playerName = new StringBuilder(player.getLogName()).append("'s").toString(); String playerName = new StringBuilder(player.getLogName()).append("'s").toString();
if (source.isControlledBy(player.getId())) { if (source.isControlledBy(player.getId())) {
playerName = "your"; playerName = "your";
} }
TargetCardInLibrary target = new TargetCardInLibrary(new FilterNonlandCard(new StringBuilder("nonland card from ").append(playerName).append(" library").toString())); TargetCardInLibrary target = new TargetCardInLibrary(new FilterNonlandCard(new StringBuilder("nonland card from ").append(playerName).append(" library").toString()));
if (controller.searchLibrary(target, game, playerId)) { if (controller.searchLibrary(target, game, playerId, !checkList.contains(playerId))) {
checkList.add(playerId);
UUID targetId = target.getFirstTarget(); UUID targetId = target.getFirstTarget();
Card card = player.getLibrary().remove(targetId, game); Card card = player.getLibrary().remove(targetId, game);
if (card != null) { if (card != null) {
controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); controller.moveCardsToExile(card, source, game, true, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getName());
playerList.remove(playerId);
} }
} else {
playerList.remove(playerId);
} }
} else {
playerList.remove(playerId);
}
} else {
break;
}
playerList.stream().map((playerId) -> game.getPlayer(playerId)).filter((player) -> (player == null
|| !player.canRespond())).forEachOrdered((player) -> {
playerList.remove(player.getId());
});
}
checkList.stream().map((playerId) -> game.getPlayer(playerId)).filter((player) -> (player != null)).forEachOrdered((player) -> {
player.shuffleLibrary(source, game); player.shuffleLibrary(source, game);
} });
ExileZone jaceExileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); ExileZone jaceExileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
if (jaceExileZone == null) { if (jaceExileZone == null) {
return true; return true;
} }
FilterCard filter = new FilterCard("card to cast without mana costs"); FilterCard filter = new FilterCard("card to cast without mana costs");
TargetCardInExile target = new TargetCardInExile(filter, source.getSourceId()); TargetCardInExile target = new TargetCardInExile(filter, source.getSourceId());
while (jaceExileZone.count(filter, game) > 0 && controller.choose(Outcome.PlayForFree, jaceExileZone, target, game)) { while (jaceExileZone.count(filter, game) > 0
&& controller.chooseUse(Outcome.Benefit, "Cast another spell from exile zone for free?", source, game)) {
controller.choose(Outcome.PlayForFree, jaceExileZone, target, game);
Card card = game.getCard(target.getFirstTarget()); Card card = game.getCard(target.getFirstTarget());
if (card != null) { if (card != null) {
if (controller.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game))) { if (controller.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game))) {

View file

@ -0,0 +1,49 @@
package mage.cards.k;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.dynamicvalue.common.TargetConvertedManaCost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventDamageByTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* @author L_J
*/
public final class KryShield extends CardImpl {
public KryShield(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
// {2}, {T}: Prevent all damage that would be dealt this turn by target creature you control. That creature gets +0/+X until end of turn, where X is its converted mana cost.
Effect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn);
effect.setText("Prevent all damage that would be dealt this turn by target creature you control");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(2));
ability.addEffect(new BoostTargetEffect(new StaticValue(0), new TargetConvertedManaCost(), Duration.EndOfTurn, true)
.setText("That creature gets +0/+X until end of turn, where X is its converted mana cost"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
public KryShield(final KryShield card) {
super(card);
}
@Override
public KryShield copy() {
return new KryShield(this);
}
}

View file

@ -0,0 +1,130 @@
package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.StateTriggeredAbility;
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.TokenImpl;
/**
*
* @author jeffwadsworth
*/
public final class LurkingJackals extends CardImpl {
public LurkingJackals(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}");
// When an opponent has 10 or less life, if Lurking Jackals is an enchantment, it becomes a 3/2 Hound creature.
this.addAbility(new LurkingJackalsStateTriggeredAbility());
}
public LurkingJackals(final LurkingJackals card) {
super(card);
}
@Override
public LurkingJackals copy() {
return new LurkingJackals(this);
}
}
class LurkingJackalsStateTriggeredAbility extends StateTriggeredAbility {
public LurkingJackalsStateTriggeredAbility() {
super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new LurkingJackalsToken(), "", Duration.Custom, true, false));
}
public LurkingJackalsStateTriggeredAbility(final LurkingJackalsStateTriggeredAbility ability) {
super(ability);
}
@Override
public LurkingJackalsStateTriggeredAbility copy() {
return new LurkingJackalsStateTriggeredAbility(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (game.getOpponents(getControllerId()) != null) {
for (UUID opponentId : game.getOpponents(getControllerId())) {
if (game.getPlayer(opponentId).getLife() <= 10) {
return true;
}
}
}
return false;
}
@Override
public boolean checkInterveningIfClause(Game game) {
if (getSourcePermanentIfItStillExists(game) != null) {
return getSourcePermanentIfItStillExists(game).isEnchantment();
}
return false;
}
@Override
public boolean canTrigger(Game game) {
//20100716 - 603.8
Boolean triggered = (Boolean) game.getState().getValue(getSourceId().toString() + "triggered");
if (triggered == null) {
triggered = Boolean.FALSE;
}
return !triggered;
}
@Override
public void trigger(Game game, UUID controllerId) {
//20100716 - 603.8
game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.TRUE);
super.trigger(game, controllerId);
}
@Override
public boolean resolve(Game game) {
//20100716 - 603.8
boolean result = super.resolve(game);
game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE);
return result;
}
@Override
public void counter(Game game) {
game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE);
}
@Override
public String getRule() {
return new StringBuilder("When an opponent has 10 or less life, if {this} is an enchantment, ").append(super.getRule()).toString();
}
}
class LurkingJackalsToken extends TokenImpl {
public LurkingJackalsToken() {
super("Hound", "3/2 Hound creature");
cardType.add(CardType.CREATURE);
subtype.add(SubType.HOUND);
power = new MageInt(3);
toughness = new MageInt(2);
}
public LurkingJackalsToken(final LurkingJackalsToken token) {
super(token);
}
@Override
public LurkingJackalsToken copy() {
return new LurkingJackalsToken(this);
}
}

View file

@ -0,0 +1,47 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.EnchantedSourceCondition;
import mage.abilities.decorator.ConditionalRestrictionEffect;
import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
/**
*
* @author jeffwadsworth
*/
public final class MetathranElite extends CardImpl {
private static final String rule = "{this} is unblockable as long as it's enchanted.";
public MetathranElite(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}");
this.subtype.add(SubType.METATHRAN);
this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Metathran Elite is unblockable as long as it's enchanted.
ConditionalRestrictionEffect effect = new ConditionalRestrictionEffect(
new CantBeBlockedSourceEffect(), new EnchantedSourceCondition());
effect.setText(rule);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
}
public MetathranElite(final MetathranElite card) {
super(card);
}
@Override
public MetathranElite copy() {
return new MetathranElite(this);
}
}

View file

@ -1,17 +1,10 @@
package mage.cards.m; package mage.cards.m;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.Card; import mage.cards.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.filter.FilterCard; import mage.filter.FilterCard;
@ -20,8 +13,11 @@ import mage.players.Player;
import mage.target.Target; import mage.target.Target;
import mage.target.common.TargetDiscard; import mage.target.common.TargetDiscard;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class MindBomb extends CardImpl { public final class MindBomb extends CardImpl {
@ -67,6 +63,7 @@ class MindBombEffect extends OneShotEffect {
if (controller != null && sourceObject != null) { if (controller != null && sourceObject != null) {
Map<UUID, Cards> cardsToDiscard = new HashMap<>(); Map<UUID, Cards> cardsToDiscard = new HashMap<>();
// choose
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null) { if (player != null) {
@ -77,6 +74,8 @@ class MindBombEffect extends OneShotEffect {
cardsToDiscard.put(playerId, cards); cardsToDiscard.put(playerId, cards);
} }
} }
// discard
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null) { if (player != null) {
@ -91,31 +90,17 @@ class MindBombEffect extends OneShotEffect {
} }
} }
} }
// damage
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null) { if (player != null) {
Cards cardsPlayer = cardsToDiscard.get(playerId); Cards cardsPlayer = cardsToDiscard.get(playerId);
if (cardsPlayer != null && !cardsPlayer.isEmpty()) { if (cardsPlayer != null) {
player.damage(3 - cardsPlayer.size(), source.getId(), game, false, true); player.damage(3 - cardsPlayer.size(), source.getId(), game, false, true);
} }
} }
} }
// reveal the searched lands, put in hands, and shuffle
// for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
// Player player = game.getPlayer(playerId);
// if (player != null) {
// Cards cardsPlayer = cardsToReveal.get(playerId);
// if (cardsPlayer != null) {
// for (UUID cardId : cardsPlayer) {
// Cards cards = new CardsImpl(game.getCard(cardId));
// Card card = game.getCard(cardId);
// player.revealCards(sourceObject.getIdName() + " (" + player.getName() + ')', cards, game);
// player.moveCards(card, Zone.HAND, source, game);
// player.shuffleLibrary(source, game);
// }
// }
// }
// }
return true; return true;
} }
return false; return false;

View file

@ -10,10 +10,11 @@ import mage.constants.*;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.players.Player; import mage.players.Player;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.AsThoughManaEffect;
import mage.players.ManaPoolItem;
/** /**
* @author TheElk801 * @author TheElk801
@ -69,17 +70,18 @@ class MnemonicBetrayalExileEffect extends OneShotEffect {
} }
Cards cards = new CardsImpl(); Cards cards = new CardsImpl();
Map<UUID, Integer> cardMap = new HashMap(); Map<UUID, Integer> cardMap = new HashMap();
for (UUID playerId : game.getOpponents(source.getControllerId())) { game.getOpponents(source.getControllerId()).stream().map((playerId) -> game.getPlayer(playerId)).filter((player) -> (player != null)).forEachOrdered((player) -> {
Player player = game.getPlayer(playerId);
if (player != null) {
cards.addAll(player.getGraveyard()); cards.addAll(player.getGraveyard());
} });
} cards.getCards(game).stream().map((card) -> {
for (Card card : cards.getCards(game)) {
cardMap.put(card.getId(), card.getZoneChangeCounter(game)); cardMap.put(card.getId(), card.getZoneChangeCounter(game));
return card;
}).map((card) -> {
game.addEffect(new MnemonicBetrayalCastFromExileEffect(card, game), source); game.addEffect(new MnemonicBetrayalCastFromExileEffect(card, game), source);
return card;
}).forEachOrdered((card) -> {
game.addEffect(new MnemonicBetrayalAnyColorEffect(card, game), source); game.addEffect(new MnemonicBetrayalAnyColorEffect(card, game), source);
} });
controller.moveCardsToExile(cards.getCards(game), source, game, true, source.getSourceId(), source.getSourceObjectIfItStillExists(game).getName()); controller.moveCardsToExile(cards.getCards(game), source, game, true, source.getSourceId(), source.getSourceObjectIfItStillExists(game).getName());
game.addDelayedTriggeredAbility(new MnemonicBetrayalDelayedTriggeredAbility(cards, cardMap), source); game.addDelayedTriggeredAbility(new MnemonicBetrayalDelayedTriggeredAbility(cards, cardMap), source);
return true; return true;
@ -125,7 +127,7 @@ class MnemonicBetrayalCastFromExileEffect extends AsThoughEffectImpl {
} }
} }
class MnemonicBetrayalAnyColorEffect extends AsThoughEffectImpl { class MnemonicBetrayalAnyColorEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
private final Card card; private final Card card;
private final int zoneCounter; private final int zoneCounter;
@ -154,13 +156,21 @@ class MnemonicBetrayalAnyColorEffect extends AsThoughEffectImpl {
@Override @Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (card.getZoneChangeCounter(game) != zoneCounter) { if (objectId.equals(card.getId())
&& card.getZoneChangeCounter(game) <= zoneCounter + 1
&& affectedControllerId.equals(source.getControllerId())) {
return true;
} else {
if (objectId.equals(card.getId())) {
this.discard(); this.discard();
}
}
return false; return false;
} }
return objectId.equals(card.getId())
&& card.getZoneChangeCounter(game) == zoneCounter @Override
&& affectedControllerId.equals(source.getControllerId()); public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
return mana.getFirstAvailable();
} }
} }
@ -240,12 +250,10 @@ class MnemonicBetrayalReturnEffect extends OneShotEffect {
return false; return false;
} }
Cards cardsToReturn = new CardsImpl(); Cards cardsToReturn = new CardsImpl();
for (Card card : cards.getCards(game)) { cards.getCards(game).stream().filter((card) -> (game.getState().getZone(card.getId()) == Zone.EXILED
if (game.getState().getZone(card.getId()) == Zone.EXILED && card.getZoneChangeCounter(game) == cardMap.getOrDefault(card.getId(), -5) + 1)).forEachOrdered((card) -> {
&& card.getZoneChangeCounter(game) == cardMap.getOrDefault(card.getId(), -5) + 1) {
cardsToReturn.add(card); cardsToReturn.add(card);
} });
}
return player.moveCards(cardsToReturn, Zone.GRAVEYARD, source, game); return player.moveCards(cardsToReturn, Zone.GRAVEYARD, source, game);
} }
} }

View file

@ -0,0 +1,60 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.target.TargetPlayer;
/**
*
* @author jeffwadsworth
*/
public final class MoggBombers extends CardImpl {
private static final String rule = "When another creature enters the battlefield, sacrifice {this} and it deals 3 damage to target player.";
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature");
static {
filter.add(new AnotherPredicate());
}
public MoggBombers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.GOBLIN);
this.power = new MageInt(3);
this.toughness = new MageInt(4);
// When another creature enters the battlefield, sacrifice Mogg Bombers and it deals 3 damage to target player.
Effect sacrificeMoggBombers = new SacrificeSourceEffect();
Effect damageTargetPlayer = new DamageTargetEffect(3);
Ability ability = new EntersBattlefieldAllTriggeredAbility(
Zone.BATTLEFIELD,
sacrificeMoggBombers,
filter, false, rule);
ability.addEffect(damageTargetPlayer);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
public MoggBombers(final MoggBombers card) {
super(card);
}
@Override
public MoggBombers copy() {
return new MoggBombers(this);
}
}

View file

@ -1,11 +1,11 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.common.SkipNextCombatEffect; import mage.abilities.effects.common.SkipCombatStepEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
/** /**
@ -15,10 +15,10 @@ import mage.target.TargetPlayer;
public final class MomentOfSilence extends CardImpl { public final class MomentOfSilence extends CardImpl {
public MomentOfSilence(UUID ownerId, CardSetInfo setInfo) { public MomentOfSilence(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
// Target player skips their next combat phase this turn. // Target player skips their next combat phase this turn.
this.getSpellAbility().addEffect(new SkipNextCombatEffect()); this.getSpellAbility().addEffect(new SkipCombatStepEffect(Duration.EndOfTurn).setText("Target player skips their next combat this turn"));
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
} }

View file

@ -54,12 +54,18 @@ class OpalAvengerStateTriggeredAbility extends StateTriggeredAbility {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
if (game.getState().getPlayer(getControllerId()) != null) {
return game.getState().getPlayer(getControllerId()).getLife() <= 10; return game.getState().getPlayer(getControllerId()).getLife() <= 10;
} }
return false;
}
@Override @Override
public boolean checkInterveningIfClause(Game game) { public boolean checkInterveningIfClause(Game game) {
return this.getSourcePermanentIfItStillExists(game).getCardType().contains(CardType.ENCHANTMENT); if (getSourcePermanentIfItStillExists(game) != null) {
return getSourcePermanentIfItStillExists(game).isEnchantment();
}
return false;
} }
@Override @Override

View file

@ -1,4 +1,3 @@
package mage.cards.o; package mage.cards.o;
import java.util.UUID; import java.util.UUID;
@ -30,12 +29,13 @@ public final class OuterRimSlaver extends CardImpl {
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
// When Outer Rim Slaver enters the battlefield, you may put a bounty counter on target creature. If you do, another target creature fights that creature // When Outer Rim Slaver enters the battlefield, you may put a bounty counter on target creature. If you do, another target creature fights that creature
Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()), true); Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance())
ability.addEffect(new FightTargetsEffect("another target creature fights that creature")); .setText("you may put a bounty counter on target creature"), true);
TargetCreaturePermanent target = new TargetCreaturePermanent(); ability.addEffect(new FightTargetsEffect("If you do, another target creature fights that creature"));
TargetCreaturePermanent target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature to put a bounty counter on it"));
target.setTargetTag(1); target.setTargetTag(1);
ability.addTarget(target); ability.addTarget(target);
FilterCreaturePermanent filter = new FilterCreaturePermanent(); FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature to fight that creature that gets the bounty counter");
filter.add(new AnotherTargetPredicate(2)); filter.add(new AnotherTargetPredicate(2));
TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter);
target2.setTargetTag(2); target2.setTargetTag(2);

View file

@ -0,0 +1,60 @@
package mage.cards.p;
import java.util.UUID;
import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.DiesAttachedTriggeredAbility;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType;
/**
*
* @author jeffwadsworth
*/
public final class PrivateResearch extends CardImpl {
private static final String rule = "draw a card for each page counter on {this}.";
public PrivateResearch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// At the beginning of your upkeep, you may put a page counter on Private Research.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD,
new AddCountersSourceEffect(CounterType.PAGE.createInstance(), true), TargetController.YOU, true));
// When enchanted creature dies, draw a card for each page counter on Private Research.
this.addAbility(new DiesAttachedTriggeredAbility(new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.PAGE)).setText(rule), "enchanted creature"));
}
public PrivateResearch(final PrivateResearch card) {
super(card);
}
@Override
public PrivateResearch copy() {
return new PrivateResearch(this);
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.p; package mage.cards.p;
import java.util.UUID; import java.util.UUID;
@ -11,8 +10,8 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -26,7 +25,7 @@ import mage.target.common.TargetControlledPermanent;
public final class ProwlingPangolin extends CardImpl { public final class ProwlingPangolin extends CardImpl {
public ProwlingPangolin(UUID ownerId, CardSetInfo setInfo) { public ProwlingPangolin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.subtype.add(SubType.BEAST, SubType.PANGOLIN); this.subtype.add(SubType.BEAST, SubType.PANGOLIN);
this.power = new MageInt(6); this.power = new MageInt(6);
this.toughness = new MageInt(5); this.toughness = new MageInt(5);

View file

@ -1,4 +1,3 @@
package mage.cards.r; package mage.cards.r;
import java.util.UUID; import java.util.UUID;
@ -8,12 +7,13 @@ import mage.abilities.common.CantBlockAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.ManaWasSpentCondition; import mage.abilities.condition.common.ManaWasSpentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.SkipNextCombatEffect; import mage.abilities.effects.common.SkipCombatStepEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.ColoredManaSymbol; import mage.constants.ColoredManaSymbol;
import mage.constants.Duration;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import mage.watchers.common.ManaSpentToCastWatcher; import mage.watchers.common.ManaSpentToCastWatcher;
@ -24,13 +24,13 @@ import mage.watchers.common.ManaSpentToCastWatcher;
public final class RevenantPatriarch extends CardImpl { public final class RevenantPatriarch extends CardImpl {
public RevenantPatriarch(UUID ownerId, CardSetInfo setInfo) { public RevenantPatriarch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
this.subtype.add(SubType.SPIRIT); this.subtype.add(SubType.SPIRIT);
this.power = new MageInt(4); this.power = new MageInt(4);
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
// When Revenant Patriarch enters the battlefield, if {W} was spent to cast it, target player skips their next combat phase. // When Revenant Patriarch enters the battlefield, if {W} was spent to cast it, target player skips their next combat phase.
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new SkipNextCombatEffect(), false); TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new SkipCombatStepEffect(Duration.OneUse).setText("target player skips their next combat phase."), false);
ability.addTarget(new TargetPlayer()); ability.addTarget(new TargetPlayer());
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.W), this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.W),
"if {W} was spent to cast it, target player skips their next combat phase."), new ManaSpentToCastWatcher()); "if {W} was spent to cast it, target player skips their next combat phase."), new ManaSpentToCastWatcher());

View file

@ -0,0 +1,105 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetSpell;
/**
*
* @author L_J
*/
public final class Reverberation extends CardImpl {
private static final FilterSpell filter = new FilterSpell("sorcery spell");
static {
filter.add(new CardTypePredicate(CardType.SORCERY));
}
public Reverberation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
// All damage that would be dealt this turn by target sorcery spell is dealt to that spells controller instead.
this.getSpellAbility().addEffect(new ReverberationEffect());
this.getSpellAbility().addTarget(new TargetSpell(filter));
}
public Reverberation(final Reverberation card) {
super(card);
}
@Override
public Reverberation copy() {
return new Reverberation(this);
}
}
class ReverberationEffect extends ReplacementEffectImpl {
public ReverberationEffect() {
super(Duration.EndOfTurn, Outcome.RedirectDamage);
staticText = "All damage that would be dealt this turn by target sorcery spell is dealt to that spells controller instead";
}
public ReverberationEffect(final ReverberationEffect effect) {
super(effect);
}
@Override
public ReverberationEffect copy() {
return new ReverberationEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGE_CREATURE ||
event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER ||
event.getType() == GameEvent.EventType.DAMAGE_PLAYER;
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
DamageEvent damageEvent = (DamageEvent) event;
if (controller != null) {
Spell targetSpell = game.getStack().getSpell(source.getFirstTarget());
if (targetSpell != null) {
Player targetsController = game.getPlayer(targetSpell.getControllerId());
if (targetsController != null) {
targetsController.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects());
return true;
}
}
}
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
DamageEvent damageEvent = (DamageEvent) event;
Spell targetSpell = game.getStack().getSpell(source.getFirstTarget());
if (targetSpell != null) {
return damageEvent.getAmount() > 0;
}
return false;
}
}

View file

@ -0,0 +1,87 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.ChoiceColor;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
/**
*
* @author jeffwadsworth
*/
public final class ScryingGlass extends CardImpl {
public ScryingGlass(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// {3}, {tap}: Choose a number greater than 0 and a color. Target opponent reveals his or her hand. If that opponent reveals exactly the chosen number of cards of the chosen color, you draw a card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScryingGlassEffect(), new ManaCostsImpl("{3}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
public ScryingGlass(final ScryingGlass card) {
super(card);
}
@Override
public ScryingGlass copy() {
return new ScryingGlass(this);
}
}
class ScryingGlassEffect extends OneShotEffect {
public ScryingGlassEffect() {
super(Outcome.Neutral);
staticText = "Choose a number greater than 0 and a color. Target opponent reveals his or her hand. If that opponent reveals exactly the chosen number of cards of the chosen color, you draw a card";
}
public ScryingGlassEffect(final ScryingGlassEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player targetOpponent = game.getPlayer(source.getFirstTarget());
ChoiceColor color = new ChoiceColor();
int amount = 0;
if (controller != null
&& targetOpponent != null) {
amount = controller.getAmount(1, Integer.MAX_VALUE, "Choose a number", game);
controller.choose(Outcome.Discard, color, game);
FilterCard filter = new FilterCard();
filter.add(new ColorPredicate(color.getColor()));
targetOpponent.revealCards(source, targetOpponent.getHand(), game);
if (targetOpponent.getHand().count(filter, game) == amount) {
game.informPlayers(controller.getName() + " has chosen the exact number and color of the revealed cards from " + targetOpponent.getName() + "'s hand. They draw a card.");
controller.drawCards(1, game);
return true;
} else {
game.informPlayers(controller.getName() + " has chosen incorrectly and will not draw a card.");
}
}
return false;
}
@Override
public ScryingGlassEffect copy() {
return new ScryingGlassEffect(this);
}
}

View file

@ -0,0 +1,129 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.RegenerateSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
*
* @author jeffwadsworth
*/
public final class SkeletonScavengers extends CardImpl {
public SkeletonScavengers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.SKELETON);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// Skeleton Scavengers enters the battlefield with a +1/+1 counter on it.
this.addAbility(new AsEntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())));
// Pay {1} for each +1/+1 counter on Skeleton Scavengers: Regenerate Skeleton Scavengers. When it regenerates this way, put a +1/+1 counter on it.
this.addAbility(new SimpleActivatedAbility(new SkeletonScavengersEffect(), new DynamicValueGenericManaCost(new CountersSourceCount(CounterType.P1P1))));
}
public SkeletonScavengers(final SkeletonScavengers card) {
super(card);
}
@Override
public SkeletonScavengers copy() {
return new SkeletonScavengers(this);
}
}
class DynamicValueGenericManaCost extends CostImpl {
DynamicValue amount;
public DynamicValueGenericManaCost(DynamicValue amount) {
this.amount = amount;
setText();
}
public DynamicValueGenericManaCost(DynamicValueGenericManaCost cost) {
super(cost);
this.amount = cost.amount;
}
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
Player controller = game.getPlayer(controllerId);
if (controller == null) {
return false;
}
int convertedCost = amount.calculate(game, ability, null);
Cost cost = new GenericManaCost(convertedCost);
return cost.canPay(ability, sourceId, controllerId, game);
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
Player controller = game.getPlayer(controllerId);
int convertedCost = amount.calculate(game, ability, null);
Cost cost = new GenericManaCost(convertedCost);
if (controller != null) {
paid = cost.pay(ability, game, sourceId, controllerId, noMana);
}
return paid;
}
@Override
public DynamicValueGenericManaCost copy() {
return new DynamicValueGenericManaCost(this);
}
private void setText() {
text = ("Pay {1} for each +1/+1 counter on {this}");
}
}
class SkeletonScavengersEffect extends OneShotEffect {
SkeletonScavengersEffect() {
super(Outcome.Benefit);
this.staticText = "Regenerate {this}. When it regenerates this way, put a +1/+1 counter on it";
}
SkeletonScavengersEffect(final SkeletonScavengersEffect effect) {
super(effect);
}
@Override
public SkeletonScavengersEffect copy() {
return new SkeletonScavengersEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent skeletonScavengers = game.getPermanent(source.getSourceId());
if (skeletonScavengers != null) {
if (new RegenerateSourceEffect().apply(game, source)) {
return new AddCountersSourceEffect(CounterType.P1P1.createInstance()).apply(game, source);
}
}
return false;
}
}

View file

@ -1,6 +1,5 @@
package mage.cards.s; package mage.cards.s;
import mage.abilities.costs.mana.VariableManaCost;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DoUnlessAnyPlayerPaysEffect; import mage.abilities.effects.common.DoUnlessAnyPlayerPaysEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
@ -11,6 +10,7 @@ import mage.filter.common.FilterCreatureCard;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID; import java.util.UUID;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
/** /**
* @author jmharmon * @author jmharmon
@ -23,8 +23,7 @@ public final class SoulStrings extends CardImpl {
// Return two target creature cards from your graveyard to your hand unless any player pays {X}. // Return two target creature cards from your graveyard to your hand unless any player pays {X}.
Effect effect = new DoUnlessAnyPlayerPaysEffect( Effect effect = new DoUnlessAnyPlayerPaysEffect(
new ReturnFromGraveyardToHandTargetEffect(), new VariableManaCost() new ReturnFromGraveyardToHandTargetEffect(), new ManacostVariableValue());
);
this.getSpellAbility().addEffect(effect); this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(2, new FilterCreatureCard("creature cards from your graveyard"))); this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(2, new FilterCreatureCard("creature cards from your graveyard")));
} }

View file

@ -1,4 +1,3 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID; import java.util.UUID;
@ -65,21 +64,22 @@ class StadiumVendorsEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId());
if (controller == null) { if (controller == null) {
return false; return false;
} }
TargetPlayer target = new TargetPlayer(1, 1, true); TargetPlayer target = new TargetPlayer(1, 1, true);
if (!controller.choose(Outcome.Benefit, target, source.getSourceId(), game)) { if (controller.choose(Outcome.Benefit, target, source.getSourceId(), game)) {
return false;
}
Player player = game.getPlayer(target.getFirstTarget()); Player player = game.getPlayer(target.getFirstTarget());
ChoiceColor colorChoice = new ChoiceColor(true); ChoiceColor colorChoice = new ChoiceColor(true);
if (player == null || !player.choose(Outcome.Benefit, colorChoice, game)) { if (player == null
|| !player.choose(Outcome.Benefit, colorChoice, game)) {
return false; return false;
} }
Effect effect = new AddManaToManaPoolTargetControllerEffect(colorChoice.getMana(2), "that player's"); Effect effect = new AddManaToManaPoolTargetControllerEffect(colorChoice.getMana(2), "that player's");
effect.setTargetPointer(new FixedTarget(player.getId(), game)); effect.setTargetPointer(new FixedTarget(player.getId(), game));
return effect.apply(game, source); return effect.apply(game, source);
} }
return false;
}
} }

View file

@ -1,14 +1,14 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.SkipNextCombatEffect; import mage.abilities.effects.common.SkipCombatStepEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import mage.target.common.TargetOpponent; import mage.target.common.TargetOpponent;
@ -19,7 +19,7 @@ import mage.target.common.TargetOpponent;
public final class StonehornDignitary extends CardImpl { public final class StonehornDignitary extends CardImpl {
public StonehornDignitary(UUID ownerId, CardSetInfo setInfo) { public StonehornDignitary(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.RHINO); this.subtype.add(SubType.RHINO);
this.subtype.add(SubType.SOLDIER); this.subtype.add(SubType.SOLDIER);
@ -27,7 +27,7 @@ public final class StonehornDignitary extends CardImpl {
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// When Stonehorn Dignitary enters the battlefield, target opponent skips their next combat phase. // When Stonehorn Dignitary enters the battlefield, target opponent skips their next combat phase.
Ability ability = new EntersBattlefieldTriggeredAbility(new SkipNextCombatEffect()); Ability ability = new EntersBattlefieldTriggeredAbility(new SkipCombatStepEffect(Duration.OneUse).setText("target opponent skips their next combat phase."));
ability.addTarget(new TargetOpponent()); ability.addTarget(new TargetOpponent());
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -0,0 +1,39 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.dynamicvalue.common.TargetConvertedManaCost;
import mage.abilities.effects.common.PreventDamageByTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author L_J
*/
public final class Subdue extends CardImpl {
public Subdue(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}");
// Prevent all combat damage that would be dealt by target creature this turn. That creature gets +0/+X until end of turn, where X is its converted mana cost.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true));
this.getSpellAbility().addEffect(new BoostTargetEffect(new StaticValue(0), new TargetConvertedManaCost(), Duration.EndOfTurn, true)
.setText("That creature gets +0/+X until end of turn, where X is its converted mana cost"));
}
public Subdue(final Subdue card) {
super(card);
}
@Override
public Subdue copy() {
return new Subdue(this);
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.t; package mage.cards.t;
import java.util.UUID; import java.util.UUID;
@ -13,7 +12,6 @@ import mage.constants.SagaChapter;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.CardTypePredicate;
@ -35,6 +33,7 @@ public final class TheEldestReborn extends CardImpl {
} }
private static final FilterControlledPermanent filterSacrifice = new FilterControlledPermanent("creature or planeswalker"); private static final FilterControlledPermanent filterSacrifice = new FilterControlledPermanent("creature or planeswalker");
static { static {
filterSacrifice.add(Predicates.or( filterSacrifice.add(Predicates.or(
new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.CREATURE),

View file

@ -67,7 +67,10 @@ class VeiledCrocodileStateTriggeredAbility extends StateTriggeredAbility {
@Override @Override
public boolean checkInterveningIfClause(Game game) { public boolean checkInterveningIfClause(Game game) {
return this.getSourcePermanentIfItStillExists(game).getCardType().contains(CardType.ENCHANTMENT); if (getSourcePermanentIfItStillExists(game) != null) {
return getSourcePermanentIfItStillExists(game).isEnchantment();
}
return false;
} }
@Override @Override

View file

@ -79,7 +79,9 @@ class ViashinoBeyEffect extends OneShotEffect {
} else { } else {
targetDefender.add(game.getOpponents(controller.getId()).iterator().next(), game); targetDefender.add(game.getOpponents(controller.getId()).iterator().next(), game);
} }
if (permanent.canAttack(targetDefender.getFirstTarget(), game)) {
controller.declareAttacker(permanent.getId(), targetDefender.getFirstTarget(), game, false); controller.declareAttacker(permanent.getId(), targetDefender.getFirstTarget(), game, false);
}
}); });
} }
return false; return false;

View file

@ -0,0 +1,59 @@
package mage.cards.w;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.OpponentControlsPermanentCondition;
import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
import mage.abilities.effects.ContinuousRuleModifyingEffect;
import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect;
import mage.abilities.keyword.CantBeBlockedSourceAbility;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
/**
*
* @author jeffwadsworth
*/
public final class WalkingDream extends CardImpl {
private static final String rule = "{this} doesn't untap during your untap step if an opponent controls two or more creatures.";
public WalkingDream(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.ILLUSION);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Walking Dream is unblockable.
this.addAbility(new CantBeBlockedSourceAbility());
// Walking Dream doesn't untap during your untap step if an opponent controls two or more creatures.
ContinuousRuleModifyingEffect dontUntap = new DontUntapInControllersUntapStepSourceEffect(false, true);
dontUntap.setText(rule);
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD,
new ConditionalContinuousRuleModifyingEffect(
dontUntap,
new OpponentControlsPermanentCondition(
new FilterCreaturePermanent(),
ComparisonType.MORE_THAN, 1)));
this.addAbility(ability);
}
public WalkingDream(final WalkingDream card) {
super(card);
}
@Override
public WalkingDream copy() {
return new WalkingDream(this);
}
}

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