Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Count Andromalius 2018-03-17 10:56:50 -03:00
commit 17db6f5345
67 changed files with 1059 additions and 548 deletions

View file

@ -613,7 +613,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
}
}
private static MagePane getTopMost(MagePane exclude) {
public static MagePane getTopMost(MagePane exclude) {
MagePane topmost = null;
int best = Integer.MAX_VALUE;
for (Component frame : desktopPane.getComponentsInLayer(JLayeredPane.DEFAULT_LAYER)) {

View file

@ -3,6 +3,7 @@ package mage.client.components;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
@ -40,6 +41,7 @@ public class HoverButton extends JPanel implements MouseListener {
private String topText;
private Image topTextImage;
private Image topTextImageRight;
private String centerText;
private boolean isHovered = false;
private boolean isSelected = false;
@ -49,12 +51,15 @@ public class HoverButton extends JPanel implements MouseListener {
private Command observer = null;
private Command onHover = null;
private Color textColor = Color.white;
private final Rectangle centerTextArea = new Rectangle(5, 18, 75, 40);
private final Color centerTextColor = Color.YELLOW;
private final Color textBGColor = Color.black;
static final Font textFont = new Font("Arial", Font.PLAIN, 12);
static final Font textFontMini = new Font("Arial", Font.PLAIN, 11);
static final Font textSetFontBoldMini = new Font("Arial", Font.BOLD, 12);
static final Font textSetFontBold = new Font("Arial", Font.BOLD, 14);
private boolean useMiniFont = false;
private boolean alignTextLeft = false;
@ -134,6 +139,21 @@ public class HoverButton extends JPanel implements MouseListener {
if (topTextImageRight != null) {
g.drawImage(topTextImageRight, this.getWidth() - 20, 3, this);
}
if (centerText != null) {
g2d.setColor(centerTextColor);
int fontSize = 40;
int val = Integer.parseInt(centerText);
if (val > 9999) {
fontSize = 24;
} else if (val > 999) {
fontSize = 28;
} else if (val > 99) {
fontSize = 34;
}
drawCenteredString(g2d, centerText, centerTextArea, new Font("Arial", Font.BOLD, fontSize));
}
g2d.setColor(textColor);
if (overlayImage != null) {
g.drawImage(overlayImage, (imageSize.width - overlayImageSize.width) / 2, 10, this);
} else if (set != null) {
@ -298,13 +318,17 @@ public class HoverButton extends JPanel implements MouseListener {
public void setTopTextImage(Image topTextImage) {
this.topTextImage = topTextImage;
this.textOffsetX = -1; // rest for new clculation
this.textOffsetX = -1; // rest for new calculation
}
public void setTopTextImageRight(Image topTextImage) {
this.topTextImageRight = topTextImage;
}
public void setCenterText(String centerText) {
this.centerText = centerText;
}
public void setTextAlwaysVisible(boolean textAlwaysVisible) {
this.textAlwaysVisible = textAlwaysVisible;
}
@ -313,4 +337,24 @@ public class HoverButton extends JPanel implements MouseListener {
this.alignTextLeft = alignTextLeft;
}
/**
* Draw a String centered in the middle of a Rectangle.
*
* @param g The Graphics instance.
* @param text The String to draw.
* @param rect The Rectangle to center the text in.
* @param font
*/
public void drawCenteredString(Graphics g, String text, Rectangle rect, Font font) {
// Get the FontMetrics
FontMetrics metrics = g.getFontMetrics(font);
// Determine the X coordinate for the text
int x = rect.x + (rect.width - metrics.stringWidth(text)) / 2;
// Determine the Y coordinate for the text (note we add the ascent, as in java 2d 0 is top of the screen)
int y = rect.y + ((rect.height - metrics.getHeight()) / 2) + metrics.getAscent();
// Set the font
g.setFont(font);
// Draw the String
g.drawString(text, x, y);
}
}

View file

@ -7,6 +7,11 @@
<Property name="text" type="java.lang.String" value="jButton2"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" value="jLabel1"/>
</Properties>
</Component>
</NonVisualComponents>
<Properties>
<Property name="title" type="java.lang.String" value="Add Land"/>
@ -29,40 +34,62 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblMountain" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblForest" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblLandSet" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblIsland" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblPains" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblSwamp" alignment="1" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblMountain" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lblForest" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblLandSet" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblIsland" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblPains" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="lblSwamp" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lblDeckSize" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="ckbFullArtLands" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Component id="btnAutoAdd" alignment="0" pref="85" max="32767" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
<Component id="spnMountain" alignment="0" pref="85" max="32767" attributes="0"/>
<Component id="spnIsland" alignment="0" pref="85" max="32767" attributes="0"/>
<Component id="spnForest" alignment="0" max="32767" attributes="0"/>
</Group>
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
<Component id="spnSwamp" alignment="0" pref="85" max="32767" attributes="0"/>
<Component id="spnPlains" alignment="0" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="btnAdd" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Component id="ckbFullArtLands" min="-2" max="-2" attributes="0"/>
<Component id="panelSet" min="-2" pref="219" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="spnForest" min="-2" pref="50" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblForestIcon" min="-2" pref="20" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="spnIsland" min="-2" pref="50" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblIslandIcon" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="spnMountain" min="-2" pref="50" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblMountainIcon" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="spnSwamp" min="-2" pref="50" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblSwampIcon" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="spnDeckSize" min="-2" pref="50" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="btnAutoAdd" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnAdd" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="panelSet" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="spnPlains" min="-2" pref="50" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblPlainsIcon" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="36" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
@ -79,35 +106,54 @@
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblForest" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnForest" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblForestIcon" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblIsland" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnIsland" alignment="3" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblIsland" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnIsland" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lblIslandIcon" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblMountain" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnMountain" alignment="3" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblMountain" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnMountain" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lblMountainIcon" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblPains" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnPlains" alignment="3" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblPains" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnPlains" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lblPlainsIcon" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblSwamp" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnSwamp" alignment="3" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lblSwamp" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnSwamp" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lblSwampIcon" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="ckbFullArtLands" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnAutoAdd" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lblDeckSize" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spnDeckSize" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnAdd" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnCancel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -120,7 +166,7 @@
</Component>
<Component class="javax.swing.JLabel" name="lblForest">
<Properties>
<Property name="text" type="java.lang.String" value="Forest"/>
<Property name="text" type="java.lang.String" value="Forest:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spnForest">
@ -130,9 +176,23 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblForestIcon">
<Properties>
<Property name="toolTipText" type="java.lang.String" value=""/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblIsland">
<Properties>
<Property name="text" type="java.lang.String" value="Island"/>
<Property name="text" type="java.lang.String" value="Island:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spnIsland">
@ -142,9 +202,22 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblIslandIcon">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblMountain">
<Properties>
<Property name="text" type="java.lang.String" value="Mountain"/>
<Property name="text" type="java.lang.String" value="Mountain:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spnMountain">
@ -154,9 +227,22 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblMountainIcon">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblPains">
<Properties>
<Property name="text" type="java.lang.String" value="Plains"/>
<Property name="text" type="java.lang.String" value="Plains:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spnPlains">
@ -166,9 +252,22 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblPlainsIcon">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblSwamp">
<Properties>
<Property name="text" type="java.lang.String" value="Swamp"/>
<Property name="text" type="java.lang.String" value="Swamp:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spnSwamp">
@ -178,9 +277,44 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblSwampIcon">
<Properties>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[22, 20]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblDeckSize">
<Properties>
<Property name="text" type="java.lang.String" value="Deck size:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spnDeckSize">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="0" minimum="0" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnAutoAdd">
<Properties>
<Property name="text" type="java.lang.String" value="Suggest"/>
<Property name="toolTipText" type="java.lang.String" value="&lt;HTML&gt;Propose related to the mana costs of the cards in the deck&lt;br&gt;&#xa;the number of lands to add to get to the set deck size."/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnAutoAddActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnAdd">
<Properties>
<Property name="text" type="java.lang.String" value="Add"/>
<Property name="toolTipText" type="java.lang.String" value="Add the selected number of basic lands to the deck."/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnAddActionPerformed"/>
@ -194,14 +328,6 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCancelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnAutoAdd">
<Properties>
<Property name="text" type="java.lang.String" value="Suggest"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnAutoAddActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JPanel" name="panelSet">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>

View file

@ -27,12 +27,13 @@
*/
package mage.client.dialog;
import java.util.HashSet;
import java.awt.image.BufferedImage;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JLayeredPane;
import mage.Mana;
import mage.cards.Card;
@ -49,6 +50,7 @@ import mage.client.util.gui.FastSearchUtil;
import mage.constants.Rarity;
import mage.util.RandomUtil;
import org.apache.log4j.Logger;
import org.mage.card.arcane.ManaSymbols;
/**
*
@ -59,7 +61,6 @@ public class AddLandDialog extends MageDialog {
private static final Logger logger = Logger.getLogger(MageDialog.class);
private Deck deck;
private final Set<String> landSetCodes = new HashSet<>();
private static final int DEFAULT_SEALED_DECK_CARD_NUMBER = 40;
@ -131,6 +132,27 @@ public class AddLandDialog extends MageDialog {
} else {
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
}
spnDeckSize.setValue(DEFAULT_SEALED_DECK_CARD_NUMBER);
BufferedImage image = ManaSymbols.getSizedManaSymbol("G", 15);
if (image != null) {
lblForestIcon.setIcon(new ImageIcon(image));
}
image = ManaSymbols.getSizedManaSymbol("U", 15);
if (image != null) {
lblIslandIcon.setIcon(new ImageIcon(image));
}
image = ManaSymbols.getSizedManaSymbol("W", 15);
if (image != null) {
lblPlainsIcon.setIcon(new ImageIcon(image));
}
image = ManaSymbols.getSizedManaSymbol("R", 15);
if (image != null) {
lblMountainIcon.setIcon(new ImageIcon(image));
}
image = ManaSymbols.getSizedManaSymbol("B", 15);
if (image != null) {
lblSwampIcon.setIcon(new ImageIcon(image));
}
this.setVisible(true);
}
@ -139,9 +161,7 @@ public class AddLandDialog extends MageDialog {
String landSetName = (String) cbLandSet.getSelectedItem();
CardCriteria criteria = new CardCriteria();
if (landSetName.equals("<Random lands>")) {
criteria.setCodes(landSetCodes.toArray(new String[landSetCodes.size()]));
} else {
if (!landSetName.equals("<Random lands>")) {
ExpansionInfo expansionInfo = ExpansionRepository.instance.getSetByName(landSetName);
if (expansionInfo == null) {
throw new IllegalArgumentException("Code of Set " + landSetName + " not found");
@ -193,20 +213,28 @@ public class AddLandDialog extends MageDialog {
private void initComponents() {
jButton2 = new javax.swing.JButton();
jLabel1 = new javax.swing.JLabel();
lblLandSet = new javax.swing.JLabel();
lblForest = new javax.swing.JLabel();
spnForest = new javax.swing.JSpinner();
lblForestIcon = new javax.swing.JLabel();
lblIsland = new javax.swing.JLabel();
spnIsland = new javax.swing.JSpinner();
lblIslandIcon = new javax.swing.JLabel();
lblMountain = new javax.swing.JLabel();
spnMountain = new javax.swing.JSpinner();
lblMountainIcon = new javax.swing.JLabel();
lblPains = new javax.swing.JLabel();
spnPlains = new javax.swing.JSpinner();
lblPlainsIcon = new javax.swing.JLabel();
lblSwamp = new javax.swing.JLabel();
spnSwamp = new javax.swing.JSpinner();
lblSwampIcon = new javax.swing.JLabel();
lblDeckSize = new javax.swing.JLabel();
spnDeckSize = new javax.swing.JSpinner();
btnAutoAdd = new javax.swing.JButton();
btnAdd = new javax.swing.JButton();
btnCancel = new javax.swing.JButton();
btnAutoAdd = new javax.swing.JButton();
panelSet = new javax.swing.JPanel();
cbLandSet = new javax.swing.JComboBox();
btnSetFastSearch = new javax.swing.JButton();
@ -214,31 +242,67 @@ public class AddLandDialog extends MageDialog {
jButton2.setText("jButton2");
jLabel1.setText("jLabel1");
setTitle("Add Land");
lblLandSet.setText("Set:");
lblForest.setText("Forest");
lblForest.setText("Forest:");
spnForest.setModel(new javax.swing.SpinnerNumberModel(0, 0, null, 1));
lblIsland.setText("Island");
lblForestIcon.setToolTipText("");
lblForestIcon.setMaximumSize(new java.awt.Dimension(22, 20));
lblForestIcon.setMinimumSize(new java.awt.Dimension(22, 20));
lblForestIcon.setPreferredSize(new java.awt.Dimension(22, 20));
lblIsland.setText("Island:");
spnIsland.setModel(new javax.swing.SpinnerNumberModel(0, 0, null, 1));
lblMountain.setText("Mountain");
lblIslandIcon.setMaximumSize(new java.awt.Dimension(22, 20));
lblIslandIcon.setMinimumSize(new java.awt.Dimension(22, 20));
lblIslandIcon.setPreferredSize(new java.awt.Dimension(22, 20));
lblMountain.setText("Mountain:");
spnMountain.setModel(new javax.swing.SpinnerNumberModel(0, 0, null, 1));
lblPains.setText("Plains");
lblMountainIcon.setMaximumSize(new java.awt.Dimension(22, 20));
lblMountainIcon.setMinimumSize(new java.awt.Dimension(22, 20));
lblMountainIcon.setPreferredSize(new java.awt.Dimension(22, 20));
lblPains.setText("Plains:");
spnPlains.setModel(new javax.swing.SpinnerNumberModel(0, 0, null, 1));
lblSwamp.setText("Swamp");
lblPlainsIcon.setMaximumSize(new java.awt.Dimension(22, 20));
lblPlainsIcon.setMinimumSize(new java.awt.Dimension(22, 20));
lblPlainsIcon.setPreferredSize(new java.awt.Dimension(22, 20));
lblSwamp.setText("Swamp:");
spnSwamp.setModel(new javax.swing.SpinnerNumberModel(0, 0, null, 1));
lblSwampIcon.setMaximumSize(new java.awt.Dimension(22, 20));
lblSwampIcon.setMinimumSize(new java.awt.Dimension(22, 20));
lblSwampIcon.setPreferredSize(new java.awt.Dimension(22, 20));
lblDeckSize.setText("Deck size:");
spnDeckSize.setModel(new javax.swing.SpinnerNumberModel(0, 0, null, 1));
btnAutoAdd.setText("Suggest");
btnAutoAdd.setToolTipText("<HTML>Propose related to the mana costs of the cards in the deck<br>\nthe number of lands to add to get to the set deck size.");
btnAutoAdd.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAutoAddActionPerformed(evt);
}
});
btnAdd.setText("Add");
btnAdd.setToolTipText("Add the selected number of basic lands to the deck.");
btnAdd.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAddActionPerformed(evt);
@ -252,13 +316,6 @@ public class AddLandDialog extends MageDialog {
}
});
btnAutoAdd.setText("Suggest");
btnAutoAdd.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAutoAddActionPerformed(evt);
}
});
panelSet.setLayout(new javax.swing.BoxLayout(panelSet, javax.swing.BoxLayout.LINE_AXIS));
cbLandSet.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
@ -285,32 +342,50 @@ public class AddLandDialog extends MageDialog {
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblMountain)
.addComponent(lblForest, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblLandSet, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblIsland, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblPains, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblSwamp, javax.swing.GroupLayout.Alignment.TRAILING))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblMountain)
.addComponent(lblForest, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblLandSet, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblIsland, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblPains, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lblSwamp, javax.swing.GroupLayout.Alignment.TRAILING))
.addComponent(lblDeckSize))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(ckbFullArtLands)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(btnAdd)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel)
.addContainerGap())
.addComponent(ckbFullArtLands)
.addComponent(panelSet, javax.swing.GroupLayout.PREFERRED_SIZE, 219, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addComponent(spnForest, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblForestIcon, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(spnIsland, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblIslandIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(spnMountain, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblMountainIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(spnSwamp, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblSwampIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(spnDeckSize, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(btnAutoAdd)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(btnAutoAdd, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(spnMountain, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
.addComponent(spnIsland, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
.addComponent(spnForest, javax.swing.GroupLayout.Alignment.LEADING))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(spnSwamp, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 85, Short.MAX_VALUE)
.addComponent(spnPlains, javax.swing.GroupLayout.Alignment.LEADING))))
.addComponent(spnPlains, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnAdd)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel))
.addComponent(panelSet, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addComponent(lblPlainsIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(36, 36, 36))))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -322,30 +397,44 @@ public class AddLandDialog extends MageDialog {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblForest)
.addComponent(spnForest, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(spnForest, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblForestIcon, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblIsland)
.addComponent(spnIsland, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblIsland)
.addComponent(spnIsland, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(lblIslandIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblMountain)
.addComponent(spnMountain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblMountain)
.addComponent(spnMountain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(lblMountainIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblPains)
.addComponent(spnPlains, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblPains)
.addComponent(spnPlains, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(lblPlainsIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblSwamp)
.addComponent(spnSwamp, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(lblSwampIcon, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblSwamp)
.addComponent(spnSwamp, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(ckbFullArtLands)
.addGap(2, 2, 2)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnAutoAdd)
.addComponent(lblDeckSize)
.addComponent(spnDeckSize, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnAdd)
.addComponent(btnCancel)))
.addComponent(btnCancel))
.addContainerGap())
);
pack();
@ -386,7 +475,7 @@ public class AddLandDialog extends MageDialog {
int blue = 0;
int white = 0;
Set<Card> cards = deck.getCards();
int land_number = DEFAULT_SEALED_DECK_CARD_NUMBER - cards.size();
int land_number = ((Number) spnDeckSize.getValue()).intValue() - cards.size();
if (land_number < 0) {
land_number = 0;
}
@ -427,13 +516,21 @@ public class AddLandDialog extends MageDialog {
private javax.swing.JComboBox cbLandSet;
private javax.swing.JCheckBox ckbFullArtLands;
private javax.swing.JButton jButton2;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel lblDeckSize;
private javax.swing.JLabel lblForest;
private javax.swing.JLabel lblForestIcon;
private javax.swing.JLabel lblIsland;
private javax.swing.JLabel lblIslandIcon;
private javax.swing.JLabel lblLandSet;
private javax.swing.JLabel lblMountain;
private javax.swing.JLabel lblMountainIcon;
private javax.swing.JLabel lblPains;
private javax.swing.JLabel lblPlainsIcon;
private javax.swing.JLabel lblSwamp;
private javax.swing.JLabel lblSwampIcon;
private javax.swing.JPanel panelSet;
private javax.swing.JSpinner spnDeckSize;
private javax.swing.JSpinner spnForest;
private javax.swing.JSpinner spnIsland;
private javax.swing.JSpinner spnMountain;

View file

@ -27,6 +27,12 @@
*/
package mage.client.dialog;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.swing.*;
import mage.cards.decks.importer.DeckImporterUtil;
import mage.client.MageFrame;
import mage.client.SessionHandler;
@ -45,13 +51,6 @@ import mage.view.GameTypeView;
import mage.view.TableView;
import org.apache.log4j.Logger;
import javax.swing.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* @author BetaSteward_at_googlemail.com
*/
@ -623,17 +622,22 @@ public class NewTableDialog extends MageDialog {
* set the table settings from java prefs
*/
int currentSettingVersion = 0;
private void setGameSettingsFromPrefs(int version) {
currentSettingVersion = version;
String versionStr = "";
if (currentSettingVersion == 1) {
versionStr = "1";
btnPreviousConfiguration1.requestFocus();
} else if (currentSettingVersion == 2) {
versionStr = "2";
btnPreviousConfiguration2.requestFocus();
} else {
btnPreviousConfiguration2.getParent().requestFocus();
switch (currentSettingVersion) {
case 1:
versionStr = "1";
btnPreviousConfiguration1.requestFocus();
break;
case 2:
versionStr = "2";
btnPreviousConfiguration2.requestFocus();
break;
default:
btnPreviousConfiguration2.getParent().requestFocus();
break;
}
txtName.setText(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NAME + versionStr, "Game"));
txtPassword.setText(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_PASSWORD + versionStr, ""));
@ -724,6 +728,7 @@ public class NewTableDialog extends MageDialog {
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_RANGE + versionStr, Integer.toString(options.getRange().getRange()));
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_ATTACK_OPTION + versionStr, options.getAttackOption().toString());
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_SKILL_LEVEL + versionStr, options.getSkillLevel().toString());
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_SPECTATORS_ALLOWED + versionStr, options.isSpectatorsAllowed() ? "Yes" : "No");
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_QUIT_RATIO + versionStr, Integer.toString(options.getQuitRatio()));
StringBuilder playerTypesString = new StringBuilder();
for (Object player : players) {

View file

@ -35,11 +35,13 @@ package mage.client.dialog;
import java.awt.*;
import java.io.File;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import mage.cards.decks.Deck;
import mage.cards.decks.importer.DeckImporterUtil;
import mage.cards.repository.ExpansionInfo;
@ -589,9 +591,9 @@ public class NewTournamentDialog extends MageDialog {
} else {
for (JPanel panel : packPanels) {
JComboBox combo = findComboInComponent(panel);
if(combo != null) {
if (combo != null) {
tOptions.getLimitedOptions().getSetCodes().add(((ExpansionInfo) combo.getSelectedItem()).getCode());
}else{
} else {
logger.error("Can't find combo component in " + panel.toString());
}
}
@ -764,7 +766,6 @@ public class NewTournamentDialog extends MageDialog {
this.spnNumPlayers.setModel(new SpinnerNumberModel(numPlayers, tournamentType.getMinPlayers(), tournamentType.getMaxPlayers(), 1));
this.spnNumPlayers.setEnabled(tournamentType.getMinPlayers() != tournamentType.getMaxPlayers());
createPlayers((Integer) spnNumPlayers.getValue() - 1);
this.spnNumSeats.setModel(new SpinnerNumberModel(2, 2, tournamentType.getMaxPlayers(), 1));
if (tournamentType.isLimited()) {
@ -926,7 +927,7 @@ public class NewTournamentDialog extends MageDialog {
public void actionPerformed(java.awt.event.ActionEvent evt) {
// search combo box near button (must be only one combo in panel)
JButton button = (JButton)evt.getSource();
JButton button = (JButton) evt.getSource();
JComboBox combo = findComboInComponent(button.getParent());
if (combo != null) {
@ -941,12 +942,12 @@ public class NewTournamentDialog extends MageDialog {
this.repaint();
}
private JComboBox findComboInComponent(Container panel){
private JComboBox findComboInComponent(Container panel) {
// search combo box near button (must be only one combo in panel)
JComboBox combo = null;
for(Component comp: panel.getComponents()){
if (comp instanceof JComboBox){
combo = (JComboBox)comp;
for (Component comp : panel.getComponents()) {
if (comp instanceof JComboBox) {
combo = (JComboBox) comp;
break;
}
}
@ -955,21 +956,21 @@ public class NewTournamentDialog extends MageDialog {
private void packActionPerformed(java.awt.event.ActionEvent evt) {
// fill all bottom combobox with same value
JComboBox curentCombo = (JComboBox)evt.getSource();
JComboBox curentCombo = (JComboBox) evt.getSource();
int newValue = curentCombo.getSelectedIndex();
// search start index
int startIndex = 0;
for(int i = 0; i < packPanels.size(); i++){
for (int i = 0; i < packPanels.size(); i++) {
JComboBox pack = findComboInComponent(packPanels.get(i));
if (pack.equals(curentCombo)){
if (pack.equals(curentCombo)) {
startIndex = i + 1;
break;
}
}
// change all from start index
for(int i = startIndex; i < packPanels.size(); i++){
for (int i = startIndex; i < packPanels.size(); i++) {
JComboBox pack = findComboInComponent(packPanels.get(i));
pack.setSelectedIndex(newValue);
}
@ -1128,7 +1129,7 @@ public class NewTournamentDialog extends MageDialog {
break;
}
}
}else{
} else {
logger.error("Can't find combo component in " + panel.toString());
}
}

View file

@ -95,10 +95,10 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="main_game" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="main_gamelog" min="-2" pref="107" max="-2" attributes="0"/>
<Component id="main_gamelog" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="main_battlefield" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="121" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -200,7 +200,7 @@
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
<Component id="tooltipDelayLabel" pref="308" max="32767" attributes="0"/>
<Component id="tooltipDelayLabel" max="32767" attributes="0"/>
<Component id="tooltipDelay" alignment="1" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
@ -295,16 +295,22 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="showPlayerNamesPermanently" alignment="0" max="32767" attributes="0"/>
<Component id="nonLandPermanentsInOnePile" alignment="0" max="32767" attributes="0"/>
<Component id="cbConfirmEmptyManaPool" alignment="0" max="32767" attributes="0"/>
<Component id="cbAllowRequestToShowHandCards" alignment="0" max="32767" attributes="0"/>
<Component id="cbShowStormCounter" alignment="0" max="32767" attributes="0"/>
<Component id="cbAskMoveToGraveOrder" alignment="0" max="32767" attributes="0"/>
<Component id="showAbilityPickerForced" alignment="0" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="showPlayerNamesPermanently" alignment="0" max="32767" attributes="0"/>
<Component id="nonLandPermanentsInOnePile" alignment="0" max="32767" attributes="0"/>
<Component id="cbConfirmEmptyManaPool" alignment="0" max="32767" attributes="0"/>
<Component id="cbAllowRequestToShowHandCards" alignment="0" max="32767" attributes="0"/>
<Component id="cbShowStormCounter" alignment="0" max="32767" attributes="0"/>
<Component id="cbAskMoveToGraveOrder" alignment="0" max="32767" attributes="0"/>
<Component id="showAbilityPickerForced" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="displayLifeOnAvatar" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace pref="177" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -315,6 +321,8 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="showPlayerNamesPermanently" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="displayLifeOnAvatar" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="showAbilityPickerForced" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cbAllowRequestToShowHandCards" min="-2" max="-2" attributes="0"/>
@ -324,7 +332,6 @@
<Component id="cbConfirmEmptyManaPool" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cbAskMoveToGraveOrder" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -354,6 +361,17 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showPlayerNamesPermanentlyActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="displayLifeOnAvatar">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="Display life on avatar image"/>
<Property name="toolTipText" type="java.lang.String" value="Display the player&apos;s life over its avatar image."/>
<Property name="horizontalAlignment" type="int" value="2"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="displayLifeOnAvatarActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="showAbilityPickerForced">
<Properties>
<Property name="selected" type="boolean" value="true"/>
@ -4274,7 +4292,7 @@
<Component id="panelCardImages" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="panelBackgroundImages" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="125" max="32767" attributes="0"/>
<EmptySpace pref="133" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -4847,7 +4865,7 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="avatarPane" pref="584" max="32767" attributes="0"/>
<Component id="avatarPane" pref="620" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>

View file

@ -96,6 +96,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
public static final String KEY_SHOW_FULL_IMAGE_PATH = "showFullImagePath";
public static final String KEY_PERMANENTS_IN_ONE_PILE = "nonLandPermanentsInOnePile";
public static final String KEY_SHOW_PLAYER_NAMES_PERMANENTLY = "showPlayerNamesPermanently";
public static final String KEY_DISPLAY_LIVE_ON_AVATAR = "displayLiveOnAvatar";
public static final String KEY_SHOW_ABILITY_PICKER_FORCED = "showAbilityPicker";
public static final String KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS = "gameAllowRequestShowHandCards";
public static final String KEY_GAME_SHOW_STORM_COUNTER = "gameShowStormCounter";
@ -421,6 +422,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
main_game = new javax.swing.JPanel();
nonLandPermanentsInOnePile = new javax.swing.JCheckBox();
showPlayerNamesPermanently = new javax.swing.JCheckBox();
displayLifeOnAvatar = new javax.swing.JCheckBox();
showAbilityPickerForced = new javax.swing.JCheckBox();
cbAllowRequestToShowHandCards = new javax.swing.JCheckBox();
cbShowStormCounter = new javax.swing.JCheckBox();
@ -700,7 +702,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(6, 6, 6)
.add(main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
.add(tooltipDelayLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 308, Short.MAX_VALUE)
.add(tooltipDelayLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(tooltipDelay, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.add(main_cardLayout.createSequentialGroup()
.add(showCardName)
@ -741,6 +743,16 @@ public class PreferencesDialog extends javax.swing.JDialog {
}
});
displayLifeOnAvatar.setSelected(true);
displayLifeOnAvatar.setText("Display life on avatar image");
displayLifeOnAvatar.setToolTipText("Display the player's life over its avatar image.");
displayLifeOnAvatar.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
displayLifeOnAvatar.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
displayLifeOnAvatarActionPerformed(evt);
}
});
showAbilityPickerForced.setSelected(true);
showAbilityPickerForced.setText("Show ability picker for abilities or spells without costs");
showAbilityPickerForced.setToolTipText("This prevents you from accidently activating abilities without other costs than tapping or casting spells with 0 mana costs.");
@ -797,15 +809,19 @@ public class PreferencesDialog extends javax.swing.JDialog {
main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(main_gameLayout.createSequentialGroup()
.addContainerGap()
.add(main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
.add(showPlayerNamesPermanently, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(nonLandPermanentsInOnePile, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(cbConfirmEmptyManaPool, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(cbAllowRequestToShowHandCards, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(cbShowStormCounter, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(cbAskMoveToGraveOrder, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(showAbilityPickerForced, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(177, Short.MAX_VALUE))
.add(main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(main_gameLayout.createSequentialGroup()
.add(main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
.add(showPlayerNamesPermanently, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(nonLandPermanentsInOnePile, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(cbConfirmEmptyManaPool, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(cbAllowRequestToShowHandCards, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(cbShowStormCounter, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(cbAskMoveToGraveOrder, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(showAbilityPickerForced, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.add(0, 0, Short.MAX_VALUE))
.add(displayLifeOnAvatar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
main_gameLayout.setVerticalGroup(
main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
@ -814,6 +830,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(showPlayerNamesPermanently)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(displayLifeOnAvatar)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(showAbilityPickerForced)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(cbAllowRequestToShowHandCards)
@ -822,8 +840,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(cbConfirmEmptyManaPool)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(cbAskMoveToGraveOrder)
.addContainerGap())
.add(cbAskMoveToGraveOrder))
);
nonLandPermanentsInOnePile.getAccessibleContext().setAccessibleName("nonLandPermanentsInOnePile");
@ -880,10 +897,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(main_game, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(main_gamelog, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 107, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(main_gamelog, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(main_battlefield, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerGap(121, Short.MAX_VALUE))
.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
main_card.getAccessibleContext().setAccessibleName("Game panel");
@ -1797,7 +1814,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
.add(panelCardImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(panelBackgroundImages, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerGap(125, Short.MAX_VALUE))
.addContainerGap(133, Short.MAX_VALUE))
);
tabsPanel.addTab("Images", tabImages);
@ -2372,7 +2389,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
tabAvatarsLayout.setVerticalGroup(
tabAvatarsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(tabAvatarsLayout.createSequentialGroup()
.add(avatarPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 584, Short.MAX_VALUE)
.add(avatarPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 620, Short.MAX_VALUE)
.addContainerGap())
);
@ -2762,6 +2779,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
save(prefs, dialog.showFullImagePath, KEY_SHOW_FULL_IMAGE_PATH, "true", "false", UPDATE_CACHE_POLICY);
save(prefs, dialog.nonLandPermanentsInOnePile, KEY_PERMANENTS_IN_ONE_PILE, "true", "false", UPDATE_CACHE_POLICY);
save(prefs, dialog.showPlayerNamesPermanently, KEY_SHOW_PLAYER_NAMES_PERMANENTLY, "true", "false", UPDATE_CACHE_POLICY);
save(prefs, dialog.displayLifeOnAvatar, KEY_DISPLAY_LIVE_ON_AVATAR, "true", "false", UPDATE_CACHE_POLICY);
save(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true", "false", UPDATE_CACHE_POLICY);
save(prefs, dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true", "false", UPDATE_CACHE_POLICY);
save(prefs, dialog.cbShowStormCounter, KEY_GAME_SHOW_STORM_COUNTER, "true", "false", UPDATE_CACHE_POLICY);
@ -3225,6 +3243,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
}
}//GEN-LAST:event_cbGameJsonLogAutoSaveActionPerformed
private void displayLifeOnAvatarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_displayLifeOnAvatarActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_displayLifeOnAvatarActionPerformed
private void showProxySettings() {
Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem();
switch (proxyType) {
@ -3331,6 +3353,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
load(prefs, dialog.showFullImagePath, KEY_SHOW_FULL_IMAGE_PATH, "true");
load(prefs, dialog.nonLandPermanentsInOnePile, KEY_PERMANENTS_IN_ONE_PILE, "true");
load(prefs, dialog.showPlayerNamesPermanently, KEY_SHOW_PLAYER_NAMES_PERMANENTLY, "true");
load(prefs, dialog.displayLifeOnAvatar, KEY_DISPLAY_LIVE_ON_AVATAR, "true");
load(prefs, dialog.showAbilityPickerForced, KEY_SHOW_ABILITY_PICKER_FORCED, "true");
load(prefs, dialog.cbAllowRequestToShowHandCards, KEY_GAME_ALLOW_REQUEST_SHOW_HAND_CARDS, "true");
load(prefs, dialog.cbShowStormCounter, KEY_GAME_SHOW_STORM_COUNTER, "true");
@ -3928,6 +3951,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
private javax.swing.JCheckBox checkBoxUpkeepYou;
private javax.swing.JPanel connection_servers;
private javax.swing.JLabel controlsDescriptionLabel;
private javax.swing.JCheckBox displayLifeOnAvatar;
private javax.swing.JButton exitButton;
private javax.swing.JLabel fontSizeLabel;
private javax.swing.JPanel guiSizeBasic;

View file

@ -77,7 +77,6 @@ import mage.constants.ManaType;
import mage.counters.Counter;
import mage.counters.CounterType;
import mage.designations.DesignationType;
import mage.remote.Session;
import mage.utils.timer.PriorityTimer;
import mage.view.CardView;
import mage.view.ManaPoolView;
@ -93,13 +92,10 @@ public class PlayerPanelExt extends javax.swing.JPanel {
private UUID playerId;
private UUID gameId;
private Session session;
private PlayerView player;
private BigCard bigCard;
private static final int AVATAR_COUNT = 77;
private static final String DEFAULT_AVATAR_PATH = "/avatars/" + DEFAULT_AVATAR_ID + ".jpg";
private static final int PANEL_WIDTH = 94;
@ -179,8 +175,11 @@ public class PlayerPanelExt extends javax.swing.JPanel {
public void update(PlayerView player) {
this.player = player;
updateAvatar();
int playerLife = player.getLife();
avatar.setCenterText("true".equals(MageFrame.getPreferences().get(PreferencesDialog.KEY_DISPLAY_LIVE_ON_AVATAR, "true"))
? String.valueOf(playerLife) : null);
updateAvatar();
if (playerLife > 99) {
Font font = lifeLabel.getFont();
font = font.deriveFont(9f);
@ -701,8 +700,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
.addComponent(btnPlayer, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(timerLabel, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(avatar, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 80, Short.MAX_VALUE))
// .addGroup(gl_panelBackground.createSequentialGroup()
// .addComponent(avatarFlag, GroupLayout.PREFERRED_SIZE, 16, GroupLayout.PREFERRED_SIZE))
.addGap(8))
.addGroup(gl_panelBackground.createSequentialGroup()
.addGap(6)
@ -824,16 +821,12 @@ public class PlayerPanelExt extends javax.swing.JPanel {
protected void sizePlayerPanel(boolean smallMode) {
if (smallMode) {
avatar.setVisible(false);
// avatarFlag.setVisible(false);
// monarchIcon.setVisible(false);
btnPlayer.setVisible(true);
timerLabel.setVisible(true);
panelBackground.setPreferredSize(new Dimension(PANEL_WIDTH - 2, PANEL_HEIGHT_SMALL));
panelBackground.setBounds(0, 0, PANEL_WIDTH - 2, PANEL_HEIGHT_SMALL);
} else {
avatar.setVisible(true);
// avatarFlag.setVisible(true);
// monarchIcon.setVisible(true);
btnPlayer.setVisible(false);
timerLabel.setVisible(false);
panelBackground.setPreferredSize(new Dimension(PANEL_WIDTH - 2, PANEL_HEIGHT));
@ -887,8 +880,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
}
private HoverButton avatar;
// private JLabel avatarFlag;
// private JLabel monarchIcon;
private JButton btnPlayer;
private ImagePanel life;
private ImagePanel poison;
@ -918,7 +909,6 @@ public class PlayerPanelExt extends javax.swing.JPanel {
private JPanel energyExperiencePanel;
private HoverButton exileZone;
private HoverButton commandZone;
private HoverButton enchantPlayerViewZone;
private final Map<String, JLabel> manaLabels = new HashMap<>();
}

View file

@ -26,10 +26,12 @@ import mage.cards.MageCard;
import mage.cards.action.ActionCallback;
import mage.cards.action.TransferData;
import mage.client.MageFrame;
import mage.client.MagePane;
import mage.client.SessionHandler;
import mage.client.cards.BigCard;
import mage.client.components.MageComponents;
import mage.client.dialog.PreferencesDialog;
import mage.client.game.GamePane;
import mage.client.plugins.impl.Plugins;
import mage.client.util.DefaultActionCallback;
import mage.client.util.gui.ArrowBuilder;
@ -367,6 +369,16 @@ public class MageActionCallback implements ActionCallback {
}
private void handleOverNewView(TransferData data) {
// Prevent to show tooltips from panes not in front
MagePane topPane = MageFrame.getTopMost(null);
if (topPane instanceof GamePane) {
if (!((GamePane) topPane).getGameId().equals(data.gameId)) {
return;
}
} else if (data.gameId != null) {
return;
}
hideTooltipPopup();
cancelTimeout();
Component parentComponent = SwingUtilities.getRoot(data.component);

View file

@ -554,8 +554,8 @@ public final class ManaSymbols {
public static void draw(Graphics g, String manaCost, int x, int y, int symbolWidth, Color symbolsTextColor, int symbolMarginX) {
if (!manaImages.containsKey(symbolWidth)) {
loadSymbolImages(symbolWidth);
}
}
// TODO: replace with jlabel render (look at table rendere)?
/*
@ -605,12 +605,16 @@ public final class ManaSymbols {
return;
}
manaCost = manaCost.replace("\\", "");
manaCost = manaCost.replace("\\", "");
manaCost = UI.getDisplayManaCost(manaCost);
StringTokenizer tok = new StringTokenizer(manaCost, " ");
while (tok.hasMoreTokens()) {
String symbol = tok.nextToken();
Image image = sizedSymbols.get(symbol);
if (image == null && symbol != null) {
String symbol2 = "" + symbol.charAt(1) + symbol.charAt(0);
image = sizedSymbols.get(symbol2);
}
if (image == null) {
// TEXT draw

View file

@ -34,6 +34,7 @@ import mage.util.SubTypeList;
import mage.view.CardView;
import mage.view.PermanentView;
import org.apache.log4j.Logger;
import static org.mage.card.arcane.ManaSymbols.getSizedManaSymbol;
/*
@ -72,13 +73,13 @@ public class ModernCardRenderer extends CardRenderer {
BufferedImage img = CardRendererUtils.toBufferedImage(icon.getImage());
return new TexturePaint(img, new Rectangle(0, 0, img.getWidth(), img.getHeight()));
}
private static BufferedImage loadBackgroundImage(String name) {
URL url = ModernCardRenderer.class.getResource("/cardrender/background_texture_" + name + ".png");
ImageIcon icon = new ImageIcon(url);
BufferedImage img = CardRendererUtils.toBufferedImage(icon.getImage());
return img;
}
}
private static BufferedImage loadFramePart(String name) {
URL url = ModernCardRenderer.class.getResource("/cardrender/" + name + ".png");
@ -108,7 +109,7 @@ public class ModernCardRenderer extends CardRenderer {
public static final Paint BG_TEXTURE_ARTIFACT = loadBackgroundTexture("artifact");
public static final Paint BG_TEXTURE_LAND = loadBackgroundTexture("land");
public static final Paint BG_TEXTURE_VEHICLE = loadBackgroundTexture("vehicle");
public static final BufferedImage BG_IMG_WHITE = loadBackgroundImage("white");
public static final BufferedImage BG_IMG_BLUE = loadBackgroundImage("blue");
public static final BufferedImage BG_IMG_BLACK = loadBackgroundImage("black");
@ -119,7 +120,8 @@ public class ModernCardRenderer extends CardRenderer {
public static final BufferedImage BG_IMG_LAND = loadBackgroundImage("land");
public static final BufferedImage BG_IMG_VEHICLE = loadBackgroundImage("vehicle");
public static final BufferedImage BG_IMG_COLORLESS = loadBackgroundImage("colorless");
public static final BufferedImage BG_IMG_EXPEDITION = loadBackgroundImage("expedition");
public static final BufferedImage FRAME_INVENTION = loadFramePart("invention_frame");
public static final Color BORDER_WHITE = new Color(216, 203, 188);
@ -301,7 +303,11 @@ public class ModernCardRenderer extends CardRenderer {
// Just draw a brown rectangle
drawCardBack(g);
} else {
BufferedImage bg = getBackgroundImage(cardView.getColor(), cardView.getCardTypes(), cardView.getSubTypes());
boolean isExped = false;
if (cardView.getExpansionSetCode().equals("EXP")) {
isExped = true;
}
BufferedImage bg = getBackgroundImage(cardView.getColor(), cardView.getCardTypes(), cardView.getSubTypes(), isExped);
if (bg == null) {
return;
}
@ -318,12 +324,12 @@ public class ModernCardRenderer extends CardRenderer {
cardWidth - borderWidth * 2, cornerRadius * 4,
cornerRadius * 2, cornerRadius * 2);
a.add(new Area(rr2));
// Draw the M15 rounded "swoosh" at the bottom
Rectangle r = new Rectangle(borderWidth + contentInset, cardHeight - borderWidth * 5, cardWidth - borderWidth * 2 - contentInset * 2, borderWidth * 2);
a.add(new Area(r));
g.setClip(a);
g.drawImage(bg, 0, 0, cardWidth, cardHeight, 0, 0, bgw, bgh, BOX_BLUE, null);
g.drawImage(bg, 0, 0, cardWidth, cardHeight, 0, 0, bgw, bgh, BOX_BLUE, null);
g.setClip(null);
}
}
@ -545,24 +551,13 @@ public class ModernCardRenderer extends CardRenderer {
if (!isZendikarFullArtLand()) {
drawRulesText(g, textboxKeywords, textboxRules,
totalContentInset + 2, typeLineY + boxHeight + 2,
contentWidth - 4, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3);
contentWidth - 4, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3, false);
} else {
int x = totalContentInset;
int y = typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset;
int w = contentWidth;
int h = boxHeight - 4;
CardRendererUtils.drawZendikarLandBox(g,
x, y, w, h,
contentInset,
borderPaint, boxColor);
drawTypeLine(g, getCardSuperTypeLine(),
totalContentInset + contentInset, typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset,
contentWidth / 2 - boxHeight, boxHeight - 4, false);
drawTypeLine(g, getCardSubTypeLine(),
totalContentInset + 4 * contentWidth / 7 + boxHeight, typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset,
3 * contentWidth / 7 - boxHeight - contentInset, boxHeight - 4, true);
if (cardView.getFrameStyle() == FrameStyle.ZEN_FULL_ART_BASIC) {
// Draw curved lines (old Zendikar land style) - bigger (around 6%) inset on curve on bottom than inset (around 4.5%) on top...
int x2 = x + contentWidth;
@ -584,9 +579,49 @@ public class ModernCardRenderer extends CardRenderer {
boxColor, borderPaint);
}
// If an expedition, needs the rules box to be visible.
if (cardView.getExpansionSetCode().equals("EXP")) {
// Draw a small separator between the type line and box, and shadow
// at the left of the texbox, and above the name line
g.setPaint(textboxPaint);
float alpha = 0.55f;
AlphaComposite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
Composite origc = g.getComposite();
g.setComposite(comp);
g.setBackground(new Color(155, 0, 0, 150));
g.fillRect(
totalContentInset + 1, typeLineY - boxHeight,
contentWidth - 2, cardHeight - borderWidth * 3 - typeLineY - 1);
g.setComposite(origc);
g.fillRect(
totalContentInset - 1, totalContentInset - 1,
contentWidth + 1, 1);
g.fillRect(
totalContentInset + 1, typeLineY - boxHeight,
contentWidth - 2, 1);
drawRulesText(g, textboxKeywords, textboxRules,
totalContentInset + 2, typeLineY - boxHeight,
contentWidth - 4, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3, true);
}
CardRendererUtils.drawZendikarLandBox(g,
x, y, w, h,
contentInset,
borderPaint, boxColor);
drawTypeLine(g, getCardSuperTypeLine(),
totalContentInset + contentInset, typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset,
contentWidth / 2 - boxHeight, boxHeight - 4, false);
drawTypeLine(g, getCardSubTypeLine(),
totalContentInset + 4 * contentWidth / 7 + boxHeight, typeLineY + boxHeight + (cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3) / 2 - contentInset,
3 * contentWidth / 7 - boxHeight - contentInset, boxHeight - 4, true);
drawRulesText(g, textboxKeywords, textboxRules,
x, y,
w, h);
w, h, false);
}
// Draw the bottom right stuff
@ -962,7 +997,7 @@ public class ModernCardRenderer extends CardRenderer {
return layout;
}
protected void drawRulesText(Graphics2D g, ArrayList<TextboxRule> keywords, ArrayList<TextboxRule> rules, int x, int y, int w, int h) {
protected void drawRulesText(Graphics2D g, ArrayList<TextboxRule> keywords, ArrayList<TextboxRule> rules, int x, int y, int w, int h, boolean forceRules) {
// Gather all rules to render
List<TextboxRule> allRules = new ArrayList<>(rules);
@ -974,14 +1009,19 @@ public class ModernCardRenderer extends CardRenderer {
}
// Basic mana draw mana symbol in textbox (for basic lands)
if (allRules.size() == 1 && (allRules.get(0) instanceof TextboxBasicManaRule) && cardView.isLand() || isZendikarFullArtLand()) {
if (!forceRules && (allRules.size() == 1 && (allRules.get(0) instanceof TextboxBasicManaRule) && cardView.isLand() || isZendikarFullArtLand())) {
if (!isZendikarFullArtLand()) {
drawBasicManaTextbox(g, x, y, w, h, ((TextboxBasicManaRule) allRules.get(0)).getBasicManaSymbol());
return;
} else // Big circle in the middle for Zendikar lands
if (allRules.size() == 1) {
{
if (allRules.size() == 1) {
// Size of mana symbol = 9/4 * h, 3/4h above line
drawBasicManaSymbol(g, x + w / 2 - 9 * h / 8 + 1, y - 3 * h / 4, 9 * h / 4, 9 * h / 4, ((TextboxBasicManaRule) allRules.get(0)).getBasicManaSymbol());
if (allRules.get(0) instanceof TextboxBasicManaRule) {
drawBasicManaSymbol(g, x + w / 2 - 9 * h / 8 + 1, y - 3 * h / 4, 9 * h / 4, 9 * h / 4, ((TextboxBasicManaRule) allRules.get(0)).getBasicManaSymbol());
} else {
drawBasicManaSymbol(g, x + w / 2 - h - h / 8, y - 3 * h / 4, 9 * h / 4, 9 * h / 4, cardView.getFrameColor().toString());
}
return;
} else {
if (allRules.size() > 1) {
@ -989,6 +1029,7 @@ public class ModernCardRenderer extends CardRenderer {
}
return;
}
}
}
// Go through possible font sizes in descending order to find the best fit
@ -1043,7 +1084,15 @@ public class ModernCardRenderer extends CardRenderer {
private void drawBasicManaSymbol(Graphics2D g, int x, int y, int w, int h, String symbol) {
String symbs = symbol;
ManaSymbols.draw(g, symbs, x, y, w, Color.black, 2);
if (getSizedManaSymbol(symbol) != null) {
ManaSymbols.draw(g, symbs, x, y, w, Color.black, 2);
}
if (symbol.length() == 2) {
String symbs2 = "" + symbol.charAt(1) + symbol.charAt(0);
if (getSizedManaSymbol(symbs2) != null) {
ManaSymbols.draw(g, symbs2, x, y, w, Color.black, 2);
}
}
}
// Get the first line of the textbox, the keyword string
@ -1272,13 +1321,16 @@ public class ModernCardRenderer extends CardRenderer {
return new Color(71, 86, 101);
}
}
// Determine which background image to use from a set of colors
// and the current card.
protected static BufferedImage getBackgroundImage(ObjectColor colors, Collection<CardType> types, SubTypeList subTypes) {
protected static BufferedImage getBackgroundImage(ObjectColor colors, Collection<CardType> types, SubTypeList subTypes, boolean isExped) {
if (subTypes.contains(SubType.VEHICLE)) {
return BG_IMG_VEHICLE;
} else if (types.contains(CardType.LAND)) {
if (isExped) {
return BG_IMG_EXPEDITION;
}
return BG_IMG_LAND;
} else if (types.contains(CardType.ARTIFACT)) {
return BG_IMG_ARTIFACT;
@ -1299,7 +1351,7 @@ public class ModernCardRenderer extends CardRenderer {
return BG_IMG_COLORLESS;
}
}
// Get the box color for the given colors
protected Color getBoxColor(ObjectColor colors, Collection<CardType> types, boolean isNightCard) {
if (cardView.isAbility()) {

View file

@ -272,7 +272,7 @@ public class ModernSplitCardRenderer extends ModernCardRenderer {
// Draw the textbox rules
drawRulesText(g, half.keywords, half.rules,
2, typeLineY + boxHeight + 2 - 4,
half.cw - 4, half.ch - typeLineY - boxHeight);
half.cw - 4, half.ch - typeLineY - boxHeight, false);
}
private Graphics2D getUnmodifiedHalfContext(Graphics2D g) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View file

@ -27,18 +27,14 @@
*/
package mage.view;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.Serializable;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.costs.Cost;
import mage.cards.Card;
@ -60,8 +56,6 @@ import mage.game.stack.StackObject;
import mage.players.Player;
import mage.watchers.common.CastSpellLastTurnWatcher;
import org.apache.log4j.Logger;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
*
@ -105,7 +99,12 @@ public class GameView implements Serializable {
}
}
for (StackObject stackObject : state.getStack()) {
if (stackObject instanceof StackAbility) {
if (stackObject instanceof Spell) {
// Spell
CardView spellView = new CardView((Spell) stackObject, game, stackObject.getControllerId().equals(createdForPlayerId));
spellView.paid = ((Spell) stackObject).getSpellAbility().getManaCostsToPay().isPaid();
stack.put(stackObject.getId(), spellView);
} else if (stackObject instanceof StackAbility) {
// Stack Ability
MageObject object = game.getObject(stackObject.getSourceId());
Card card = game.getCard(stackObject.getSourceId());
@ -161,9 +160,7 @@ public class GameView implements Serializable {
LOGGER.debug("Stack Object for stack ability not found: " + stackObject.getStackAbility().getRule());
}
} else {
// Spell
stack.put(stackObject.getId(), new CardView((Spell) stackObject, game, stackObject.getControllerId().equals(createdForPlayerId)));
checkPaid(stackObject.getId(), (Spell) stackObject);
LOGGER.fatal("Unknown type of StackObject: " + stackObject.getName() + ' ' + stackObject.toString() + ' ' + stackObject.getClass().toString());
}
//stackOrder.add(stackObject.getId());
}
@ -223,21 +220,6 @@ public class GameView implements Serializable {
cardView.paid = true;
}
private void checkPaid(UUID uuid, Spell spell) {
for (Cost cost : spell.getSpellAbility().getManaCostsToPay()) {
if (!cost.isPaid()) {
return;
}
}
CardView cardView = stack.get(uuid);
cardView.paid = true;
}
private void setPaid(UUID uuid) {
CardView cardView = stack.get(uuid);
cardView.paid = true;
}
private void updateLatestCardView(Game game, Card card, UUID stackId) {
if (!card.isTransformable()) {
return;

View file

@ -617,7 +617,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ {
} // end of for (allActions)
if (depth == maxDepth) {
logger.info(new StringBuilder("Sim Prio [").append(depth).append("] -- End for Max Depth -- Nodes calculated: ").append(SimulationNode2.nodeCount));
logger.info("Sim Prio [" + depth + "] -- End for Max Depth -- Nodes calculated: " + SimulationNode2.nodeCount);
}
if (bestNode != null) {
node.children.clear();

View file

@ -44,12 +44,11 @@ import mage.target.common.TargetControlledCreaturePermanent;
public class AcrobaticManeuver extends CardImpl {
public AcrobaticManeuver(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
// Exile target creature you control, then return that card to the battlefield under its owner's control.
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
Effect effect = new ExileTargetForSourceEffect();
effect.setApplyEffectsAfter();
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect());

View file

@ -1,16 +1,16 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.

View file

@ -52,14 +52,12 @@ public class Ambuscade extends CardImpl {
static {
filter.add(new ControllerPredicate(TargetController.NOT_YOU));
}
public Ambuscade(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}");
// Target creature you control gets +1/+0 until end of turn.
Effect effect = new BoostTargetEffect(1, 0, Duration.EndOfTurn);
effect.setApplyEffectsAfter(); // needed to count the boost for the second effect
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addEffect(effect);

View file

@ -46,13 +46,12 @@ import mage.target.common.TargetCreaturePermanent;
public class BarrelDownSokenzan extends CardImpl {
public BarrelDownSokenzan(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
this.subtype.add(SubType.ARCANE);
// Sweep - Return any number of Mountains you control to their owner's hand. Barrel Down Sokenzan deals damage to target creature equal to twice the number of Mountains returned this way.
this.getSpellAbility().addEffect(new SweepEffect(SubType.MOUNTAIN));
DynamicValue sweepValue = new MultipliedValue(new SweepNumber("Mountain", false), 2);
DynamicValue sweepValue = new MultipliedValue(new SweepNumber("Mountain"), 2);
this.getSpellAbility().addEffect(new DamageTargetEffect(sweepValue));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}

View file

@ -53,7 +53,7 @@ import mage.target.common.TargetControlledPermanent;
public class BragoKingEternal extends CardImpl {
public BragoKingEternal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.SPIRIT);
@ -65,7 +65,6 @@ public class BragoKingEternal extends CardImpl {
// When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control.
Effect effect = new ExileTargetEffect(this.getId(), this.getName(), Zone.BATTLEFIELD);
effect.setText("exile any number of target nonland permanents you control");
effect.setApplyEffectsAfter();
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(effect, false);
FilterControlledPermanent filterControlledNonlandPermanent = new FilterControlledPermanent();
filterControlledNonlandPermanent.add(Predicates.not(new CardTypePredicate(CardType.LAND)));

View file

@ -41,17 +41,16 @@ import mage.target.common.TargetCreaturePermanent;
* @author jeffwadsworth
*/
public class CauldronHaze extends CardImpl {
private String rule = "Choose any number of target creatures. Each of those creatures gains persist until end of turn";
private final String rule = "Choose any number of target creatures. Each of those creatures gains persist until end of turn";
public CauldronHaze(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W/B}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W/B}");
// Choose any number of target creatures. Each of those creatures gains persist until end of turn.
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(new PersistAbility(), Duration.EndOfTurn, rule));
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE));
}
public CauldronHaze(final CauldronHaze card) {

View file

@ -1,4 +1,4 @@
/*
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
@ -27,16 +27,16 @@
*/
package mage.cards.c;
import java.util.UUID;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.SweepNumber;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.keyword.SweepEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import java.util.UUID;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.SweepNumber;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.keyword.SweepEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
/**
*
@ -45,14 +45,13 @@ package mage.cards.c;
public class ChargeAcrossTheAraba extends CardImpl {
public ChargeAcrossTheAraba(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{W}");
this.subtype.add(SubType.ARCANE);
// Sweep - Return any number of Plains you control to their owner's hand. Creatures you control get +1/+1 until end of turn for each Plains returned this way.
this.getSpellAbility().addEffect(new SweepEffect(SubType.PLAINS));
DynamicValue sweepValue = new SweepNumber("Plains", true);
this.getSpellAbility().addEffect(new BoostControlledEffect(sweepValue, sweepValue, Duration.EndOfTurn));
DynamicValue sweepValue = new SweepNumber("Plains");
this.getSpellAbility().addEffect(new BoostControlledEffect(sweepValue, sweepValue, Duration.EndOfTurn, null, false, true));
}

View file

@ -58,7 +58,6 @@ public class ClearShot extends CardImpl {
// Target creature you control gets +1/+1 until end of turn.
Effect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn);
effect.setApplyEffectsAfter(); // needed to count the boost for the second effect
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addEffect(effect);

View file

@ -43,12 +43,11 @@ import mage.target.common.TargetControlledCreaturePermanent;
public class Cloudshift extends CardImpl {
public Cloudshift(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
// Exile target creature you control, then return that card to the battlefield under your control.
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
Effect effect = new ExileTargetForSourceEffect();
effect.setApplyEffectsAfter();
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(true));
}

View file

@ -27,6 +27,7 @@
*/
package mage.cards.c;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -41,8 +42,6 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
@ -50,7 +49,7 @@ import java.util.UUID;
public class Cultivate extends CardImpl {
public Cultivate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}");
// Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Then shuffle your library.
this.getSpellAbility().addEffect(new CultivateEffect());
@ -96,11 +95,7 @@ class CultivateEffect extends OneShotEffect {
TargetCardInLibrary target = new TargetCardInLibrary(0, 2, StaticFilters.FILTER_BASIC_LAND_CARD);
if (controller.searchLibrary(target, game)) {
if (!target.getTargets().isEmpty()) {
Cards revealed = new CardsImpl();
for (UUID cardId : target.getTargets()) {
Card card = controller.getLibrary().getCard(cardId, game);
revealed.add(card);
}
Cards revealed = new CardsImpl(target.getTargets());
controller.revealCards(sourceObject.getIdName(), revealed, game);
if (target.getTargets().size() == 2) {
TargetCard target2 = new TargetCard(Zone.LIBRARY, filter);
@ -120,13 +115,10 @@ class CultivateEffect extends OneShotEffect {
controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
}
}
}
controller.shuffleLibrary(source, game);
return true;
}
controller.shuffleLibrary(source, game);
return false;
return true;
}

View file

@ -0,0 +1,113 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SuperType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
import mage.util.functions.EmptyApplyToPermanent;
/**
*
* @author jeffwadsworth
*/
public class Cytoshape extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonlegendary creature");
static {
filter.add(Predicates.not(new SupertypePredicate(SuperType.LEGENDARY)));
}
public Cytoshape(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}{U}");
// Choose a nonlegendary creature on the battlefield. Target creature becomes a copy of that creature until end of turn.
this.getSpellAbility().addEffect(new CytoshapeEffect());
Target target = new TargetCreaturePermanent(1, 1, filter, true);
target.setTargetTag(1);
this.getSpellAbility().addTarget(target);
FilterCreaturePermanent filter2 = new FilterCreaturePermanent("target creature that will become a copy of that chosen creature");
target = new TargetCreaturePermanent(filter2);
target.setTargetTag(2);
this.getSpellAbility().addTarget(target);
}
public Cytoshape(final Cytoshape card) {
super(card);
}
@Override
public Cytoshape copy() {
return new Cytoshape(this);
}
}
class CytoshapeEffect extends OneShotEffect {
public CytoshapeEffect() {
super(Outcome.Copy);
this.staticText = "Choose a nonlegendary creature on the battlefield. Target creature becomes a copy of that creature until end of turn.";
}
public CytoshapeEffect(final CytoshapeEffect effect) {
super(effect);
}
@Override
public CytoshapeEffect copy() {
return new CytoshapeEffect(this);
}
@Override
public boolean apply(Game game, Ability ability) {
Permanent copyFrom = game.getPermanent(getTargetPointer().getFirst(game, ability));
if (copyFrom != null) {
Permanent copyTo = game.getPermanentOrLKIBattlefield(ability.getTargets().get(1).getFirstTarget());
if (copyTo != null) {
game.copyPermanent(Duration.EndOfTurn, copyFrom, copyTo.getId(), ability, new EmptyApplyToPermanent());
}
}
return true;
}
}

View file

@ -78,7 +78,6 @@ public class DromokasCommand extends CardImpl {
Mode mode = new Mode();
Effect effect = new SacrificeEffect(filterEnchantment, 1, "target player");
effect.setText("Target player sacrifices an enchantment");
effect.setApplyEffectsAfter(); // so P/T chnaging effects take place before the fighting effect is applied
mode.getEffects().add(effect);
mode.getTargets().add(new TargetPlayer());
this.getSpellAbility().getModes().addMode(mode);
@ -87,7 +86,6 @@ public class DromokasCommand extends CardImpl {
mode = new Mode();
effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance());
effect.setText("Put a +1/+1 counter on target creature");
effect.setApplyEffectsAfter(); // so the counter is taken into account if the target is also used in mode 4
mode.getEffects().add(effect);
mode.getTargets().add(new TargetCreaturePermanent(filterCreature));
this.getSpellAbility().getModes().addMode(mode);

View file

@ -58,7 +58,7 @@ public class EldraziDisplacer extends CardImpl {
}
public EldraziDisplacer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.ELDRAZI);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
@ -69,7 +69,6 @@ public class EldraziDisplacer extends CardImpl {
// {2}{C}: Exile another target creature, then return it to the battlefield tapped under its owner's control.
Effect effect = new ExileTargetForSourceEffect();
effect.setText("Exile another target creature");
effect.setApplyEffectsAfter(); // Needed to let temporary continuous effects end if a permanent is blinked
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{2}{C}"));
effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(true);
effect.setText(", then return it to the battlefield tapped under its owner's control");

View file

@ -56,7 +56,7 @@ import mage.target.common.TargetOpponent;
public class EndlessWhispers extends CardImpl {
public EndlessWhispers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}");
// Each creature has "When this creature dies, choose target opponent. That player puts this card from its owner's graveyard onto the battlefield under his or her control at the beginning of the next end step."
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceToBattlefieldEffect());

View file

@ -40,15 +40,14 @@ import mage.game.permanent.token.AngelToken;
/**
*
* @author noxx
*
*/
public class EntreatTheAngels extends CardImpl {
public EntreatTheAngels(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{X}{W}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{W}{W}{W}");
// create X 4/4 white Angel creature tokens with flying.
// Create X 4/4 white Angel creature tokens with flying.
this.getSpellAbility().addEffect(new CreateTokenEffect(new AngelToken(), new ManacostVariableValue()));
// Miracle {X}{W}{W}

View file

@ -47,6 +47,7 @@ import mage.target.common.TargetCreaturePermanent;
* @author fireshoes
*/
public class EpicConfrontation extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don't control");
static {
@ -54,18 +55,17 @@ public class EpicConfrontation extends CardImpl {
}
public EpicConfrontation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{G}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}");
// Target creature you control gets +1/+2 until end of turn. It fights target creature you don't control.
Effect effect = new BoostTargetEffect(1,2,Duration.EndOfTurn);
effect.setApplyEffectsAfter();
Effect effect = new BoostTargetEffect(1, 2, Duration.EndOfTurn);
this.getSpellAbility().addEffect(effect);
effect = new FightTargetsEffect();
effect.setText("It fights target creature you don't control");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
Target target = new TargetCreaturePermanent(filter);
this.getSpellAbility().addTarget(target);
this.getSpellAbility().addTarget(target);
}
public EpicConfrontation(final EpicConfrontation card) {

View file

@ -54,12 +54,11 @@ import mage.util.CardUtil;
public class EssenceFlux extends CardImpl {
public EssenceFlux(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}");
// Exile target creature you control, then return that card to the battlefield under its owner's control. If it's a Spirit, put a +1/+1 counter on it.
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
Effect effect = new ExileTargetForSourceEffect();
effect.setApplyEffectsAfter();
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(new EssenceFluxEffect());
}
@ -102,8 +101,7 @@ class EssenceFluxEffect extends OneShotEffect {
for (UUID targetId : this.getTargetPointer().getTargets(game, source)) {
if (exileZone.contains(targetId)) {
cardsToBattlefield.add(targetId);
}
else {
} else {
Card card = game.getCard(targetId);
if (card != null && card instanceof MeldCard) {
MeldCard meldCard = (MeldCard) card;

View file

@ -64,7 +64,6 @@ public class FelidarGuardian extends CardImpl {
// When Felidar Guardian enters the battlefield, you may exile another target permanent you control, then return that card to the battlefield under its owner's control.
Effect effect = new ExileTargetForSourceEffect();
effect.setApplyEffectsAfter();
Ability ability = new EntersBattlefieldTriggeredAbility(effect, true);
ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect());
ability.addTarget(new TargetControlledPermanent(filter));

View file

@ -51,12 +51,12 @@ import mage.target.common.TargetCreaturePermanent;
/**
*
* @author LoneFox
*
*/
public class GrabTheReins extends CardImpl {
public GrabTheReins(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}");
// Choose one -
this.getSpellAbility().getModes().setMinModes(1);
@ -64,7 +64,6 @@ public class GrabTheReins extends CardImpl {
// Until end of turn, you gain control of target creature and it gains haste;
Effect effect = new GainControlTargetEffect(Duration.EndOfTurn);
effect.setText("Until end of turn, you gain control of target creature");
effect.setApplyEffectsAfter();
this.getSpellAbility().addEffect(effect);
effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn);
effect.setText("and it gains haste");
@ -111,15 +110,15 @@ class GrabTheReinsEffect extends OneShotEffect {
Target target = new TargetCreaturePermanent();
target.setNotTarget(true);
target.setTargetName("a creature to sacrifice");
if(!target.canChoose(source.getSourceId(), controllerId, game)) {
if (!target.canChoose(source.getSourceId(), controllerId, game)) {
return false;
}
Player player = game.getPlayer(controllerId);
if(player != null) {
if (player != null) {
player.chooseTarget(Outcome.Sacrifice, target, source, game);
Permanent creatureToSacrifice = game.getPermanent(target.getTargets().get(0));
int amount = creatureToSacrifice.getPower().getValue();
if(!creatureToSacrifice.sacrifice(creatureToSacrifice.getId(), game)) {
if (!creatureToSacrifice.sacrifice(creatureToSacrifice.getId(), game)) {
return false;
}
if (amount > 0) {
@ -133,8 +132,7 @@ class GrabTheReinsEffect extends OneShotEffect {
player.damage(amount, source.getSourceId(), game, false, true);
return true;
}
}
else {
} else {
return true;
}
}

View file

@ -53,6 +53,7 @@ public class HuntTheHunter extends CardImpl {
private static final FilterControlledCreaturePermanent filterControlledGreen = new FilterControlledCreaturePermanent("green creature you control");
private static final FilterCreaturePermanent filterOpponentGreen = new FilterCreaturePermanent("green creature an opponent controls");
static {
filterControlledGreen.add(new ColorPredicate(ObjectColor.GREEN));
filterOpponentGreen.add(new ControllerPredicate(TargetController.OPPONENT));
@ -60,14 +61,12 @@ public class HuntTheHunter extends CardImpl {
}
public HuntTheHunter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{G}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}");
// Target green creature you control gets +2/+2 until end of turn. It fights target green creature an opponent controls.
Effect effect = new BoostTargetEffect(2,2, Duration.EndOfTurn);
effect.setApplyEffectsAfter();
Effect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn);
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(1,1,filterControlledGreen, false));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(1, 1, filterControlledGreen, false));
effect = new FightTargetsEffect();
effect.setText("It fights target green creature an opponent controls");

View file

@ -49,17 +49,16 @@ import mage.target.common.TargetCreaturePermanent;
public class HuntTheWeak extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don't control");
static {
filter.add(new ControllerPredicate(TargetController.NOT_YOU));
}
public HuntTheWeak(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{G}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}");
// Put a +1/+1 counter on target creature you control. Then that creature fights target creature you don't control.
Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance());
effect.setApplyEffectsAfter();
this.getSpellAbility().addEffect(effect);
effect = new FightTargetsEffect();
effect.setText("Then that creature fights target creature you don't control");

View file

@ -60,11 +60,10 @@ public class NissasJudgment extends CardImpl {
}
public NissasJudgment(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{G}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}");
// Support 2.
Effect effect = new SupportEffect(this, 2, false);
effect.setApplyEffectsAfter();
getSpellAbility().addEffect(effect);
// Choose up to one target creature an opponent controls. Each creature you control with a +1/+1 counter on it deals damage equal to its power to that creature.

View file

@ -46,14 +46,13 @@ import mage.target.common.TargetCreaturePermanent;
public class PlowThroughReito extends CardImpl {
public PlowThroughReito(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
this.subtype.add(SubType.ARCANE);
// Sweep - Return any number of Plains you control to their owner's hand. Target creature gets +1/+1 until end of turn for each Plains returned this way.
this.getSpellAbility().addEffect(new SweepEffect(SubType.PLAINS));
DynamicValue sweepValue = new SweepNumber("Plains", true);
this.getSpellAbility().addEffect(new BoostTargetEffect(sweepValue, sweepValue, Duration.EndOfTurn));
DynamicValue sweepValue = new SweepNumber("Plains");
this.getSpellAbility().addEffect(new BoostTargetEffect(sweepValue, sweepValue, Duration.EndOfTurn, true));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}

View file

@ -45,7 +45,6 @@ import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author LevelX2
@ -59,14 +58,13 @@ public class SavagePunch extends CardImpl {
}
public SavagePunch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{G}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}");
// <i>Ferocious</i> - The creature you control gets +2/+2 until end of turn before it fights if you control a creature with power 4 or greater.
Effect effect = new ConditionalContinuousEffect(
new BoostTargetEffect(2,2,Duration.EndOfTurn),
new BoostTargetEffect(2, 2, Duration.EndOfTurn),
new LockedInCondition(FerociousCondition.instance),
"<i>Ferocious</i> &mdash; The creature you control gets +2/+2 until end of turn before it fights if you control a creature with power 4 or greater");
effect.setApplyEffectsAfter();
this.getSpellAbility().addEffect(effect);
// Target creature you control fights target creature you don't control.

View file

@ -75,7 +75,6 @@ public class SavageStomp extends CardImpl {
// Put a +1/+1 counter on target creature you control. Then that creature fights target creature you don't control.
Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance());
effect.setApplyEffectsAfter();
this.getSpellAbility().addEffect(effect);
effect = new FightTargetsEffect();
effect.setText("Then that creature fights target creature you don't control");

View file

@ -45,13 +45,12 @@ import mage.target.TargetPlayer;
public class SinkIntoTakenuma extends CardImpl {
public SinkIntoTakenuma(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}");
this.subtype.add(SubType.ARCANE);
// Sweep - Return any number of Swamps you control to their owner's hand. Target player discards a card for each Swamp returned this way.
this.getSpellAbility().addEffect(new SweepEffect(SubType.SWAMP));
DynamicValue sweepValue = new SweepNumber("Swamp", false);
DynamicValue sweepValue = new SweepNumber("Swamp");
this.getSpellAbility().addEffect(new DiscardTargetEffect(sweepValue));
this.getSpellAbility().addTarget(new TargetPlayer());
}

View file

@ -36,7 +36,6 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.ChooseOpponentEffect;
import mage.constants.SubType;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -45,6 +44,7 @@ import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
@ -107,7 +107,7 @@ class SkyshroudWarBeastEffect extends ContinuousEffectImpl {
MageObject target = game.getObject(source.getSourceId());
if (target != null) {
UUID playerId = (UUID) game.getState().getValue(source.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY);
FilterLandPermanent filter = new FilterLandPermanent();
FilterLandPermanent filter = FilterLandPermanent.nonbasicLand();
filter.add(new ControllerIdPredicate(playerId));
int number = new PermanentsOnBattlefieldCount(filter).calculate(game, source, this);
target.getPower().setValue(number);

View file

@ -27,6 +27,7 @@
*/
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
@ -37,8 +38,6 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author LevelX2
@ -46,11 +45,10 @@ import java.util.UUID;
public class StartYourEngines extends CardImpl {
public StartYourEngines(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}");
// Vehicles you control becomes artifact creatures until end of turn.
Effect effect = new StartYourEnginesEffect();
effect.setApplyEffectsAfter(); // needed to recognize vehicle as creatures by the next effect
this.getSpellAbility().addEffect(effect);
// Creatures you control get +2/+0 until end of turn.

View file

@ -49,23 +49,22 @@ import mage.target.common.TargetCreaturePermanent;
public class SwiftKick extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don't control");
static {
filter.add(new ControllerPredicate(TargetController.NOT_YOU));
}
public SwiftKick(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}");
// Target creature you control gets +1/+0 until end of turn. It fights target creature you don't control.
Effect effect = new BoostTargetEffect(1,0,Duration.EndOfTurn);
effect.setApplyEffectsAfter();
Effect effect = new BoostTargetEffect(1, 0, Duration.EndOfTurn);
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
effect = new FightTargetsEffect();
effect.setText("It fights target creature you don't control");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(effect);
Target target = new TargetCreaturePermanent(filter);
this.getSpellAbility().addTarget(target);

View file

@ -132,7 +132,7 @@ class SylvanLibraryEffect extends OneShotEffect {
}
}
}
controller.putCardsOnTopOfLibrary(cardsPutBack, game, source, applyEffectsAfter);
controller.putCardsOnTopOfLibrary(cardsPutBack, game, source, false);
}
}
return true;

View file

@ -57,39 +57,37 @@ public class TemurCharm extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you don't control");
private static final FilterCreaturePermanent filterCantBlock = new FilterCreaturePermanent("Creatures with power 3 or less");
static {
filter.add(new ControllerPredicate(TargetController.NOT_YOU));
filterCantBlock.add(new PowerPredicate(ComparisonType.FEWER_THAN, 4));
}
public TemurCharm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G}{U}{R}");
public TemurCharm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}{U}{R}");
// Choose one -
// <strong><EFBFBD></strong> Target creature you control gets +1/+1 until end of turn. That creature fights target creature you don't control.
Effect effect = new BoostTargetEffect(1,1,Duration.EndOfTurn);
effect.setApplyEffectsAfter();
Effect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn);
this.getSpellAbility().addEffect(effect);
effect = new FightTargetsEffect();
effect.setText("That creature fights target creature you don't control");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
Target target = new TargetCreaturePermanent(filter);
this.getSpellAbility().addTarget(target);
this.getSpellAbility().addTarget(target);
// <strong><EFBFBD></strong> Counter target spell unless its controller pays {3}.
Mode mode = new Mode();
mode.getEffects().add(new CounterUnlessPaysEffect(new GenericManaCost(3)));
mode.getTargets().add(new TargetSpell());
this.getSpellAbility().addMode(mode);
// <strong><EFBFBD></strong> Creatures with power 3 or less can't block this turn.
mode = new Mode();
mode.getEffects().add(new CantBlockAllEffect(filterCantBlock, Duration.EndOfTurn));
this.getSpellAbility().addMode(mode);
}
public TemurCharm(final TemurCharm card) {

View file

@ -54,11 +54,10 @@ public class WildInstincts extends CardImpl {
}
public WildInstincts(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{G}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}");
// Target creature you control gets +2/+2 until end of turn. It fights target creature an opponent controls.
Effect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn);
effect.setApplyEffectsAfter();
getSpellAbility().addEffect(effect);
getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
effect = new FightTargetsEffect();

View file

@ -42,8 +42,8 @@ import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.MeldCard;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
@ -66,7 +66,7 @@ public class WispweaverAngel extends CardImpl {
}
public WispweaverAngel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}");
this.subtype.add(SubType.ANGEL);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
@ -76,7 +76,6 @@ public class WispweaverAngel extends CardImpl {
// When Wispweaver Angel enters the battlefield, you may exile another target creature you control, then return that card to the battlefield under its owner's control.
Effect effect = new ExileTargetForSourceEffect();
effect.setApplyEffectsAfter();
Ability ability = new EntersBattlefieldTriggeredAbility(effect, true);
ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false));
ability.addEffect(new WispweaverAngelEffect());

View file

@ -49,7 +49,7 @@ import mage.target.TargetPermanent;
public class ZealousConscripts extends CardImpl {
public ZealousConscripts(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}");
this.subtype.add(SubType.HUMAN, SubType.WARRIOR);
this.power = new MageInt(3);

View file

@ -85,6 +85,7 @@ public class Dissension extends ExpansionSet {
cards.add(new SetCardInfo("Crypt Champion", 40, Rarity.UNCOMMON, mage.cards.c.CryptChampion.class));
cards.add(new SetCardInfo("Cytoplast Manipulator", 23, Rarity.RARE, mage.cards.c.CytoplastManipulator.class));
cards.add(new SetCardInfo("Cytoplast Root-Kin", 81, Rarity.RARE, mage.cards.c.CytoplastRootKin.class));
cards.add(new SetCardInfo("Cytoshape", 108, Rarity.RARE, mage.cards.c.Cytoshape.class));
cards.add(new SetCardInfo("Cytospawn Shambler", 82, Rarity.COMMON, mage.cards.c.CytospawnShambler.class));
cards.add(new SetCardInfo("Delirium Skeins", 41, Rarity.COMMON, mage.cards.d.DeliriumSkeins.class));
cards.add(new SetCardInfo("Demonfire", 60, Rarity.RARE, mage.cards.d.Demonfire.class));

View file

@ -47,50 +47,50 @@ public class ZendikarExpeditions extends ExpansionSet {
super("Zendikar Expeditions", "EXP", ExpansionSet.buildDate(2015, 10, 2), SetType.PROMOTIONAL);
this.hasBoosters = false;
this.hasBasicLands = false;
cards.add(new SetCardInfo("Ancient Tomb", 36, Rarity.MYTHIC, mage.cards.a.AncientTomb.class));
cards.add(new SetCardInfo("Arid Mesa", 24, Rarity.MYTHIC, mage.cards.a.AridMesa.class));
cards.add(new SetCardInfo("Blood Crypt", 8, Rarity.MYTHIC, mage.cards.b.BloodCrypt.class));
cards.add(new SetCardInfo("Bloodstained Mire", 18, Rarity.MYTHIC, mage.cards.b.BloodstainedMire.class));
cards.add(new SetCardInfo("Breeding Pool", 15, Rarity.MYTHIC, mage.cards.b.BreedingPool.class));
cards.add(new SetCardInfo("Canopy Vista", 5, Rarity.MYTHIC, mage.cards.c.CanopyVista.class));
cards.add(new SetCardInfo("Cascade Bluffs", 32, Rarity.MYTHIC, mage.cards.c.CascadeBluffs.class));
cards.add(new SetCardInfo("Cinder Glade", 4, Rarity.MYTHIC, mage.cards.c.CinderGlade.class));
cards.add(new SetCardInfo("Dust Bowl", 37, Rarity.MYTHIC, mage.cards.d.DustBowl.class));
cards.add(new SetCardInfo("Eye of Ugin", 38, Rarity.MYTHIC, mage.cards.e.EyeOfUgin.class));
cards.add(new SetCardInfo("Fetid Heath", 31, Rarity.MYTHIC, mage.cards.f.FetidHeath.class));
cards.add(new SetCardInfo("Fire-Lit Thicket", 29, Rarity.MYTHIC, mage.cards.f.FireLitThicket.class));
cards.add(new SetCardInfo("Flooded Grove", 35, Rarity.MYTHIC, mage.cards.f.FloodedGrove.class));
cards.add(new SetCardInfo("Flooded Strand", 16, Rarity.MYTHIC, mage.cards.f.FloodedStrand.class));
cards.add(new SetCardInfo("Forbidden Orchard", 39, Rarity.MYTHIC, mage.cards.f.ForbiddenOrchard.class));
cards.add(new SetCardInfo("Godless Shrine", 11, Rarity.MYTHIC, mage.cards.g.GodlessShrine.class));
cards.add(new SetCardInfo("Graven Cairns", 28, Rarity.MYTHIC, mage.cards.g.GravenCairns.class));
cards.add(new SetCardInfo("Hallowed Fountain", 6, Rarity.MYTHIC, mage.cards.h.HallowedFountain.class));
cards.add(new SetCardInfo("Horizon Canopy", 40, Rarity.MYTHIC, mage.cards.h.HorizonCanopy.class));
cards.add(new SetCardInfo("Kor Haven", 41, Rarity.MYTHIC, mage.cards.k.KorHaven.class));
cards.add(new SetCardInfo("Mana Confluence", 42, Rarity.MYTHIC, mage.cards.m.ManaConfluence.class));
cards.add(new SetCardInfo("Marsh Flats", 21, Rarity.MYTHIC, mage.cards.m.MarshFlats.class));
cards.add(new SetCardInfo("Misty Rainforest", 25, Rarity.MYTHIC, mage.cards.m.MistyRainforest.class));
cards.add(new SetCardInfo("Mystic Gate", 26, Rarity.MYTHIC, mage.cards.m.MysticGate.class));
cards.add(new SetCardInfo("Overgrown Tomb", 13, Rarity.MYTHIC, mage.cards.o.OvergrownTomb.class));
cards.add(new SetCardInfo("Polluted Delta", 17, Rarity.MYTHIC, mage.cards.p.PollutedDelta.class));
cards.add(new SetCardInfo("Prairie Stream", 1, Rarity.MYTHIC, mage.cards.p.PrairieStream.class));
cards.add(new SetCardInfo("Rugged Prairie", 34, Rarity.MYTHIC, mage.cards.r.RuggedPrairie.class));
cards.add(new SetCardInfo("Sacred Foundry", 14, Rarity.MYTHIC, mage.cards.s.SacredFoundry.class));
cards.add(new SetCardInfo("Scalding Tarn", 22, Rarity.MYTHIC, mage.cards.s.ScaldingTarn.class));
cards.add(new SetCardInfo("Smoldering Marsh", 3, Rarity.MYTHIC, mage.cards.s.SmolderingMarsh.class));
cards.add(new SetCardInfo("Steam Vents", 12, Rarity.MYTHIC, mage.cards.s.SteamVents.class));
cards.add(new SetCardInfo("Stomping Ground", 9, Rarity.MYTHIC, mage.cards.s.StompingGround.class));
cards.add(new SetCardInfo("Strip Mine", 43, Rarity.MYTHIC, mage.cards.s.StripMine.class));
cards.add(new SetCardInfo("Sunken Hollow", 2, Rarity.MYTHIC, mage.cards.s.SunkenHollow.class));
cards.add(new SetCardInfo("Sunken Ruins", 27, Rarity.MYTHIC, mage.cards.s.SunkenRuins.class));
cards.add(new SetCardInfo("Tectonic Edge", 44, Rarity.MYTHIC, mage.cards.t.TectonicEdge.class));
cards.add(new SetCardInfo("Temple Garden", 10, Rarity.MYTHIC, mage.cards.t.TempleGarden.class));
cards.add(new SetCardInfo("Twilight Mire", 33, Rarity.MYTHIC, mage.cards.t.TwilightMire.class));
cards.add(new SetCardInfo("Verdant Catacombs", 23, Rarity.MYTHIC, mage.cards.v.VerdantCatacombs.class));
cards.add(new SetCardInfo("Wasteland", 45, Rarity.MYTHIC, mage.cards.w.Wasteland.class));
cards.add(new SetCardInfo("Watery Grave", 7, Rarity.MYTHIC, mage.cards.w.WateryGrave.class));
cards.add(new SetCardInfo("Windswept Heath", 20, Rarity.MYTHIC, mage.cards.w.WindsweptHeath.class));
cards.add(new SetCardInfo("Wooded Bastion", 30, Rarity.MYTHIC, mage.cards.w.WoodedBastion.class));
cards.add(new SetCardInfo("Wooded Foothills", 19, Rarity.MYTHIC, mage.cards.w.WoodedFoothills.class));
cards.add(new SetCardInfo("Ancient Tomb", 36, Rarity.MYTHIC, mage.cards.a.AncientTomb.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Arid Mesa", 24, Rarity.MYTHIC, mage.cards.a.AridMesa.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Blood Crypt", 8, Rarity.MYTHIC, mage.cards.b.BloodCrypt.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Bloodstained Mire", 18, Rarity.MYTHIC, mage.cards.b.BloodstainedMire.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Breeding Pool", 15, Rarity.MYTHIC, mage.cards.b.BreedingPool.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Canopy Vista", 5, Rarity.MYTHIC, mage.cards.c.CanopyVista.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Cascade Bluffs", 32, Rarity.MYTHIC, mage.cards.c.CascadeBluffs.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Cinder Glade", 4, Rarity.MYTHIC, mage.cards.c.CinderGlade.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Dust Bowl", 37, Rarity.MYTHIC, mage.cards.d.DustBowl.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Eye of Ugin", 38, Rarity.MYTHIC, mage.cards.e.EyeOfUgin.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Fetid Heath", 31, Rarity.MYTHIC, mage.cards.f.FetidHeath.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Fire-Lit Thicket", 29, Rarity.MYTHIC, mage.cards.f.FireLitThicket.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Flooded Grove", 35, Rarity.MYTHIC, mage.cards.f.FloodedGrove.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Flooded Strand", 16, Rarity.MYTHIC, mage.cards.f.FloodedStrand.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Forbidden Orchard", 39, Rarity.MYTHIC, mage.cards.f.ForbiddenOrchard.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Godless Shrine", 11, Rarity.MYTHIC, mage.cards.g.GodlessShrine.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Graven Cairns", 28, Rarity.MYTHIC, mage.cards.g.GravenCairns.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Hallowed Fountain", 6, Rarity.MYTHIC, mage.cards.h.HallowedFountain.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Horizon Canopy", 40, Rarity.MYTHIC, mage.cards.h.HorizonCanopy.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Kor Haven", 41, Rarity.MYTHIC, mage.cards.k.KorHaven.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Mana Confluence", 42, Rarity.MYTHIC, mage.cards.m.ManaConfluence.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Marsh Flats", 21, Rarity.MYTHIC, mage.cards.m.MarshFlats.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Misty Rainforest", 25, Rarity.MYTHIC, mage.cards.m.MistyRainforest.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Mystic Gate", 26, Rarity.MYTHIC, mage.cards.m.MysticGate.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Overgrown Tomb", 13, Rarity.MYTHIC, mage.cards.o.OvergrownTomb.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Polluted Delta", 17, Rarity.MYTHIC, mage.cards.p.PollutedDelta.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Prairie Stream", 1, Rarity.MYTHIC, mage.cards.p.PrairieStream.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Rugged Prairie", 34, Rarity.MYTHIC, mage.cards.r.RuggedPrairie.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Sacred Foundry", 14, Rarity.MYTHIC, mage.cards.s.SacredFoundry.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Scalding Tarn", 22, Rarity.MYTHIC, mage.cards.s.ScaldingTarn.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Smoldering Marsh", 3, Rarity.MYTHIC, mage.cards.s.SmolderingMarsh.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Steam Vents", 12, Rarity.MYTHIC, mage.cards.s.SteamVents.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Stomping Ground", 9, Rarity.MYTHIC, mage.cards.s.StompingGround.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Strip Mine", 43, Rarity.MYTHIC, mage.cards.s.StripMine.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Sunken Hollow", 2, Rarity.MYTHIC, mage.cards.s.SunkenHollow.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Sunken Ruins", 27, Rarity.MYTHIC, mage.cards.s.SunkenRuins.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Tectonic Edge", 44, Rarity.MYTHIC, mage.cards.t.TectonicEdge.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Temple Garden", 10, Rarity.MYTHIC, mage.cards.t.TempleGarden.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Twilight Mire", 33, Rarity.MYTHIC, mage.cards.t.TwilightMire.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Verdant Catacombs", 23, Rarity.MYTHIC, mage.cards.v.VerdantCatacombs.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Wasteland", 45, Rarity.MYTHIC, mage.cards.w.Wasteland.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Watery Grave", 7, Rarity.MYTHIC, mage.cards.w.WateryGrave.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Windswept Heath", 20, Rarity.MYTHIC, mage.cards.w.WindsweptHeath.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Wooded Bastion", 30, Rarity.MYTHIC, mage.cards.w.WoodedBastion.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Wooded Foothills", 19, Rarity.MYTHIC, mage.cards.w.WoodedFoothills.class, FULL_ART_BFZ_VARIOUS));
}
}

View file

@ -31,5 +31,52 @@ public class AnnihilatorTest extends CardTestPlayerBase {
assertPermanentCount(playerA, 1);
}
/**
* I was attacked with an It that Betrays while i had an Academy Rector and
* with the annihilator trigger on the stack i cast Cauldron Haze targeting
* academy rector then sacrificed her to the annihilator trigger and chose
* not to exile her. My persist resolved before the second ability of it
* that betrays because i was not the active player, the game log shows:
*
* 9:18 AM: Ability triggers: Academy Rector [e15] - Persist (When this
* creature dies, if it had no -1/-1 counters on it, return it to the
* battlefield under its owner's control with a -1/-1 counter on it.)
*
* 9:19 AM: EllNubNub puts Academy Rector [e15] from graveyard onto the
* Battlefield
*
* 9:20 AM: hellmo puts Academy Rector [e15] from battlefield onto the
* Battlefield
*
* The It that Betrays trigger should have fissled, instead it stole her
* from my battlefield and removed the persist counter.
*/
@Test
public void testCardItThatBetrays() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// Choose any number of target creatures. Each of those creatures gains persist until end of turn.
// Persist (When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it.)
addCard(Zone.HAND, playerA, "Cauldron Haze", 1); // Instant {1}{W/B}
// When Academy Rector dies, you may exile it. If you do, search your library for an enchantment card, put that card onto the battlefield, then shuffle your library.
addCard(Zone.BATTLEFIELD, playerA, "Academy Rector", 1);
// Annihilator 2 (Whenever this creature attacks, defending player sacrifices two permanents.)
// Whenever an opponent sacrifices a nontoken permanent, put that card onto the battlefield under your control.
addCard(Zone.BATTLEFIELD, playerB, "It That Betrays");
attack(2, playerB, "It That Betrays");
setChoice(playerA, "Academy Rector"); // Annihilator
setChoice(playerA, "Plains"); // Annihilator
castSpell(2, PhaseStep.DECLARE_ATTACKERS, playerA, "Cauldron Haze", "Academy Rector", "Annihilator");
setChoice(playerA, "No"); // Academy Rector No Exile
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertGraveyardCount(playerA, "Cauldron Haze", 1);
assertPermanentCount(playerB, "Academy Rector", 0);
assertPowerToughness(playerA, "Academy Rector", 0, 1);
}
}

View file

@ -853,4 +853,45 @@ public class MorphTest extends CardTestPlayerBase {
assertTappedCount("Island", true, 3);
}
/**
* If you have Endless Whispers in play and a morph creature dies, it should
* be returned to play face up at end of turn under the control of an
* opponent.
*/
@Test
public void testMorphEndlessWhispers() {
/*
Quicksilver Dragon {4}{U}{U}
Creature - Dragon
5/5
Flying
{U}: If target spell has only one target and that target is Quicksilver Dragon, change that spell's target to another creature.
Morph {4}{U}
*/
addCard(Zone.HAND, playerA, "Quicksilver Dragon");
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
// Each creature has "When this creature dies, choose target opponent. That player puts this card from its owner's graveyard
// onto the battlefield under his or her control at the beginning of the next end step."
addCard(Zone.BATTLEFIELD, playerA, "Endless Whispers", 1);
addCard(Zone.HAND, playerB, "Lightning Bolt");
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Quicksilver Dragon");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "");
setStopAt(2, PhaseStep.UPKEEP);
execute();
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertGraveyardCount(playerA, "Quicksilver Dragon", 0);
assertPermanentCount(playerA, "Quicksilver Dragon", 0);
assertPermanentCount(playerB, "Quicksilver Dragon", 1);
}
}

View file

@ -0,0 +1,25 @@
package org.mage.test.cards.triggers;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class ShapeStealerTest extends CardTestPlayerBase {
private String shapeStealer = "Shape Stealer";
private String myojinOfCleansingFire = "Myojin of Cleansing Fire";
@Test
public void testShapeStealerSingleBlocker() {
addCard(Zone.BATTLEFIELD, playerA, shapeStealer);
addCard(Zone.BATTLEFIELD, playerB, myojinOfCleansingFire);
attack(1, playerA, shapeStealer);
block(1, playerB, myojinOfCleansingFire, shapeStealer);
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertDamageReceived(playerA, shapeStealer, 4);
assertPowerToughness(playerA, shapeStealer, 4, 6);
assertDamageReceived(playerB, myojinOfCleansingFire, 4);
}
}

View file

@ -220,10 +220,8 @@ public abstract class AbilityImpl implements Ability {
* too late Example:
* {@link org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy}
*/
if (effect.applyEffectsAfter()) {
game.applyEffects();
game.getState().getTriggers().checkStateTriggers(game);
}
game.applyEffects();
game.getState().getTriggers().checkStateTriggers(game);
}
}
return result;

View file

@ -28,6 +28,8 @@
*/
package mage.abilities;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import mage.MageObject;
import mage.constants.Zone;
import mage.game.Game;
@ -36,15 +38,12 @@ import mage.game.events.NumberOfTriggersEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author BetaSteward_at_googlemail.com
* <p>
* This class uses ConcurrentHashMap to avoid ConcurrentModificationExceptions.
* See ticket https://github.com/magefree/mage/issues/966 and
* https://github.com/magefree/mage/issues/473
* <p>
* This class uses ConcurrentHashMap to avoid ConcurrentModificationExceptions.
* See ticket https://github.com/magefree/mage/issues/966 and
* https://github.com/magefree/mage/issues/473
*/
public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbility> {
@ -63,7 +62,7 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
}
public void checkStateTriggers(Game game) {
for (Iterator<TriggeredAbility> it = this.values().iterator(); it.hasNext(); ) {
for (Iterator<TriggeredAbility> it = this.values().iterator(); it.hasNext();) {
TriggeredAbility ability = it.next();
if (ability instanceof StateTriggeredAbility && ((StateTriggeredAbility) ability).canTrigger(game)) {
checkTrigger(ability, null, game);
@ -72,7 +71,7 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
}
public void checkTriggers(GameEvent event, Game game) {
for (Iterator<TriggeredAbility> it = this.values().iterator(); it.hasNext(); ) {
for (Iterator<TriggeredAbility> it = this.values().iterator(); it.hasNext();) {
TriggeredAbility ability = it.next();
if (ability.checkEventType(event, game)) {
checkTrigger(ability, event, game);
@ -98,7 +97,10 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
// need to check if object was face down for dies and destroy events because the ability triggers in the new zone, zone counter -1 is used
Permanent permanent = (Permanent) game.getLastKnownInformation(ability.getSourceId(), Zone.BATTLEFIELD, ability.getSourceObjectZoneChangeCounter() - 1);
if (permanent != null) {
if (!ability.getWorksFaceDown() && permanent.isFaceDown(game)) {
if (permanent.isFaceDown(game)
&& !isGainedAbility(ability, permanent) // the face down creature got the ability from an effect => so it should work
&& !ability.getWorksFaceDown()) { // the ability is declared to work also face down
// Not all triggered abilities of face down creatures work if they are faced down
return;
}
controllerSet = true;
@ -130,8 +132,8 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
/**
* Adds a by sourceId gained triggered ability
*
* @param ability - the gained ability
* @param sourceId - the source that assigned the ability
* @param ability - the gained ability
* @param sourceId - the source that assigned the ability
* @param attachedTo - the object that gained the ability
*/
public void add(TriggeredAbility ability, UUID sourceId, MageObject attachedTo) {
@ -161,7 +163,6 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
return key;
}
public void removeAbilitiesOfSource(UUID sourceId) {
keySet().removeIf(key -> key.endsWith(sourceId.toString()));
}
@ -171,6 +172,10 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
sources.clear();
}
public boolean isGainedAbility(TriggeredAbility abilityToCheck, MageObject attachedTo) {
return sources.containsKey(getKey(abilityToCheck, attachedTo));
}
public void removeAbilitiesOfNonExistingSources(Game game) {
// e.g. Token that had triggered abilities

View file

@ -1,16 +1,16 @@
/*
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
@ -20,7 +20,7 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
@ -53,12 +53,10 @@ public class OpponentSacrificesNonTokenPermanentTriggeredAbility extends Trigger
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (game.getPlayer(getControllerId()).hasOpponent(event.getPlayerId(), game)) {
if (game.getPlayer(getControllerId()).hasOpponent(event.getPlayerId(), game)) {
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
if (permanent != null && !(permanent instanceof PermanentToken) ) {
for (Effect effect : getEffects()) {
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
}
if (permanent != null && !(permanent instanceof PermanentToken)) {
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game.getState().getZoneChangeCounter(event.getTargetId())));
return true;
}
}
@ -75,4 +73,4 @@ public class OpponentSacrificesNonTokenPermanentTriggeredAbility extends Trigger
return new OpponentSacrificesNonTokenPermanentTriggeredAbility(this);
}
}
}

View file

@ -30,7 +30,6 @@ package mage.abilities.dynamicvalue.common;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.cards.Card;
import mage.game.Game;
/**
@ -39,37 +38,21 @@ import mage.game.Game;
*/
public class SweepNumber implements DynamicValue {
private int zoneChangeCounter = 0;
private final String sweepSubtype;
private final boolean previousZone;
public SweepNumber(String sweepSubtype, boolean previousZone) {
public SweepNumber(String sweepSubtype) {
this.sweepSubtype = sweepSubtype;
this.previousZone = previousZone;
}
@Override
public int calculate(Game game, Ability source, Effect effect) {
if (zoneChangeCounter == 0) {
Card card = game.getCard(source.getSourceId());
if (card != null) {
zoneChangeCounter = card.getZoneChangeCounter(game);
if (previousZone) {
zoneChangeCounter--;
}
}
}
int number = 0;
Integer sweepNumber = (Integer) game.getState().getValue(new StringBuilder("sweep").append(source.getSourceId()).append(zoneChangeCounter).toString());
if (sweepNumber != null) {
number = sweepNumber;
}
return number;
Integer sweepNumber = (Integer) game.getState().getValue("sweep" + source.getSourceId() + game.getState().getZoneChangeCounter(source.getSourceId()));
return sweepNumber != null ? sweepNumber : 0;
}
@Override
public SweepNumber copy() {
return new SweepNumber(sweepSubtype, previousZone);
return new SweepNumber(sweepSubtype);
}
@Override
@ -79,6 +62,6 @@ public class SweepNumber implements DynamicValue {
@Override
public String getMessage() {
return new StringBuilder("the number of ").append(sweepSubtype).append(sweepSubtype.endsWith("s") ? "":"s").append(" returned this way").toString();
return "the number of " + sweepSubtype + (sweepSubtype.endsWith("s") ? "" : "s") + " returned this way";
}
}

View file

@ -88,10 +88,6 @@ public interface Effect extends Serializable {
Object getValue(String key);
void setApplyEffectsAfter();
boolean applyEffectsAfter();
Effect copy();
}

View file

@ -138,18 +138,4 @@ public abstract class EffectImpl implements Effect {
}
return values.get(key);
}
/**
* If set, the game.applyEffects() method will be called to apply the
* effects before the next effect (of the same ability) will resolve.
*/
@Override
public void setApplyEffectsAfter() {
applyEffectsAfter = true;
}
@Override
public boolean applyEffectsAfter() {
return applyEffectsAfter;
}
}

View file

@ -37,6 +37,7 @@ import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -54,15 +55,15 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
protected boolean lockedIn = false;
public BoostControlledEffect(int power, int toughness, Duration duration) {
this(power, toughness, duration, new FilterCreaturePermanent("creatures"), false);
this(power, toughness, duration, StaticFilters.FILTER_PERMANENT_CREATURES, false);
}
public BoostControlledEffect(DynamicValue power, DynamicValue toughness, Duration duration) {
this(power, toughness, duration, new FilterCreaturePermanent("creatures"), false);
this(power, toughness, duration, StaticFilters.FILTER_PERMANENT_CREATURES, false);
}
public BoostControlledEffect(int power, int toughness, Duration duration, boolean excludeSource) {
this(power, toughness, duration, new FilterCreaturePermanent("creatures"), excludeSource);
this(power, toughness, duration, StaticFilters.FILTER_PERMANENT_CREATURES, excludeSource);
}
public BoostControlledEffect(int power, int toughness, Duration duration, FilterCreaturePermanent filter) {
@ -91,7 +92,7 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
super(duration, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature);
this.power = power;
this.toughness = toughness;
this.filter = filter;
this.filter = (filter == null ? StaticFilters.FILTER_PERMANENT_CREATURES : filter);
this.excludeSource = excludeSource;
this.lockedIn = lockedIn;
setText();

View file

@ -70,7 +70,7 @@ public class SweepEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
FilterPermanent filter = new FilterControlledLandPermanent(new StringBuilder("any number of ").append(sweepSubtype).append("s you control").toString());
FilterPermanent filter = new FilterControlledLandPermanent("any number of " + sweepSubtype + "s you control");
filter.add(new SubtypePredicate(sweepSubtype));
Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true);
if (controller.chooseTarget(outcome, target, source, game)) {

View file

@ -126,8 +126,8 @@ public class FlashbackAbility extends SpellAbility {
spellAbilityCopy.setId(this.getId());
spellAbilityCopy.getManaCosts().clear();
spellAbilityCopy.getManaCostsToPay().clear();
spellAbilityCopy.getCosts().addAll(this.getCosts());
spellAbilityCopy.addCost(this.getManaCosts());
spellAbilityCopy.getCosts().addAll(this.getCosts().copy());
spellAbilityCopy.addCost(this.getManaCosts().copy());
spellAbilityCopy.setSpellAbilityCastMode(this.getSpellAbilityCastMode());
spellAbilityToResolve = spellAbilityCopy;
ContinuousEffect effect = new FlashbackReplacementEffect();

View file

@ -1,4 +1,4 @@
/*
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
@ -24,8 +24,7 @@
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
*/
package mage.abilities.keyword;
import mage.abilities.TriggeredAbilityImpl;
@ -41,7 +40,6 @@ import mage.game.events.GameEvent.EventType;
*
* @author LevelX2
*/
public class InspiredAbility extends TriggeredAbilityImpl {
public InspiredAbility(Effect effect) {
@ -73,6 +71,6 @@ public class InspiredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return new StringBuilder("<i>Inspired</i> - Whenever {this} becomes untapped, ").append(super.getRule()).toString();
return "<i>Inspired</i> - Whenever {this} becomes untapped, " + super.getRule();
}
}

View file

@ -24,11 +24,11 @@
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
*/
package mage.abilities.keyword;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
@ -45,61 +45,67 @@ import mage.watchers.common.MiracleWatcher;
/**
* 702.92. Miracle
*
* 702.92a Miracle is a static ability linked to a triggered ability (see rule 603.10).
* "Miracle [cost]" means "You may reveal this card from your hand as you draw it if
* it's the first card you've drawn this turn. When you reveal this card this way,
* you may cast it by paying [cost] rather than its mana cost."
* 702.92a Miracle is a static ability linked to a triggered ability (see rule
* 603.10). "Miracle [cost]" means "You may reveal this card from your hand as
* you draw it if it's the first card you've drawn this turn. When you reveal
* this card this way, you may cast it by paying [cost] rather than its mana
* cost."
*
* 702.92b If a player chooses to reveal a card using its miracle ability, he or she
* plays with that card revealed until that card leaves his or her hand, that ability
* resolves, or that ability otherwise leaves the stack.
* 702.92b If a player chooses to reveal a card using its miracle ability, he or
* she plays with that card revealed until that card leaves his or her hand,
* that ability resolves, or that ability otherwise leaves the stack.
*
* You can cast a card for its miracle cost only as the miracle triggered ability resolves.
* If you don't want to cast it at that time (or you can't cast it, perhaps because
* there are no legal targets available), you won't be able to cast it later for the miracle cost.
* You can cast a card for its miracle cost only as the miracle triggered
* ability resolves. If you don't want to cast it at that time (or you can't
* cast it, perhaps because there are no legal targets available), you won't be
* able to cast it later for the miracle cost.
*
* RULINGS:
* You still draw the card, whether you use the miracle ability or not. Any ability that
* triggers whenever you draw a card, for example, will trigger. If you don't cast the card
* using its miracle ability, it will remain in your hand.
* RULINGS: You still draw the card, whether you use the miracle ability or not.
* Any ability that triggers whenever you draw a card, for example, will
* trigger. If you don't cast the card using its miracle ability, it will remain
* in your hand.
*
* You can reveal and cast a card with miracle on any turn, not just your own, if it's the
* first card you've drawn that turn.
* You can reveal and cast a card with miracle on any turn, not just your own,
* if it's the first card you've drawn that turn.
*
* You don't have to reveal a drawn card with miracle if you don't wish to cast it at that time.
* You don't have to reveal a drawn card with miracle if you don't wish to cast
* it at that time.
*
* You can cast a card for its miracle cost only as the miracle triggered ability resolves.
* If you don't want to cast it at that time (or you can't cast it, perhaps because there are
* no legal targets available), you won't be able to cast it later for the miracle cost.
* You can cast a card for its miracle cost only as the miracle triggered
* ability resolves. If you don't want to cast it at that time (or you can't
* cast it, perhaps because there are no legal targets available), you won't be
* able to cast it later for the miracle cost.
*
* You cast the card with miracle during the resolution of the triggered ability. Ignore any timing
* restrictions based on the card's type.
* You cast the card with miracle during the resolution of the triggered
* ability. Ignore any timing restrictions based on the card's type.
*
* It's important to reveal a card with miracle before it is mixed with the other cards in your hand.
* It's important to reveal a card with miracle before it is mixed with the
* other cards in your hand.
*
* Multiple card draws are always treated as a sequence of individual card draws. For example, if
* you haven't drawn any cards yet during a turn and cast a spell that instructs you to draw three
* cards, you'll draw them one at a time. Only the first card drawn this way may be revealed and cast
* using its miracle ability.
* Multiple card draws are always treated as a sequence of individual card
* draws. For example, if you haven't drawn any cards yet during a turn and cast
* a spell that instructs you to draw three cards, you'll draw them one at a
* time. Only the first card drawn this way may be revealed and cast using its
* miracle ability.
*
* If the card with miracle leaves your hand before the triggered ability resolves, you won't be able
* to cast it using its miracle ability.
* If the card with miracle leaves your hand before the triggered ability
* resolves, you won't be able to cast it using its miracle ability.
*
* You draw your opening hand before any turn begins. Cards you draw for your opening hand
* can't be cast using miracle.
* You draw your opening hand before any turn begins. Cards you draw for your
* opening hand can't be cast using miracle.
*
* @author noxx, LevelX2
*/
public class MiracleAbility extends TriggeredAbilityImpl {
private static final String staticRule = " <i>(You may cast this card for its miracle cost when you draw it if it's the first card you drew this turn.)</i>";
private String ruleText;
@SuppressWarnings("unchecked")
public MiracleAbility(Card card, ManaCosts miracleCosts) {
super(Zone.HAND, new MiracleEffect((ManaCosts<ManaCost>)miracleCosts), true);
addWatcher(new MiracleWatcher());
ruleText = "Miracle " + miracleCosts.getText() + staticRule;
super(Zone.HAND, new MiracleEffect((ManaCosts<ManaCost>) miracleCosts), true);
addWatcher(new MiracleWatcher());
ruleText = "Miracle " + miracleCosts.getText() + staticRule;
}
public MiracleAbility(final MiracleAbility ability) {
@ -161,17 +167,12 @@ class MiracleEffect extends OneShotEffect {
// use target pointer here, so it's the same card that triggered the event (not gone back to library e.g.)
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (controller != null && card != null) {
ManaCosts<ManaCost> costRef = card.getSpellAbility().getManaCostsToPay();
SpellAbility abilityToCast = card.getSpellAbility().copy();
ManaCosts<ManaCost> costRef = abilityToCast.getManaCostsToPay();
// replace with the new cost
costRef.clear();
costRef.add(miracleCosts);
controller.cast(card.getSpellAbility(), game, false);
// Reset the casting costs (in case the player cancels cast and plays the card later)
costRef.clear();
for (ManaCost manaCost : card.getSpellAbility().getManaCosts()) {
costRef.add(manaCost);
}
controller.cast(abilityToCast, game, false);
return true;
}
return false;

View file

@ -179,13 +179,13 @@ public final class StaticFilters {
static {
FILTER_CONTROLLED_CREATURE.setLockedFilter(true);
}
}
public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_CREATURES = new FilterControlledCreaturePermanent("creatures you control");
static {
FILTER_CONTROLLED_CREATURES.setLockedFilter(true);
}
public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_A_CREATURE = new FilterControlledCreaturePermanent("a creature you control");
static {
@ -210,11 +210,15 @@ public final class StaticFilters {
static {
FILTER_LAND.setLockedFilter(true);
}
public static final FilterLandPermanent FILTER_LANDS = new FilterLandPermanent("lands");
static {
FILTER_LANDS.setLockedFilter(true);
}
public static final FilterLandPermanent FILTER_LANDS_NONBASIC = FilterLandPermanent.nonbasicLands();
public static final FilterBasicLandCard FILTER_BASIC_LAND_CARD = new FilterBasicLandCard();
static {