Merge remote-tracking branch 'origin/master' into m21_test

This commit is contained in:
Ingmar Goudt 2020-07-25 12:38:33 +02:00
commit 41b7439403
95 changed files with 1935 additions and 1452 deletions

View file

@ -881,7 +881,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
popupDebug.add(menuDebugTestCardRenderModesDialog); popupDebug.add(menuDebugTestCardRenderModesDialog);
setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
setMinimumSize(new java.awt.Dimension(1024, 768)); setMinimumSize(new java.awt.Dimension(1024, 500));
desktopPane.setBackground(new java.awt.Color(204, 204, 204)); desktopPane.setBackground(new java.awt.Color(204, 204, 204));

View file

@ -73,8 +73,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
} }
trimGrid(); trimGrid();
layoutGrid(); layoutGrid();
cardScroll.revalidate(); repaintGrid();
cardScroll.repaint();
} }
} }
@ -315,8 +314,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
// Remove empty rows / cols / spaces in stacks // Remove empty rows / cols / spaces in stacks
trimGrid(); trimGrid();
layoutGrid(); layoutGrid();
cardScroll.revalidate(); repaintGrid();
cardScroll.repaint();
} else { } else {
// Add new cards to grid // Add new cards to grid
for (CardView card : cards) { for (CardView card : cards) {
@ -325,14 +323,14 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
eventSource.fireEvent(card, ClientEventType.ADD_SPECIFIC_CARD); eventSource.fireEvent(card, ClientEventType.ADD_SPECIFIC_CARD);
} }
layoutGrid(); layoutGrid();
cardContent.repaint(); repaintGrid();
} }
} }
public void changeGUISize() { public void changeGUISize() {
layoutGrid(); layoutGrid();
cardScroll.getVerticalScrollBar().setUnitIncrement(CardRenderer.getCardTopHeight(getCardWidth())); cardScroll.getVerticalScrollBar().setUnitIncrement(CardRenderer.getCardTopHeight(getCardWidth()));
cardContent.repaint(); repaintGrid();
} }
public void cleanUp() { public void cleanUp() {
@ -386,7 +384,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
} }
trimGrid(); trimGrid();
layoutGrid(); layoutGrid();
cardContent.repaint(); repaintGrid();
} }
public DeckCardLayout getCardLayout() { public DeckCardLayout getCardLayout() {
@ -710,6 +708,47 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
// Editting mode // Editting mode
this.mode = Constants.DeckEditorMode.LIMITED_BUILDING; this.mode = Constants.DeckEditorMode.LIMITED_BUILDING;
// Content
cardContent = new JLayeredPane();
cardContent.setLayout(null);
cardContent.setOpaque(false);
cardContent.addMouseListener(new MouseAdapter() {
private boolean isDragging = false;
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
isDragging = true;
beginSelectionDrag(e.getX(), e.getY(), e.isShiftDown());
updateSelectionDrag(e.getX(), e.getY());
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (isDragging) {
isDragging = false;
updateSelectionDrag(e.getX(), e.getY());
endSelectionDrag(e.getX(), e.getY());
}
}
});
cardContent.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
updateSelectionDrag(e.getX(), e.getY());
}
});
cardScroll = new JScrollPane(cardContent,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
cardScroll.setOpaque(false);
cardScroll.getViewport().setOpaque(false);
cardScroll.setViewportBorder(BorderFactory.createEmptyBorder());
cardScroll.setBorder(BorderFactory.createLineBorder(Color.gray, 1));
cardScroll.getVerticalScrollBar().setUnitIncrement(CardRenderer.getCardTopHeight(getCardWidth()));
this.add(cardScroll, BorderLayout.CENTER);
// Toolbar // Toolbar
sortButton = new JButton("Sort"); sortButton = new JButton("Sort");
filterButton = new JButton("Filter"); filterButton = new JButton("Filter");
@ -757,56 +796,15 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
cardSizeMod = (float) Math.pow(2, sliderFrac); cardSizeMod = (float) Math.pow(2, sliderFrac);
// Update grid // Update grid
layoutGrid(); layoutGrid();
cardContent.repaint(); repaintGrid();
} }
}); });
cardSizeSliderLabel = new JLabel("Card Size:"); cardSizeSliderLabel = new JLabel("Card size:");
sliderPanel.add(cardSizeSliderLabel); sliderPanel.add(cardSizeSliderLabel);
sliderPanel.add(cardSizeSlider); sliderPanel.add(cardSizeSlider);
toolbar.add(sliderPanel, BorderLayout.EAST); toolbar.add(sliderPanel, BorderLayout.EAST);
this.add(toolbar, BorderLayout.NORTH); this.add(toolbar, BorderLayout.NORTH);
// Content
cardContent = new JLayeredPane();
cardContent.setLayout(null);
cardContent.setOpaque(false);
cardContent.addMouseListener(new MouseAdapter() {
private boolean isDragging = false;
@Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
isDragging = true;
beginSelectionDrag(e.getX(), e.getY(), e.isShiftDown());
updateSelectionDrag(e.getX(), e.getY());
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (isDragging) {
isDragging = false;
updateSelectionDrag(e.getX(), e.getY());
endSelectionDrag(e.getX(), e.getY());
}
}
});
cardContent.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
updateSelectionDrag(e.getX(), e.getY());
}
});
cardScroll = new JScrollPane(cardContent,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
cardScroll.setOpaque(false);
cardScroll.getViewport().setOpaque(false);
cardScroll.setViewportBorder(BorderFactory.createEmptyBorder());
cardScroll.setBorder(BorderFactory.createLineBorder(Color.gray, 1));
cardScroll.getVerticalScrollBar().setUnitIncrement(CardRenderer.getCardTopHeight(getCardWidth()));
this.add(cardScroll, BorderLayout.CENTER);
// Insert arrow // Insert arrow
insertArrow = new JLabel(); insertArrow = new JLabel();
insertArrow.setSize(20, 20); insertArrow.setSize(20, 20);
@ -1230,7 +1228,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
// And finally rerender // And finally rerender
layoutGrid(); layoutGrid();
repaint(); repaintGrid();
} }
public void reselectBy() { public void reselectBy() {
@ -1340,7 +1338,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
// And finally rerender // And finally rerender
layoutGrid(); layoutGrid();
repaint(); repaintGrid();
} }
private static final Pattern pattern = Pattern.compile(".*Add(.*)(\\{[WUBRGXC]\\})"); private static final Pattern pattern = Pattern.compile(".*Add(.*)(\\{[WUBRGXC]\\})");
@ -1568,8 +1566,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
} }
layoutGrid(); layoutGrid();
cardScroll.revalidate(); repaintGrid();
repaint();
JOptionPane.showMessageDialog(null, "Added " + pimpedCards.size() + " cards. You can select them and the originals by choosing 'Multiples'"); JOptionPane.showMessageDialog(null, "Added " + pimpedCards.size() + " cards. You can select them and the originals by choosing 'Multiples'");
} }
} }
@ -1609,8 +1606,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
} }
cardGrid = newCardGrid; cardGrid = newCardGrid;
layoutGrid(); layoutGrid();
cardScroll.revalidate(); repaintGrid();
repaint();
} }
// Update the contents of the card grid // Update the contents of the card grid
@ -1734,10 +1730,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
if (didModify) { if (didModify) {
// Update layout // Update layout
layoutGrid(); layoutGrid();
repaintGrid();
// Update draw
cardScroll.revalidate();
repaint();
} }
} }
@ -1877,9 +1870,7 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
eventSource.fireEvent(card, ClientEventType.ADD_SPECIFIC_CARD); eventSource.fireEvent(card, ClientEventType.ADD_SPECIFIC_CARD);
// Update layout // Update layout
layoutGrid(); layoutGrid();
// Update draw repaintGrid();
cardScroll.revalidate();
repaint();
} }
} }
@ -2083,6 +2074,12 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg
return (int) (1.4 * getCardWidth()); return (int) (1.4 * getCardWidth());
} }
private void repaintGrid() {
cardScroll.revalidate();
cardScroll.repaint();
repaint();
}
/** /**
* Position all of the card views correctly * Position all of the card views correctly
*/ */

View file

@ -11,39 +11,45 @@
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,121,0,0,4,76"/>
</AuxValues> </AuxValues>
<Layout> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="deckAreaSplitPane" alignment="0" pref="918" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="deckAreaSplitPane" alignment="0" pref="377" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents> <SubComponents>
<Container class="javax.swing.JSplitPane" name="deckAreaSplitPane"> <Container class="javax.swing.JSplitPane" name="deckAreaSplitPane">
<Properties> <Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/> <Border info="null"/>
</Property> </Property>
<Property name="resizeWeight" type="double" value="0.6"/> <Property name="dividerSize" type="int" value="10"/>
<Property name="resizeWeight" type="double" value="0.5"/>
</Properties> </Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents> <SubComponents>
<Component class="mage.client.cards.DragCardGrid" name="dragCardGrid1"> <Component class="mage.client.cards.DragCardGrid" name="deckList">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[200, 56]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/> <JSplitPaneConstraints position="left"/>
</Constraint> </Constraint>
</Constraints> </Constraints>
</Component> </Component>
<Component class="mage.client.cards.DragCardGrid" name="dragCardGrid2"> <Component class="mage.client.cards.DragCardGrid" name="sideboardList">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[200, 56]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/> <JSplitPaneConstraints position="right"/>

View file

@ -1,9 +1,3 @@
/*
* DeckArea.java
*
* Created on Feb 18, 2010, 3:10:39 PM
*/
package mage.client.deckeditor; package mage.client.deckeditor;
import mage.cards.Card; import mage.cards.Card;
@ -26,7 +20,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class DeckArea extends javax.swing.JPanel { public class DeckArea extends javax.swing.JPanel {
@ -38,7 +31,6 @@ public class DeckArea extends javax.swing.JPanel {
private BigCard lastBigCard = null; private BigCard lastBigCard = null;
private int dividerLocationNormal = 0; private int dividerLocationNormal = 0;
private int dividerLocationLimited = 0; private int dividerLocationLimited = 0;
private static final boolean isLimitedBuildingOrientation = false;
public DeckCardLayout getCardLayout() { public DeckCardLayout getCardLayout() {
return deckList.getCardLayout(); return deckList.getCardLayout();
@ -170,7 +162,7 @@ public class DeckArea extends javax.swing.JPanel {
}); });
} }
public Settings saveSettings() { public Settings saveSettings(boolean isLimitedBuildingOrientation) {
Settings settings = new Settings(); Settings settings = new Settings();
settings.maindeckSettings = deckList.saveSettings(); settings.maindeckSettings = deckList.saveSettings();
settings.sideboardSetings = sideboardList.saveSettings(); settings.sideboardSetings = sideboardList.saveSettings();
@ -184,7 +176,7 @@ public class DeckArea extends javax.swing.JPanel {
return settings; return settings;
} }
public void loadSettings(Settings s) { public void loadSettings(Settings s, boolean isLimitedBuildingOrientation) {
if (s != null) { if (s != null) {
deckList.loadSettings(s.maindeckSettings); deckList.loadSettings(s.maindeckSettings);
sideboardList.loadSettings(s.sideboardSetings); sideboardList.loadSettings(s.sideboardSetings);
@ -215,8 +207,8 @@ public class DeckArea extends javax.swing.JPanel {
private void setGUISize() { private void setGUISize() {
} }
public void setOrientation(boolean limitedBuildingOrientation) { public void setOrientation(boolean isLimitedBuildingOrientation) {
if (limitedBuildingOrientation) { if (isLimitedBuildingOrientation) {
deckAreaSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); deckAreaSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
if (dividerLocationLimited != 0) { if (dividerLocationLimited != 0) {
deckAreaSplitPane.setDividerLocation(dividerLocationLimited); deckAreaSplitPane.setDividerLocation(dividerLocationLimited);
@ -298,21 +290,19 @@ public class DeckArea extends javax.swing.JPanel {
deckList = new mage.client.cards.DragCardGrid(); deckList = new mage.client.cards.DragCardGrid();
sideboardList = new mage.client.cards.DragCardGrid(); sideboardList = new mage.client.cards.DragCardGrid();
setLayout(new java.awt.BorderLayout());
deckAreaSplitPane.setBorder(null); deckAreaSplitPane.setBorder(null);
deckAreaSplitPane.setResizeWeight(0.6); deckAreaSplitPane.setDividerSize(10);
deckAreaSplitPane.setResizeWeight(0.5);
deckList.setMinimumSize(new java.awt.Dimension(200, 56));
deckAreaSplitPane.setLeftComponent(deckList); deckAreaSplitPane.setLeftComponent(deckList);
sideboardList.setMinimumSize(new java.awt.Dimension(200, 56));
deckAreaSplitPane.setRightComponent(sideboardList); deckAreaSplitPane.setRightComponent(sideboardList);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); add(deckAreaSplitPane, java.awt.BorderLayout.CENTER);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 918, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(deckAreaSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
public DragCardGrid getDeckList() { public DragCardGrid getDeckList() {

View file

@ -20,6 +20,11 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents> <SubComponents>
<Component class="mage.client.deckeditor.DeckEditorPanel" name="deckEditorPanel1"> <Component class="mage.client.deckeditor.DeckEditorPanel" name="deckEditorPanel1">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[1000, 500]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/> <BorderConstraints direction="Center"/>

View file

@ -74,6 +74,7 @@ public class DeckEditorPane extends MagePane {
deckEditorPanel1 = new mage.client.deckeditor.DeckEditorPanel(); deckEditorPanel1 = new mage.client.deckeditor.DeckEditorPanel();
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 32767)); filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 32767));
deckEditorPanel1.setMinimumSize(new java.awt.Dimension(1000, 500));
getContentPane().add(deckEditorPanel1, java.awt.BorderLayout.CENTER); getContentPane().add(deckEditorPanel1, java.awt.BorderLayout.CENTER);
getContentPane().add(filler1, java.awt.BorderLayout.NORTH); getContentPane().add(filler1, java.awt.BorderLayout.NORTH);
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View file

@ -33,6 +33,7 @@
<SubComponents> <SubComponents>
<Container class="javax.swing.JSplitPane" name="panelRight"> <Container class="javax.swing.JSplitPane" name="panelRight">
<Properties> <Properties>
<Property name="dividerSize" type="int" value="10"/>
<Property name="orientation" type="int" value="0"/> <Property name="orientation" type="int" value="0"/>
<Property name="resizeWeight" type="double" value="0.5"/> <Property name="resizeWeight" type="double" value="0.5"/>
</Properties> </Properties>
@ -47,6 +48,11 @@
</Constraints> </Constraints>
</Component> </Component>
<Component class="mage.client.deckeditor.DeckArea" name="deckArea"> <Component class="mage.client.deckeditor.DeckArea" name="deckArea">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[200, 56]"/>
</Property>
</Properties>
<Constraints> <Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription"> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="bottom"/> <JSplitPaneConstraints position="bottom"/>

View file

@ -78,7 +78,6 @@ public class DeckEditorPanel extends javax.swing.JPanel {
deckArea.setOpaque(false); deckArea.setOpaque(false);
panelLeft.setOpaque(false); panelLeft.setOpaque(false);
panelRight.setOpaque(false); panelRight.setOpaque(false);
restoreDividerLocationsAndDeckAreaSettings();
countdown = new javax.swing.Timer(1000, countdown = new javax.swing.Timer(1000,
e -> { e -> {
if (--timeout > 0) { if (--timeout > 0) {
@ -93,13 +92,18 @@ public class DeckEditorPanel extends javax.swing.JPanel {
} }
}); });
// Set up tracking to save the deck editor settings when the deck editor is hidden. // save editor settings dynamicly on hides (e.g. app close)
addHierarchyListener((HierarchyEvent e) -> { addHierarchyListener((HierarchyEvent e) -> {
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) { if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
if (!isShowing()) { if (!isShowing()) {
// It's bugged and called on sideboarding creates too (before load). So:
// * for free mode - save here
// * for draft/sideboarding - save on cleanup call
if (mode == DeckEditorMode.FREE_BUILDING) {
saveDividerLocationsAndDeckAreaSettings(); saveDividerLocationsAndDeckAreaSettings();
} }
} }
}
}); });
} }
@ -127,21 +131,32 @@ public class DeckEditorPanel extends javax.swing.JPanel {
} }
private void saveDividerLocationsAndDeckAreaSettings() { private void saveDividerLocationsAndDeckAreaSettings() {
PreferencesDialog.saveValue(PreferencesDialog.KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION, Integer.toString(panelRight.getDividerLocation())); boolean isLimitedBuildingOrientation = (mode != DeckEditorMode.FREE_BUILDING);
PreferencesDialog.saveValue(PreferencesDialog.KEY_EDITOR_DECKAREA_SETTINGS, this.deckArea.saveSettings().toString()); if (isLimitedBuildingOrientation) {
PreferencesDialog.saveValue(PreferencesDialog.KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION_LIMITED, Integer.toString(panelRight.getDividerLocation()));
} else {
PreferencesDialog.saveValue(PreferencesDialog.KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION_NORMAL, Integer.toString(panelRight.getDividerLocation()));
}
PreferencesDialog.saveValue(PreferencesDialog.KEY_EDITOR_DECKAREA_SETTINGS, this.deckArea.saveSettings(isLimitedBuildingOrientation).toString());
} }
private void restoreDividerLocationsAndDeckAreaSettings() { private void restoreDividerLocationsAndDeckAreaSettings() {
// Load horizontal split position setting String dividerLocation = "";
String dividerLocation = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION, ""); boolean isLimitedBuildingOrientation = (mode != DeckEditorMode.FREE_BUILDING);
if (isLimitedBuildingOrientation) {
dividerLocation = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION_LIMITED, "");
} else {
dividerLocation = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION_NORMAL, "");
}
if (!dividerLocation.isEmpty()) { if (!dividerLocation.isEmpty()) {
panelRight.setDividerLocation(Integer.parseInt(dividerLocation)); panelRight.setDividerLocation(Integer.parseInt(dividerLocation));
} }
// Load deck area settings // Load deck area settings
this.deckArea.loadSettings( this.deckArea.loadSettings(
DeckArea.Settings.parse( DeckArea.Settings.parse(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_EDITOR_DECKAREA_SETTINGS, "")),
PreferencesDialog.getCachedValue(PreferencesDialog.KEY_EDITOR_DECKAREA_SETTINGS, ""))); isLimitedBuildingOrientation);
} }
public void changeGUISize() { public void changeGUISize() {
@ -157,11 +172,12 @@ public class DeckEditorPanel extends javax.swing.JPanel {
this.mode = mode; this.mode = mode;
this.btnAddLand.setVisible(false); this.btnAddLand.setVisible(false);
restoreDividerLocationsAndDeckAreaSettings();
switch (mode) { switch (mode) {
case LIMITED_BUILDING: case LIMITED_BUILDING:
this.btnAddLand.setVisible(true); this.btnAddLand.setVisible(true);
this.txtTimeRemaining.setVisible(true); this.txtTimeRemaining.setVisible(true);
// Fall through to sideboarding // Fall through to sideboarding (no break)
case SIDEBOARDING: case SIDEBOARDING:
this.btnSubmit.setVisible(true); this.btnSubmit.setVisible(true);
this.btnSubmitTimer.setVisible(true); this.btnSubmitTimer.setVisible(true);
@ -864,9 +880,12 @@ public class DeckEditorPanel extends javax.swing.JPanel {
txtTimeRemaining = new javax.swing.JTextField(); txtTimeRemaining = new javax.swing.JTextField();
deckLegalityDisplay = new mage.client.deckeditor.DeckLegalityPanel(); deckLegalityDisplay = new mage.client.deckeditor.DeckLegalityPanel();
panelRight.setDividerSize(10);
panelRight.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); panelRight.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
panelRight.setResizeWeight(0.5); panelRight.setResizeWeight(0.5);
panelRight.setTopComponent(cardSelector); panelRight.setTopComponent(cardSelector);
deckArea.setMinimumSize(new java.awt.Dimension(200, 56));
panelRight.setBottomComponent(deckArea); panelRight.setBottomComponent(deckArea);
panelDeck.setOpaque(false); panelDeck.setOpaque(false);
@ -1193,7 +1212,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(panelLeft, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(panelLeft, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(panelRight, javax.swing.GroupLayout.PREFERRED_SIZE, 890, Short.MAX_VALUE)) .addComponent(panelRight, javax.swing.GroupLayout.DEFAULT_SIZE, 890, Short.MAX_VALUE))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

View file

@ -3,6 +3,7 @@ package mage.client.dialog;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.SessionHandler; import mage.client.SessionHandler;
import mage.client.components.KeyBindButton; import mage.client.components.KeyBindButton;
import mage.client.themes.ThemeType;
import mage.client.util.CardLanguage; import mage.client.util.CardLanguage;
import mage.client.util.ClientDefaultSettings; import mage.client.util.ClientDefaultSettings;
import mage.client.util.GUISizeHelper; import mage.client.util.GUISizeHelper;
@ -15,7 +16,6 @@ import mage.remote.Connection;
import mage.remote.Connection.ProxyType; import mage.remote.Connection.ProxyType;
import mage.view.UserRequestMessage; import mage.view.UserRequestMessage;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import mage.client.themes.ThemeType;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.Border; import javax.swing.border.Border;
@ -160,7 +160,8 @@ public class PreferencesDialog extends javax.swing.JDialog {
public static final String KEY_TABLES_DIVIDER_LOCATION_4 = "tablePanelDividerLocation4"; public static final String KEY_TABLES_DIVIDER_LOCATION_4 = "tablePanelDividerLocation4";
// Positions of deck editor divider bars // Positions of deck editor divider bars
public static final String KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION = "editorHorizontalDividerLocation"; public static final String KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION_NORMAL = "editorHorizontalDividerLocationNormal";
public static final String KEY_EDITOR_HORIZONTAL_DIVIDER_LOCATION_LIMITED = "editorHorizontalDividerLocationLimited";
public static final String KEY_EDITOR_DECKAREA_SETTINGS = "editorDeckAreaSettings"; public static final String KEY_EDITOR_DECKAREA_SETTINGS = "editorDeckAreaSettings";
// user list // user list

View file

@ -29,13 +29,13 @@ import java.util.UUID;
*/ */
public final class AlpineHoundmaster extends CardImpl { public final class AlpineHoundmaster extends CardImpl {
private static final FilterPermanent filter = new FilterAttackingCreature(); private static final FilterPermanent filter = new FilterAttackingCreature("the number of other attacking creatures");
static { static {
filter.add(AnotherPredicate.instance); filter.add(AnotherPredicate.instance);
} }
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter); private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter, null);
public AlpineHoundmaster(UUID ownerId, CardSetInfo setInfo) { public AlpineHoundmaster(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}");
@ -50,8 +50,8 @@ public final class AlpineHoundmaster extends CardImpl {
// Whenever Alpine Houndmaster attacks, it gets +X/+0 until end of turn, where X is the number of other attacking creatures. // Whenever Alpine Houndmaster attacks, it gets +X/+0 until end of turn, where X is the number of other attacking creatures.
this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect( this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(
xValue, StaticValue.get(0), Duration.EndOfTurn xValue, StaticValue.get(0), Duration.EndOfTurn, true
), false, "it gets +X/+0 until end of turn, where X is the number of other attacking creatures")); ), false));
} }
private AlpineHoundmaster(final AlpineHoundmaster card) { private AlpineHoundmaster(final AlpineHoundmaster card) {

View file

@ -1,5 +1,6 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -19,8 +20,6 @@ import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID;
/** /**
* @author LevelX2 * @author LevelX2
*/ */
@ -82,9 +81,12 @@ class AnimarCostReductionEffect extends CostModificationEffectImpl {
public boolean applies(Ability abilityToModify, Ability source, Game game) { public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify instanceof SpellAbility) { if (abilityToModify instanceof SpellAbility) {
if (abilityToModify.isControlledBy(source.getControllerId())) { if (abilityToModify.isControlledBy(source.getControllerId())) {
Card card = ((SpellAbility) abilityToModify).getCharacteristics(game); Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);
if (card != null) { if (spellCard != null) {
return card.isCreature(); if (((SpellAbility) abilityToModify).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
spellCard = ((SpellAbility) abilityToModify).getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCard, game);
}
return spellCard.isCreature();
} }
} }
} }

View file

@ -1,7 +1,5 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -9,10 +7,13 @@ import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
import java.util.UUID;
/** /**
* @author Loki * @author Loki
*/ */
@ -32,6 +33,7 @@ public final class ArdentRecruit extends CardImpl {
"{this} gets +2/+2 as long as you control three or more artifacts"); "{this} gets +2/+2 as long as you control three or more artifacts");
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
ability.setAbilityWord(AbilityWord.METALCRAFT); ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -1,7 +1,5 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -12,6 +10,7 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect; import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -20,8 +19,9 @@ import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/** /**
*
* @author Loki * @author Loki
*/ */
public final class ArgentSphinx extends CardImpl { public final class ArgentSphinx extends CardImpl {
@ -39,6 +39,7 @@ public final class ArgentSphinx extends CardImpl {
// <i>Metalcraft</i> &mdash; {U}: Exile Argent Sphinx. Return it to the battlefield under your control at the beginning of the next end step. Activate this ability only if you control three or more artifacts. // <i>Metalcraft</i> &mdash; {U}: Exile Argent Sphinx. Return it to the battlefield under your control at the beginning of the next end step. Activate this ability only if you control three or more artifacts.
Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ArgentSphinxEffect(), new ManaCostsImpl("{U}"), MetalcraftCondition.instance); Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ArgentSphinxEffect(), new ManaCostsImpl("{U}"), MetalcraftCondition.instance);
ability.setAbilityWord(AbilityWord.METALCRAFT); ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -1,10 +1,13 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility; import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
@ -17,11 +20,6 @@ import mage.target.common.TargetCardInExile;
import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInHand;
import mage.target.common.TargetNonlandPermanent; import mage.target.common.TargetNonlandPermanent;
import java.util.UUID;
import mage.MageObjectReference;
import mage.cards.Card;
/** /**
* @author TheElk801 * @author TheElk801
*/ */
@ -42,7 +40,7 @@ public final class AshiokNightmareMuse extends CardImpl {
ability.addTarget(new TargetNonlandPermanent()); ability.addTarget(new TargetNonlandPermanent());
this.addAbility(ability); this.addAbility(ability);
// 7: You may cast up to three face-up cards your opponents own from exile without paying their mana costs. // 7: You may cast up to three spells from among face-up cards your opponents own from exile without paying their mana costs.
this.addAbility(new LoyaltyAbility(new AshiokNightmareMuseCastEffect(), -7)); this.addAbility(new LoyaltyAbility(new AshiokNightmareMuseCastEffect(), -7));
} }
@ -102,7 +100,7 @@ class AshiokNightmareMuseCastEffect extends OneShotEffect {
AshiokNightmareMuseCastEffect() { AshiokNightmareMuseCastEffect() {
super(Outcome.Discard); super(Outcome.Discard);
staticText = "You may cast up to three face-up cards your opponents own from exile without paying their mana costs."; staticText = "You may cast up to three spells from among face-up cards your opponents own from exile without paying their mana costs.";
} }
private AshiokNightmareMuseCastEffect(final AshiokNightmareMuseCastEffect effect) { private AshiokNightmareMuseCastEffect(final AshiokNightmareMuseCastEffect effect) {

View file

@ -1,23 +1,20 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.DoubleStrikeAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.Duration;
import mage.constants.SubType; import java.util.UUID;
import mage.constants.Zone;
/** /**
*
* @author maurer.it_at_gmail.com * @author maurer.it_at_gmail.com
*/ */
public final class AuriokEdgewright extends CardImpl { public final class AuriokEdgewright extends CardImpl {
@ -33,7 +30,12 @@ public final class AuriokEdgewright extends CardImpl {
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
ContinuousEffect effect = new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield); ContinuousEffect effect = new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect, MetalcraftCondition.instance, effectText))); this.addAbility(new SimpleStaticAbility(
Zone.BATTLEFIELD,
new ConditionalContinuousEffect(effect, MetalcraftCondition.instance, effectText))
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public AuriokEdgewright(final AuriokEdgewright card) { public AuriokEdgewright(final AuriokEdgewright card) {

View file

@ -1,7 +1,5 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
@ -9,16 +7,15 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.Duration;
import mage.constants.SubType; import java.util.UUID;
import mage.constants.Zone;
/** /**
*
* @author maurer.it_at_gmail.com * @author maurer.it_at_gmail.com
*/ */
public final class AuriokSunchaser extends CardImpl { public final class AuriokSunchaser extends CardImpl {
@ -35,9 +32,18 @@ public final class AuriokSunchaser extends CardImpl {
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
ContinuousEffect effect1 = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield); ContinuousEffect effect1 = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect1, MetalcraftCondition.instance, effect1Text))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new ConditionalContinuousEffect(effect1, MetalcraftCondition.instance, effect1Text))
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
ContinuousEffect effect2 = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield); ContinuousEffect effect2 = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect2, MetalcraftCondition.instance, effect2Text))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new ConditionalContinuousEffect(effect2, MetalcraftCondition.instance, effect2Text))
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public AuriokSunchaser(final AuriokSunchaser card) { public AuriokSunchaser(final AuriokSunchaser card) {

View file

@ -1,7 +1,5 @@
package mage.cards.b; package mage.cards.b;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -9,15 +7,18 @@ import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import java.util.UUID;
/** /**
*
* @author North * @author North
*/ */
public final class BladeTribeBerserkers extends CardImpl { public final class BladeTribeBerserkers extends CardImpl {
@ -34,7 +35,10 @@ public final class BladeTribeBerserkers extends CardImpl {
//<i>Metalcraft</i> &mdash; When Blade-Tribe Berserkers enters the battlefield, if you control three or more artifacts, Blade-Tribe Berserkers gets +3/+3 and gains haste until end of turn. //<i>Metalcraft</i> &mdash; When Blade-Tribe Berserkers enters the battlefield, if you control three or more artifacts, Blade-Tribe Berserkers gets +3/+3 and gains haste until end of turn.
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostSourceEffect(3, 3, Duration.EndOfTurn), false); TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostSourceEffect(3, 3, Duration.EndOfTurn), false);
ability.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); ability.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn));
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MetalcraftCondition.instance, effectText)); this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MetalcraftCondition.instance, effectText)
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public BladeTribeBerserkers(final BladeTribeBerserkers card) { public BladeTribeBerserkers(final BladeTribeBerserkers card) {

View file

@ -1,7 +1,5 @@
package mage.cards.b; package mage.cards.b;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -9,15 +7,18 @@ import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.target.Target; import mage.target.Target;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import java.util.UUID;
/** /**
*
* @author North * @author North
*/ */
public final class BleakCovenVampires extends CardImpl { public final class BleakCovenVampires extends CardImpl {
@ -37,7 +38,10 @@ public final class BleakCovenVampires extends CardImpl {
Target target = new TargetPlayer(); Target target = new TargetPlayer();
ability.addTarget(target); ability.addTarget(target);
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MetalcraftCondition.instance, effectText)); this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MetalcraftCondition.instance, effectText)
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public BleakCovenVampires(final BleakCovenVampires card) { public BleakCovenVampires(final BleakCovenVampires card) {

View file

@ -1,5 +1,3 @@
package mage.cards.c; package mage.cards.c;
import mage.MageInt; import mage.MageInt;
@ -7,12 +5,10 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import java.util.UUID; import java.util.UUID;
@ -35,8 +31,9 @@ public final class CarapaceForger extends CardImpl {
new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; {this} gets " + MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; {this} gets " +
"+2/+2 as long as you control three or more artifacts" "+2/+2 as long as you control three or more artifacts"
) ))
)); .setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance));
} }
public CarapaceForger(final CarapaceForger card) { public CarapaceForger(final CarapaceForger card) {

View file

@ -1,5 +1,3 @@
package mage.cards.c; package mage.cards.c;
import mage.MageInt; import mage.MageInt;
@ -7,12 +5,10 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import java.util.UUID; import java.util.UUID;
@ -33,8 +29,9 @@ public final class ChromeSteed extends CardImpl {
new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; {this} gets " + MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; {this} gets " +
"+2/+2 as long as you control three or more artifacts" "+2/+2 as long as you control three or more artifacts"
) ))
)); .setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance));
} }
public ChromeSteed(final ChromeSteed card) { public ChromeSteed(final ChromeSteed card) {

View file

@ -5,8 +5,10 @@ import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.RestrictionEffect;
import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
@ -28,9 +30,12 @@ public final class ConcussiveBolt extends CardImpl {
// Concussive Bolt deals 4 damage to target player. // Concussive Bolt deals 4 damage to target player.
this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
this.getSpellAbility().addEffect(new DamageTargetEffect(4)); this.getSpellAbility().addEffect(new DamageTargetEffect(4));
// <i>Metalcraft</i> &mdash; If you control three or more artifacts, creatures that player controls can't block this turn. // <i>Metalcraft</i> &mdash; If you control three or more artifacts, creatures that player controls can't block this turn.
this.getSpellAbility().addEffect(new ConcussiveBoltEffect()); this.getSpellAbility().addEffect(new ConcussiveBoltEffect());
this.getSpellAbility().addEffect(new ConcussiveBoltRestrictionEffect()); this.getSpellAbility().addEffect(new ConcussiveBoltRestrictionEffect());
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
this.getSpellAbility().addHint(MetalcraftHint.instance);
} }
public ConcussiveBolt(final ConcussiveBolt card) { public ConcussiveBolt(final ConcussiveBolt card) {

View file

@ -1,19 +1,19 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
*
* @author Loki * @author Loki
*/ */
public final class Dispatch extends CardImpl { public final class Dispatch extends CardImpl {
@ -21,9 +21,14 @@ public final class Dispatch extends CardImpl {
public Dispatch(UUID ownerId, CardSetInfo setInfo) { public Dispatch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
// Tap target creature.
this.getSpellAbility().addEffect(new TapTargetEffect()); this.getSpellAbility().addEffect(new TapTargetEffect());
// Metalcraft If you control three or more artifacts, exile that creature.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ExileTargetEffect(), MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; If you control three or more artifacts, exile that creature")); this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ExileTargetEffect(), MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; If you control three or more artifacts, exile that creature"));
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
this.getSpellAbility().addHint(MetalcraftHint.instance);
} }
public Dispatch(final Dispatch card) { public Dispatch(final Dispatch card) {

View file

@ -1,22 +1,22 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.effects.common.SacrificeEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.filter.common.FilterAttackingCreature; import mage.filter.common.FilterAttackingCreature;
import mage.game.Game; import mage.game.Game;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import java.util.UUID;
/** /**
*
* @author maurer.it_at_gmail.com * @author maurer.it_at_gmail.com
*/ */
public final class DispenseJustice extends CardImpl { public final class DispenseJustice extends CardImpl {
@ -24,9 +24,12 @@ public final class DispenseJustice extends CardImpl {
public DispenseJustice(UUID ownerId, CardSetInfo setInfo) { public DispenseJustice(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
// Target player sacrifices an attacking creature.
// Metalcraft That player sacrifices two attacking creatures instead if you control three or more artifacts.
this.getSpellAbility().addEffect(new DispenseJusticeEffect()); this.getSpellAbility().addEffect(new DispenseJusticeEffect());
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
this.getSpellAbility().addHint(MetalcraftHint.instance);
} }
public DispenseJustice(final DispenseJustice card) { public DispenseJustice(final DispenseJustice card) {
@ -60,8 +63,7 @@ class DispenseJusticeEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
if (MetalcraftCondition.instance.apply(game, source)) { if (MetalcraftCondition.instance.apply(game, source)) {
return new SacrificeEffect(filter, 2, effectText).apply(game, source); return new SacrificeEffect(filter, 2, effectText).apply(game, source);
} } else {
else {
return new SacrificeEffect(filter, 1, effectText).apply(game, source); return new SacrificeEffect(filter, 1, effectText).apply(game, source);
} }
} }

View file

@ -1,7 +1,5 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -9,10 +7,11 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.other.FaceDownPredicate; import mage.filter.predicate.other.FaceDownCastablePredicate;
import java.util.UUID;
/** /**
*
* @author North * @author North
*/ */
public final class DreamChisel extends CardImpl { public final class DreamChisel extends CardImpl {
@ -20,7 +19,7 @@ public final class DreamChisel extends CardImpl {
private static final FilterCreatureCard filter = new FilterCreatureCard("Face-down creature spells"); private static final FilterCreatureCard filter = new FilterCreatureCard("Face-down creature spells");
static { static {
filter.add(FaceDownPredicate.instance); filter.add(FaceDownCastablePredicate.instance);
} }
public DreamChisel(UUID ownerId, CardSetInfo setInfo) { public DreamChisel(UUID ownerId, CardSetInfo setInfo) {

View file

@ -1,4 +1,3 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID; import java.util.UUID;
@ -11,12 +10,12 @@ import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.AbilityType; import mage.constants.AbilityType;
import mage.constants.CardType;
import mage.constants.CostModificationType; import mage.constants.CostModificationType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
@ -54,8 +53,9 @@ public final class Drought extends CardImpl {
class DroughtAdditionalCostEffect extends CostModificationEffectImpl { class DroughtAdditionalCostEffect extends CostModificationEffectImpl {
private boolean appliesToSpells; private final boolean appliesToSpells;
private static final FilterControlledPermanent filter = new FilterControlledPermanent("a Swamp"); private static final FilterControlledPermanent filter = new FilterControlledPermanent("a Swamp");
static { static {
filter.add(SubType.SWAMP.getPredicate()); filter.add(SubType.SWAMP.getPredicate());
} }

View file

@ -1,5 +1,6 @@
package mage.cards.e; package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.common.SagaAbility; import mage.abilities.common.SagaAbility;
@ -23,8 +24,6 @@ import mage.target.TargetPermanent;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID;
/** /**
* @author TheElk801 * @author TheElk801
*/ */
@ -99,12 +98,17 @@ class ElspethConquersDeathCostEffect extends CostModificationEffectImpl {
@Override @Override
public boolean applies(Ability abilityToModify, Ability source, Game game) { public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (!(abilityToModify instanceof SpellAbility) || if ((abilityToModify instanceof SpellAbility)
!game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) { && game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
return false; Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);
if (spellCard != null) {
if (((SpellAbility) abilityToModify).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
spellCard = ((SpellAbility) abilityToModify).getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCard, game);
} }
Card card = game.getCard(abilityToModify.getSourceId()); return !spellCard.isCreature();
return card != null && !card.isCreature(); }
}
return false;
} }
@Override @Override
@ -117,8 +121,8 @@ class ElspethConquersDeathReturnEffect extends OneShotEffect {
ElspethConquersDeathReturnEffect() { ElspethConquersDeathReturnEffect() {
super(Outcome.Benefit); super(Outcome.Benefit);
staticText = "Return target creature or planeswalker card from your graveyard to the battlefield. " + staticText = "Return target creature or planeswalker card from your graveyard to the battlefield. "
"Put a +1/+1 counter or a loyalty counter on it"; + "Put a +1/+1 counter or a loyalty counter on it";
} }
private ElspethConquersDeathReturnEffect(final ElspethConquersDeathReturnEffect effect) { private ElspethConquersDeathReturnEffect(final ElspethConquersDeathReturnEffect effect) {
@ -149,4 +153,5 @@ class ElspethConquersDeathReturnEffect extends OneShotEffect {
permanent.addCounters(counter, source, game); permanent.addCounters(counter, source, game);
return true; return true;
} }
} }

View file

@ -1,7 +1,5 @@
package mage.cards.e; package mage.cards.e;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -9,19 +7,18 @@ import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.ProtectionAbility; import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.ColorPredicate;
import java.util.UUID;
/** /**
*
* @author North * @author North
*/ */
public final class EtchedChampion extends CardImpl { public final class EtchedChampion extends CardImpl {
@ -45,8 +42,13 @@ public final class EtchedChampion extends CardImpl {
this.power = new MageInt(2); this.power = new MageInt(2);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// Metalcraft Etched Champion has protection from all colors as long as you control three or more artifacts.
ContinuousEffect effect = new GainAbilitySourceEffect(new ProtectionAbility(filter), Duration.WhileOnBattlefield); ContinuousEffect effect = new GainAbilitySourceEffect(new ProtectionAbility(filter), Duration.WhileOnBattlefield);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect, MetalcraftCondition.instance, ruleText))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new ConditionalContinuousEffect(effect, MetalcraftCondition.instance, ruleText))
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public EtchedChampion(final EtchedChampion card) { public EtchedChampion(final EtchedChampion card) {

View file

@ -1,4 +1,3 @@
package mage.cards.e; package mage.cards.e;
import java.util.UUID; import java.util.UUID;
@ -20,7 +19,7 @@ public final class EyeOfRamos extends CardImpl {
public EyeOfRamos(UUID ownerId, CardSetInfo setInfo) { public EyeOfRamos(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// {tap}: Add {U}. // {T}: Add {U}.
this.addAbility(new BlueManaAbility()); this.addAbility(new BlueManaAbility());
// Sacrifice Eye of Ramos: Add {U}. // Sacrifice Eye of Ramos: Add {U}.

View file

@ -1,8 +1,5 @@
package mage.cards.e; package mage.cards.e;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -11,16 +8,15 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration; import java.util.UUID;
import mage.constants.Zone;
/** /**
*
* @author Loki * @author Loki
*/ */
public final class EzurisBrigade extends CardImpl { public final class EzurisBrigade extends CardImpl {
@ -30,13 +26,16 @@ public final class EzurisBrigade extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
this.subtype.add(SubType.ELF); this.subtype.add(SubType.ELF);
this.subtype.add(SubType.WARRIOR); this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(4); this.power = new MageInt(4);
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// Metalcraft As long as you control three or more artifacts, Ezuris Brigade gets +4/+4 and has trample.
ContinuousEffect boostSource = new BoostSourceEffect(4, 4, Duration.WhileOnBattlefield); ContinuousEffect boostSource = new BoostSourceEffect(4, 4, Duration.WhileOnBattlefield);
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(boostSource, MetalcraftCondition.instance, rule); ConditionalContinuousEffect effect = new ConditionalContinuousEffect(boostSource, MetalcraftCondition.instance, rule);
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield), MetalcraftCondition.instance, "")); ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield), MetalcraftCondition.instance, ""));
ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -3,8 +3,10 @@ package mage.cards.g;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.target.common.TargetAnyTarget; import mage.target.common.TargetAnyTarget;
@ -29,6 +31,8 @@ public final class GalvanicBlast extends CardImpl {
MetalcraftCondition.instance, effectText MetalcraftCondition.instance, effectText
)); ));
this.getSpellAbility().addTarget(new TargetAnyTarget()); this.getSpellAbility().addTarget(new TargetAnyTarget());
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
this.getSpellAbility().addHint(MetalcraftHint.instance);
} }
public GalvanicBlast(final GalvanicBlast card) { public GalvanicBlast(final GalvanicBlast card) {

View file

@ -1,23 +1,19 @@
package mage.cards.g; package mage.cards.g;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration; import java.util.UUID;
import mage.constants.Zone;
/** /**
*
* @author Loki * @author Loki
*/ */
public final class GhalmasWarden extends CardImpl { public final class GhalmasWarden extends CardImpl {
@ -28,12 +24,16 @@ public final class GhalmasWarden extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.ELEPHANT); this.subtype.add(SubType.ELEPHANT);
this.subtype.add(SubType.SOLDIER); this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(2); this.power = new MageInt(2);
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// Metalcraft Ghalmas Warden gets +2/+2 as long as you control three or more artifacts.
ContinuousEffect boostSource = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield); ContinuousEffect boostSource = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield);
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(boostSource, MetalcraftCondition.instance, rule); ConditionalContinuousEffect effect = new ConditionalContinuousEffect(boostSource, MetalcraftCondition.instance, rule);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public GhalmasWarden(final GhalmasWarden card) { public GhalmasWarden(final GhalmasWarden card) {

View file

@ -1,7 +1,5 @@
package mage.cards.g; package mage.cards.g;
import java.util.ArrayList;
import java.util.List;
import mage.*; import mage.*;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
@ -124,21 +122,6 @@ class GrandArchitectManaAbility extends ActivatedManaAbilityImpl {
this.filter = ability.filter.copy(); this.filter = ability.filter.copy();
} }
@Override
public List<Mana> getNetMana(Game game) {
if (game != null && game.inCheckPlayableState()) {
int count = game.getBattlefield().count(filter, getSourceId(), getControllerId(), game);
List<Mana> netMana = new ArrayList<>();
if (count > 0) {
ConditionalMana mana = new GrandArchitectConditionalMana();
mana.setColorless(count * 2);
netMana.add(mana);
}
return netMana;
}
return super.getNetMana(game);
}
@Override @Override
public GrandArchitectManaAbility copy() { public GrandArchitectManaAbility copy() {
return new GrandArchitectManaAbility(this); return new GrandArchitectManaAbility(this);

View file

@ -1,7 +1,5 @@
package mage.cards.h; package mage.cards.h;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
@ -10,8 +8,8 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
@ -20,8 +18,9 @@ import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/** /**
*
* @author jeffwadsworth * @author jeffwadsworth
*/ */
public final class HamletbackGoliath extends CardImpl { public final class HamletbackGoliath extends CardImpl {
@ -72,7 +71,7 @@ class HamletbackGoliathTriggeredAbility extends TriggeredAbilityImpl {
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
UUID targetId = event.getTargetId(); UUID targetId = event.getTargetId();
Permanent permanent = game.getPermanent(targetId); Permanent permanent = game.getPermanent(targetId);
if (permanent.isCreature() if (permanent != null && permanent.isCreature()
&& !(targetId.equals(this.getSourceId()))) { && !(targetId.equals(this.getSourceId()))) {
for (Effect effect : this.getEffects()) { for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(event.getTargetId())); effect.setTargetPointer(new FixedTarget(event.getTargetId()));

View file

@ -1,4 +1,3 @@
package mage.cards.h; package mage.cards.h;
import java.util.UUID; import java.util.UUID;
@ -54,7 +53,7 @@ class HeraldOfWarCostReductionEffect extends CostModificationEffectImpl {
HeraldOfWarCostReductionEffect() { HeraldOfWarCostReductionEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST); super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
staticText = "Angel spells and Human spells you cast cost {1} less to cast for each +1/+1 counter on Herald of War"; staticText = "Angel spells and Human spells you cast cost {1} less to cast for each +1/+1 counter on {this}";
} }
HeraldOfWarCostReductionEffect(HeraldOfWarCostReductionEffect effect) { HeraldOfWarCostReductionEffect(HeraldOfWarCostReductionEffect effect) {

View file

@ -1,6 +1,5 @@
package mage.cards.h; package mage.cards.h;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -13,6 +12,7 @@ import mage.game.Game;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID; import java.util.UUID;
import mage.cards.Card;
/** /**
* @author Pete Rossi * @author Pete Rossi
@ -58,9 +58,12 @@ class HumOfTheRadixCostIncreaseEffect extends CostModificationEffectImpl {
@Override @Override
public boolean applies(Ability abilityToModify, Ability source, Game game) { public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify instanceof SpellAbility) { if (abilityToModify instanceof SpellAbility) {
MageObject sourceObject = abilityToModify.getSourceObject(game); Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);
if (sourceObject != null && sourceObject.isArtifact()) { if (spellCard != null) {
return true; if (((SpellAbility) abilityToModify).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
spellCard = ((SpellAbility) abilityToModify).getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCard, game);
}
return !spellCard.isArtifact();
} }
} }
return false; return false;

View file

@ -1,5 +1,3 @@
package mage.cards.h; package mage.cards.h;
import java.util.UUID; import java.util.UUID;
@ -18,6 +16,7 @@ public final class HuntersFeast extends CardImpl {
public HuntersFeast(UUID ownerId, CardSetInfo setInfo) { public HuntersFeast(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}");
// Any number of target players each gain 6 life.
this.getSpellAbility().addTarget(new TargetPlayer(0, Integer.MAX_VALUE, false)); this.getSpellAbility().addTarget(new TargetPlayer(0, Integer.MAX_VALUE, false));
this.getSpellAbility().addEffect(new GainLifeTargetEffect(6)); this.getSpellAbility().addEffect(new GainLifeTargetEffect(6));
} }

View file

@ -1,24 +1,21 @@
package mage.cards.i; package mage.cards.i;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ShroudAbility; import mage.abilities.keyword.ShroudAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import java.util.UUID;
/** /**
* @author nantuko * @author nantuko
*/ */
@ -35,13 +32,19 @@ public final class IndomitableArchangel extends CardImpl {
public IndomitableArchangel(UUID ownerId, CardSetInfo setInfo) { public IndomitableArchangel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
this.subtype.add(SubType.ANGEL); this.subtype.add(SubType.ANGEL);
this.power = new MageInt(4); this.power = new MageInt(4);
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// Flying
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// Metalcraft Artifacts you control have shroud as long as you control three or more artifacts. (An artifact with shroud cant be the target of spells or abilities.)
ContinuousEffect gainAbilityEffect = new GainAbilityControlledEffect(ShroudAbility.getInstance(), Duration.WhileOnBattlefield, filter); ContinuousEffect gainAbilityEffect = new GainAbilityControlledEffect(ShroudAbility.getInstance(), Duration.WhileOnBattlefield, filter);
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(gainAbilityEffect, MetalcraftCondition.instance, rule); ConditionalContinuousEffect effect = new ConditionalContinuousEffect(gainAbilityEffect, MetalcraftCondition.instance, rule);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public IndomitableArchangel(final IndomitableArchangel card) { public IndomitableArchangel(final IndomitableArchangel card) {

View file

@ -1,7 +1,5 @@
package mage.cards.i; package mage.cards.i;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.ActivateIfConditionActivatedAbility;
@ -11,9 +9,11 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.mana.ColorlessManaAbility; import mage.abilities.mana.ColorlessManaAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.Zone; import mage.constants.Zone;
@ -24,8 +24,9 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
import java.util.UUID;
/** /**
*
* @author fireshoes * @author fireshoes
*/ */
public final class InventorsFair extends CardImpl { public final class InventorsFair extends CardImpl {
@ -52,6 +53,8 @@ public final class InventorsFair extends CardImpl {
new GenericManaCost(4), MetalcraftCondition.instance); new GenericManaCost(4), MetalcraftCondition.instance);
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost()); ability.addCost(new SacrificeSourceCost());
ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -1,24 +1,20 @@
package mage.cards.j; package mage.cards.j;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import java.util.UUID;
/** /**
*
* @author North * @author North
*/ */
public final class JorKadeenThePrevailer extends CardImpl { public final class JorKadeenThePrevailer extends CardImpl {
@ -40,7 +36,9 @@ public final class JorKadeenThePrevailer extends CardImpl {
// <i>Metalcraft</i> &mdash; Creatures you control get +3/+0 as long as you control three or more artifacts. // <i>Metalcraft</i> &mdash; Creatures you control get +3/+0 as long as you control three or more artifacts.
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new BoostControlledEffect(3, 0, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURE, false), ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new BoostControlledEffect(3, 0, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURE, false),
MetalcraftCondition.instance, effectText); MetalcraftCondition.instance, effectText);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance));
} }
public JorKadeenThePrevailer(final JorKadeenThePrevailer card) { public JorKadeenThePrevailer(final JorKadeenThePrevailer card) {

View file

@ -5,6 +5,7 @@ import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
@ -14,10 +15,9 @@ import mage.constants.WatcherScope;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.ObjectPlayer; import mage.filter.predicate.Predicate;
import mage.filter.predicate.ObjectPlayerPredicate; import mage.filter.predicate.other.FaceDownCastablePredicate;
import mage.filter.predicate.other.FaceDownPredicate; import mage.filter.predicate.other.FaceDownPredicate;
import mage.game.Controllable;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.stack.Spell; import mage.game.stack.Spell;
@ -32,12 +32,12 @@ import java.util.UUID;
*/ */
public final class KadenaSlinkingSorcerer extends CardImpl { public final class KadenaSlinkingSorcerer extends CardImpl {
private static final FilterCard filter = new FilterCard(); private static final FilterCard filterFirstFaceDownSpell = new FilterCard("first face-down creature spell");
private static final FilterPermanent filter2 = new FilterControlledCreaturePermanent("a face-down creature"); private static final FilterPermanent filterFaceDownPermanent = new FilterControlledCreaturePermanent("a face-down creature");
static { static {
filter.add(KadenaSlinkingSorcererPredicate.instance); filterFirstFaceDownSpell.add(KadenaSlinkingSorcererPredicate.instance);
filter2.add(FaceDownPredicate.instance); filterFaceDownPermanent.add(FaceDownPredicate.instance);
} }
public KadenaSlinkingSorcerer(UUID ownerId, CardSetInfo setInfo) { public KadenaSlinkingSorcerer(UUID ownerId, CardSetInfo setInfo) {
@ -51,13 +51,13 @@ public final class KadenaSlinkingSorcerer extends CardImpl {
// The first face-down creature spell you cast each turn costs {3} less to cast. // The first face-down creature spell you cast each turn costs {3} less to cast.
this.addAbility(new SimpleStaticAbility( this.addAbility(new SimpleStaticAbility(
new SpellsCostReductionControllerEffect(filter, 3) new SpellsCostReductionControllerEffect(filterFirstFaceDownSpell, 3)
.setText("The first face-down creature spell you cast each turn costs {3} less to cast.") .setText("The first face-down creature spell you cast each turn costs {3} less to cast.")
), new KadenaSlinkingSorcererWatcher()); ), new KadenaSlinkingSorcererWatcher());
// Whenever a face-down creature enters the battlefield under your control, draw a card. // Whenever a face-down creature enters the battlefield under your control, draw a card.
this.addAbility(new EntersBattlefieldControlledTriggeredAbility( this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
new DrawCardSourceControllerEffect(1), filter2 new DrawCardSourceControllerEffect(1), filterFaceDownPermanent
)); ));
} }
@ -71,16 +71,15 @@ public final class KadenaSlinkingSorcerer extends CardImpl {
} }
} }
enum KadenaSlinkingSorcererPredicate implements ObjectPlayerPredicate<ObjectPlayer<Controllable>> { enum KadenaSlinkingSorcererPredicate implements Predicate<Card> {
instance; instance;
@Override @Override
public boolean apply(ObjectPlayer<Controllable> input, Game game) { public boolean apply(Card input, Game game) {
if (input.getObject() instanceof Spell
&& ((Spell) input.getObject()).isCreature()
&& ((Spell) input.getObject()).isFaceDown(game)) {
KadenaSlinkingSorcererWatcher watcher = game.getState().getWatcher(KadenaSlinkingSorcererWatcher.class); KadenaSlinkingSorcererWatcher watcher = game.getState().getWatcher(KadenaSlinkingSorcererWatcher.class);
return watcher != null && !watcher.castFaceDownThisTurn(input.getPlayerId()); if (watcher != null) {
return FaceDownCastablePredicate.instance.apply(input, game)
&& !watcher.castFaceDownThisTurn(input.getOwnerId());
} }
return false; return false;
} }

View file

@ -1,7 +1,5 @@
package mage.cards.k; package mage.cards.k;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.CompoundCondition;
@ -10,18 +8,16 @@ import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord; import mage.constants.*;
import mage.constants.CardType;
import mage.constants.SubType; import java.util.UUID;
import mage.constants.PhaseStep;
import mage.constants.Zone;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public final class KuldothaPhoenix extends CardImpl { public final class KuldothaPhoenix extends CardImpl {
@ -46,6 +42,7 @@ public final class KuldothaPhoenix extends CardImpl {
new IsStepCondition(PhaseStep.UPKEEP), MetalcraftCondition.instance) new IsStepCondition(PhaseStep.UPKEEP), MetalcraftCondition.instance)
); );
ability.setAbilityWord(AbilityWord.METALCRAFT); ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -1,20 +1,22 @@
package mage.cards.l; package mage.cards.l;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
* @author ayrat * @author ayrat
*/ */
@ -37,6 +39,8 @@ public final class LumengridDrake extends CardImpl {
TriggeredAbility conditional = new ConditionalInterveningIfTriggeredAbility( TriggeredAbility conditional = new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()), MetalcraftCondition.instance, ruleText); new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()), MetalcraftCondition.instance, ruleText);
conditional.addTarget(new TargetCreaturePermanent()); conditional.addTarget(new TargetCreaturePermanent());
conditional.setAbilityWord(AbilityWord.METALCRAFT);
conditional.addHint(MetalcraftHint.instance);
this.addAbility(conditional); this.addAbility(conditional);
} }

View file

@ -1,19 +1,20 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID;
import mage.abilities.condition.LockedInCondition; import mage.abilities.condition.LockedInCondition;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
*
* @author North * @author North
*/ */
public final class MirranMettle extends CardImpl { public final class MirranMettle extends CardImpl {
@ -23,12 +24,15 @@ public final class MirranMettle extends CardImpl {
public MirranMettle(UUID ownerId, CardSetInfo setInfo) { public MirranMettle(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}");
// Target creature gets +2/+2 until end of turn.
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn));
// Metalcraft That creature gets +4/+4 until end of turn instead if you control three or more artifacts.
this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn), this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn),
new LockedInCondition(MetalcraftCondition.instance), effectText)); new LockedInCondition(MetalcraftCondition.instance), effectText));
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
this.getSpellAbility().addHint(MetalcraftHint.instance);
} }
public MirranMettle(final MirranMettle card) { public MirranMettle(final MirranMettle card) {

View file

@ -3,12 +3,10 @@ package mage.cards.m;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.Outcome;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.players.Player; import mage.players.Player;
@ -31,6 +29,8 @@ public final class MoltenPsyche extends CardImpl {
// <i>Metalcraft</i> &mdash; If you control three or more artifacts, Molten Psyche deals damage to each opponent equal to the number of cards that player has drawn this turn. // <i>Metalcraft</i> &mdash; If you control three or more artifacts, Molten Psyche deals damage to each opponent equal to the number of cards that player has drawn this turn.
this.getSpellAbility().addEffect(new MoltenPsycheEffect()); this.getSpellAbility().addEffect(new MoltenPsycheEffect());
this.getSpellAbility().addWatcher(new MoltenPsycheWatcher()); this.getSpellAbility().addWatcher(new MoltenPsycheWatcher());
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
this.getSpellAbility().addHint(MetalcraftHint.instance);
} }
public MoltenPsyche(final MoltenPsyche card) { public MoltenPsyche(final MoltenPsyche card) {

View file

@ -1,4 +1,3 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID; import java.util.UUID;
@ -7,8 +6,9 @@ import mage.Mana;
import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect; import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -48,12 +48,13 @@ public final class Morselhoarder extends CardImpl {
} }
class MorselhoarderAbility extends ActivatedManaAbilityImpl { class MorselhoarderAbility extends ActivatedManaAbilityImpl {
public MorselhoarderAbility() { public MorselhoarderAbility() {
this(new RemoveCountersSourceCost(CounterType.M1M1.createInstance())); this(new RemoveCountersSourceCost(CounterType.M1M1.createInstance()));
} }
public MorselhoarderAbility(Cost cost) { public MorselhoarderAbility(Cost cost) {
super(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(), cost); super(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(1, new CountersSourceCount(CounterType.M1M1), false), cost);
this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, 1, 0)); this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, 1, 0));
} }

View file

@ -1,11 +1,10 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect; import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.mana.ActivateIfConditionManaAbility; import mage.abilities.mana.ActivateIfConditionManaAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -14,8 +13,9 @@ import mage.constants.CardType;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.Zone; import mage.constants.Zone;
import java.util.UUID;
/** /**
*
* @author BetaSteward_at_googlemail.com, Loki * @author BetaSteward_at_googlemail.com, Loki
*/ */
public final class MoxOpal extends CardImpl { public final class MoxOpal extends CardImpl {
@ -30,6 +30,7 @@ public final class MoxOpal extends CardImpl {
new TapSourceCost(), new TapSourceCost(),
MetalcraftCondition.instance); MetalcraftCondition.instance);
ability.setAbilityWord(AbilityWord.METALCRAFT); ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -1,5 +1,6 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID;
import mage.ConditionalMana; import mage.ConditionalMana;
import mage.MageObject; import mage.MageObject;
import mage.Mana; import mage.Mana;
@ -20,8 +21,6 @@ import mage.filter.FilterCard;
import mage.game.Game; import mage.game.Game;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
import java.util.UUID;
/** /**
* @author nantuko * @author nantuko
*/ */
@ -36,10 +35,10 @@ public final class MyrReservoir extends CardImpl {
public MyrReservoir(UUID ownerId, CardSetInfo setInfo) { public MyrReservoir(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// {tap}: Add {C}{C}. Spend this mana only to cast Myr spells or activate abilities of Myr. // {T}: Add {C}{C}. Spend this mana only to cast Myr spells or activate abilities of Myr.
this.addAbility(new MyrReservoirManaAbility()); this.addAbility(new MyrReservoirManaAbility());
// {3}, {tap}: Return target Myr card from your graveyard to your hand. // {3}, {T}: Return target Myr card from your graveyard to your hand.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new GenericManaCost(3)); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new GenericManaCost(3));
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCardInYourGraveyard(myrCardFilter)); ability.addTarget(new TargetCardInYourGraveyard(myrCardFilter));

View file

@ -1,7 +1,5 @@
package mage.cards.n; package mage.cards.n;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.dynamicvalue.common.EffectKeyValue; import mage.abilities.dynamicvalue.common.EffectKeyValue;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
@ -15,8 +13,9 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.token.NestOfScarabsBlackInsectToken; import mage.game.permanent.token.NestOfScarabsBlackInsectToken;
import java.util.UUID;
/** /**
*
* @author stravant * @author stravant
*/ */
public final class NestOfScarabs extends CardImpl { public final class NestOfScarabs extends CardImpl {
@ -63,7 +62,7 @@ class NestOfScarabsTriggeredAbility extends TriggeredAbilityImpl {
if (permanent == null) { if (permanent == null) {
permanent = game.getPermanentEntering(event.getTargetId()); permanent = game.getPermanentEntering(event.getTargetId());
} }
if (permanent.isCreature()) { if (permanent != null && permanent.isCreature()) {
getEffects().forEach(effect -> effect.setValue("countersAdded", event.getAmount())); getEffects().forEach(effect -> effect.setValue("countersAdded", event.getAmount()));
return true; return true;
} }

View file

@ -1,5 +1,9 @@
package mage.cards.n; package mage.cards.n;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.Mana; import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
@ -17,11 +21,6 @@ import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/** /**
* @author LevelX2 * @author LevelX2
*/ */
@ -69,14 +68,6 @@ class NykthosShrineToNyxManaAbility extends ActivatedManaAbilityImpl {
return new NykthosShrineToNyxManaAbility(this); return new NykthosShrineToNyxManaAbility(this);
} }
@Override
public List<Mana> getNetMana(Game game) {
List<Mana> netMana = new ArrayList<>();
if (game != null) {
netMana.addAll(((ManaEffect) this.getEffects().get(0)).getNetMana(game, this));
}
return netMana;
}
} }
class NykthosDynamicManaEffect extends ManaEffect { class NykthosDynamicManaEffect extends ManaEffect {

View file

@ -1,5 +1,9 @@
package mage.cards.n; package mage.cards.n;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.Mana; import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.EntersBattlefieldTappedAbility;
@ -16,11 +20,6 @@ import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/** /**
* @author TheElk801 * @author TheElk801
*/ */
@ -68,14 +67,6 @@ class NyxLotusManaAbility extends ActivatedManaAbilityImpl {
return new NyxLotusManaAbility(this); return new NyxLotusManaAbility(this);
} }
@Override
public List<Mana> getNetMana(Game game) {
List<Mana> netMana = new ArrayList<>();
if (game != null) {
netMana.addAll(((ManaEffect) this.getEffects().get(0)).getNetMana(game, this));
}
return netMana;
}
} }
class NyxLotusDynamicManaEffect extends ManaEffect { class NyxLotusDynamicManaEffect extends ManaEffect {

View file

@ -1,7 +1,5 @@
package mage.cards.o; package mage.cards.o;
import java.util.UUID;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
@ -14,10 +12,11 @@ import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.other.FaceDownPredicate; import mage.filter.predicate.other.FaceDownCastablePredicate;
import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class ObscuringAether extends CardImpl { public final class ObscuringAether extends CardImpl {
@ -25,7 +24,7 @@ public final class ObscuringAether extends CardImpl {
private static final FilterCreatureCard filter = new FilterCreatureCard("Face-down creature spells"); private static final FilterCreatureCard filter = new FilterCreatureCard("Face-down creature spells");
static { static {
filter.add(FaceDownPredicate.instance); filter.add(FaceDownCastablePredicate.instance);
} }
public ObscuringAether(UUID ownerId, CardSetInfo setInfo) { public ObscuringAether(UUID ownerId, CardSetInfo setInfo) {

View file

@ -1,8 +1,5 @@
package mage.cards.p; package mage.cards.p;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -11,6 +8,7 @@ import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -18,6 +16,8 @@ import mage.constants.*;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterControlledPermanent;
import java.util.UUID;
/** /**
* @author Loki * @author Loki
*/ */
@ -38,11 +38,15 @@ public final class PuresteelPaladin extends CardImpl {
// Whenever an Equipment enters the battlefield under your control, you may draw a card. // Whenever an Equipment enters the battlefield under your control, you may draw a card.
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), filter, true)); this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), filter, true));
// <i>Metalcraft</i> &mdash; Equipment you control have equip {0} as long as you control three or more artifacts // <i>Metalcraft</i> &mdash; Equipment you control have equip {0} as long as you control three or more artifacts
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(
new GainAbilityControlledEffect(new EquipAbility(Outcome.AddAbility, new GenericManaCost(0)), Duration.WhileOnBattlefield, filter), new GainAbilityControlledEffect(new EquipAbility(Outcome.AddAbility, new GenericManaCost(0)), Duration.WhileOnBattlefield, filter),
MetalcraftCondition.instance, MetalcraftCondition.instance,
"<i>Metalcraft</i> &mdash; Equipment you control have equip {0} as long as you control three or more artifacts"))); "<i>Metalcraft</i> &mdash; Equipment you control have equip {0} as long as you control three or more artifacts"))
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public PuresteelPaladin(final PuresteelPaladin card) { public PuresteelPaladin(final PuresteelPaladin card) {

View file

@ -1,4 +1,3 @@
package mage.cards.p; package mage.cards.p;
import java.util.UUID; import java.util.UUID;
@ -69,11 +68,10 @@ class PyromancersGauntletReplacementEffect extends ReplacementEffectImpl {
return true; return true;
} }
} }
Permanent permanent = game.getBattlefield().getPermanent(event.getSourceId()); Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
if(permanent != null && permanent.isPlaneswalker()){ return permanent != null
return true; && permanent.isPlaneswalker()
} && source.isControlledBy(permanent.getControllerId());
return false;
} }
@Override @Override

View file

@ -15,10 +15,10 @@ import mage.constants.*;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID; import java.util.UUID;
import mage.cards.Card;
/** /**
* @author LevelX2 * @author LevelX2
@ -115,9 +115,12 @@ class RakdosLordOfRiotsCostReductionEffect extends CostModificationEffectImpl {
public boolean applies(Ability abilityToModify, Ability source, Game game) { public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify instanceof SpellAbility) { if (abilityToModify instanceof SpellAbility) {
if (abilityToModify.isControlledBy(source.getControllerId())) { if (abilityToModify.isControlledBy(source.getControllerId())) {
Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);
if (spell != null) { if (spellCard != null) {
return spell.isCreature(); if (((SpellAbility) abilityToModify).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
spellCard = ((SpellAbility) abilityToModify).getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCard, game);
}
return spellCard.isCreature();
} }
} }
} }

View file

@ -1,23 +1,19 @@
package mage.cards.r; package mage.cards.r;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration; import java.util.UUID;
import mage.constants.Zone;
/** /**
*
* @author Loki * @author Loki
*/ */
public final class RazorfieldRhino extends CardImpl { public final class RazorfieldRhino extends CardImpl {
@ -27,8 +23,12 @@ public final class RazorfieldRhino extends CardImpl {
this.subtype.add(SubType.RHINO); this.subtype.add(SubType.RHINO);
this.power = new MageInt(4); this.power = new MageInt(4);
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// Metalcraft Razorfield Rhino gets +2/+2 as long as you control three or more artifacts.
ContinuousEffect effect1 = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield); ContinuousEffect effect1 = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect1, MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; Razorfield Rhino gets +2/+2 as long as you control three or more artifacts"))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect1, MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; Razorfield Rhino gets +2/+2 as long as you control three or more artifacts"))
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance));
} }
public RazorfieldRhino(final RazorfieldRhino card) { public RazorfieldRhino(final RazorfieldRhino card) {

View file

@ -1,35 +1,35 @@
package mage.cards.r; package mage.cards.r;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.game.permanent.token.TokenImpl; import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.Token;
import java.util.UUID;
/** /**
*
* @author Loki * @author Loki
*/ */
public final class RustedRelic extends CardImpl { public final class RustedRelic extends CardImpl {
public RustedRelic(UUID ownerId, CardSetInfo setInfo) { public RustedRelic(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// Metalcraft Rusted Relic is a 5/5 Golem artifact creature as long as you control three or more artifacts.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new ConditionalContinuousEffect( new ConditionalContinuousEffect(
new BecomesCreatureSourceEffect(new RustedRelicToken(), "artifact", Duration.WhileOnBattlefield), new BecomesCreatureSourceEffect(new RustedRelicToken(), "artifact", Duration.WhileOnBattlefield),
MetalcraftCondition.instance, MetalcraftCondition.instance,
"<i>Metalcraft</i> &mdash; {this} is a 5/5 Golem artifact creature as long as you control three or more artifacts"))); "<i>Metalcraft</i> &mdash; {this} is a 5/5 Golem artifact creature as long as you control three or more artifacts"))
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public RustedRelic(final RustedRelic card) { public RustedRelic(final RustedRelic card) {
@ -51,6 +51,7 @@ class RustedRelicToken extends TokenImpl {
power = new MageInt(5); power = new MageInt(5);
toughness = new MageInt(5); toughness = new MageInt(5);
} }
public RustedRelicToken(final RustedRelicToken token) { public RustedRelicToken(final RustedRelicToken token) {
super(token); super(token);
} }

View file

@ -1,6 +1,6 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -19,18 +19,11 @@ import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.stack.StackObject;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetadjustment.TargetAdjuster;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/** /**
* @author LevelX2 * @author LevelX2
*/ */
@ -80,16 +73,15 @@ class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
boolean controlledBy = isControlledBy(game.getControllerId(event.getSourceId())); if (!isControlledBy(game.getControllerId(event.getSourceId()))) {
if (!controlledBy) {
return false; return false;
} }
MageObject damageSource = game.getObject(event.getSourceId()); MageObject damageSource = game.getObject(event.getSourceId());
if (damageSource == null) { if (damageSource == null) {
return false; return false;
} }
UUID damageTarget = event.getTargetId(); UUID damageTargetId = event.getTargetId();
if (!game.getOpponents(getControllerId()).contains(damageTarget)) { if (!game.getOpponents(getControllerId()).contains(damageTargetId)) {
return false; return false;
} }
MageObject sourceObject = game.getObject(event.getSourceId()); MageObject sourceObject = game.getObject(event.getSourceId());
@ -97,7 +89,7 @@ class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl {
return false; return false;
} }
for (Effect effect : this.getEffects()) { for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(damageTarget)); // used by adjust targets effect.setTargetPointer(new FixedTarget(damageTargetId)); // used by adjust targets
effect.setValue("damage", event.getAmount()); effect.setValue("damage", event.getAmount());
} }
return true; return true;

View file

@ -1,4 +1,3 @@
package mage.cards.s; package mage.cards.s;
import mage.MageInt; import mage.MageInt;
@ -7,9 +6,11 @@ import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect; import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
@ -23,10 +24,10 @@ public final class ScreechingSilcaw extends CardImpl {
public ScreechingSilcaw(UUID ownerId, CardSetInfo setInfo) { public ScreechingSilcaw(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.BIRD); this.subtype.add(SubType.BIRD);
this.power = new MageInt(1); this.power = new MageInt(1);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
//"<i>Metalcraft</i> &mdash; Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard. //"<i>Metalcraft</i> &mdash; Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard.
@ -36,6 +37,8 @@ public final class ScreechingSilcaw extends CardImpl {
), MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; Whenever {this} " + ), MetalcraftCondition.instance, "<i>Metalcraft</i> &mdash; Whenever {this} " +
"deals combat damage to a player, if you control three or more artifacts, that player mills four cards." "deals combat damage to a player, if you control three or more artifacts, that player mills four cards."
); );
conditional.setAbilityWord(AbilityWord.METALCRAFT);
conditional.addHint(MetalcraftHint.instance);
this.addAbility(conditional); this.addAbility(conditional);
} }

View file

@ -1,5 +1,7 @@
package mage.cards.s; package mage.cards.s;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -18,9 +20,6 @@ import mage.players.Player;
import mage.target.TargetCard; import mage.target.TargetCard;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.List;
import java.util.UUID;
/** /**
* @author nantuko * @author nantuko
*/ */
@ -107,15 +106,19 @@ class SemblanceAnvilCostReductionEffect extends CostModificationEffectImpl {
@Override @Override
public boolean applies(Ability abilityToModify, Ability source, Game game) { public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify instanceof SpellAbility) { if (abilityToModify instanceof SpellAbility
Card sourceCard = game.getCard(abilityToModify.getSourceId()); && abilityToModify.isControlledBy(source.getControllerId())) {
if (sourceCard != null && sourceCard.isOwnedBy(source.getControllerId())) { Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);
if (spellCard != null) {
if (((SpellAbility) abilityToModify).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
spellCard = ((SpellAbility) abilityToModify).getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCard, game);
}
Permanent permanent = game.getPermanent(source.getSourceId()); Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) { if (permanent != null) {
List<UUID> imprinted = permanent.getImprinted(); List<UUID> imprinted = permanent.getImprinted();
if (imprinted != null && !imprinted.isEmpty()) { if (imprinted != null && !imprinted.isEmpty()) {
Card imprintedCard = game.getCard(imprinted.get(0)); Card imprintedCard = game.getCard(imprinted.get(0));
return imprintedCard != null && imprintedCard.shareTypes(sourceCard); return imprintedCard != null && imprintedCard.shareTypes(spellCard);
} }
} }
} }

View file

@ -1,24 +1,20 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration; import java.util.UUID;
import mage.constants.Zone;
/** /**
*
* @author Loki, nantuko * @author Loki, nantuko
*/ */
public final class SnapsailGlider extends CardImpl { public final class SnapsailGlider extends CardImpl {
@ -30,8 +26,12 @@ public final class SnapsailGlider extends CardImpl {
this.subtype.add(SubType.CONSTRUCT); this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(2); this.power = new MageInt(2);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// Metalcraft Snapsail Glider has flying as long as you control three or more artifacts.
ContinuousEffect effect = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield); ContinuousEffect effect = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect, MetalcraftCondition.instance, rule))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect, MetalcraftCondition.instance, rule))
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance));
} }
public SnapsailGlider(final SnapsailGlider card) { public SnapsailGlider(final SnapsailGlider card) {

View file

@ -1,23 +1,20 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.DoubleStrikeAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration; import java.util.UUID;
import mage.constants.Zone;
/** /**
*
* @author North * @author North
*/ */
public final class SpiralingDuelist extends CardImpl { public final class SpiralingDuelist extends CardImpl {
@ -28,12 +25,14 @@ public final class SpiralingDuelist extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}");
this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.BERSERKER); this.subtype.add(SubType.BERSERKER);
this.power = new MageInt(3); this.power = new MageInt(3);
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// Metalcraft Spiraling Duelist has double strike as long as you control three or more artifacts.
ContinuousEffect effect = new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield); ContinuousEffect effect = new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect, MetalcraftCondition.instance, effectText))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(effect, MetalcraftCondition.instance, effectText))
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance));
} }
public SpiralingDuelist(final SpiralingDuelist card) { public SpiralingDuelist(final SpiralingDuelist card) {

View file

@ -1,7 +1,5 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -11,16 +9,15 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect; import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration; import java.util.UUID;
import mage.constants.Zone;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public final class SpireSerpent extends CardImpl { public final class SpireSerpent extends CardImpl {
@ -34,13 +31,18 @@ public final class SpireSerpent extends CardImpl {
this.power = new MageInt(3); this.power = new MageInt(3);
this.toughness = new MageInt(5); this.toughness = new MageInt(5);
// Defender
this.addAbility(DefenderAbility.getInstance()); this.addAbility(DefenderAbility.getInstance());
// Metalcraft As long as you control three or more artifacts, Spire Serpent gets +2/+2 and can attack as though it didnt have defender.
ConditionalContinuousEffect effect1 = new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), MetalcraftCondition.instance, abilityText1); ConditionalContinuousEffect effect1 = new ConditionalContinuousEffect(new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield), MetalcraftCondition.instance, abilityText1);
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect1); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect1);
Effect effect = new ConditionalAsThoughEffect(new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.WhileOnBattlefield), Effect effect = new ConditionalAsThoughEffect(new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.WhileOnBattlefield),
MetalcraftCondition.instance); MetalcraftCondition.instance);
effect.setText("and can attack as though it didn't have defender"); effect.setText("and can attack as though it didn't have defender");
ability.addEffect(effect); ability.addEffect(effect);
ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -1,11 +1,11 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.effects.common.CounterTargetEffect; import mage.abilities.effects.common.CounterTargetEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord; import mage.constants.AbilityWord;
@ -13,6 +13,8 @@ import mage.constants.CardType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.target.TargetSpell; import mage.target.TargetSpell;
import java.util.UUID;
/** /**
* @author ayrat * @author ayrat
*/ */
@ -25,6 +27,7 @@ public final class StoicRebuttal extends CardImpl {
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(1, MetalcraftCondition.instance)); Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(1, MetalcraftCondition.instance));
ability.setRuleAtTheTop(true); ability.setRuleAtTheTop(true);
ability.setAbilityWord(AbilityWord.METALCRAFT); ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability); this.addAbility(ability);
// Counter target spell. // Counter target spell.

View file

@ -1,6 +1,5 @@
package mage.cards.t; package mage.cards.t;
import java.util.UUID;
import mage.abilities.LoyaltyAbility; import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
@ -8,16 +7,19 @@ import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.GetEmblemEffect; import mage.abilities.effects.common.GetEmblemEffect;
import mage.constants.SubType; import mage.abilities.hint.common.MetalcraftHint;
import mage.constants.SuperType;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.game.command.emblems.TezzeretArtificeMasterEmblem; import mage.game.command.emblems.TezzeretArtificeMasterEmblem;
import mage.game.permanent.token.ThopterColorlessToken; import mage.game.permanent.token.ThopterColorlessToken;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class TezzeretArtificeMaster extends CardImpl { public final class TezzeretArtificeMaster extends CardImpl {
@ -39,7 +41,9 @@ public final class TezzeretArtificeMaster extends CardImpl {
MetalcraftCondition.instance, MetalcraftCondition.instance,
"Draw a card. If you control three or " "Draw a card. If you control three or "
+ "more artifacts, draw two cards instead" + "more artifacts, draw two cards instead"
), 0)); ), 0)
.setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance));
// 9: You get an emblem with "At the beginning of your end step, search your library for a permanent card, put it into the battlefield, then shuffle your library." // 9: You get an emblem with "At the beginning of your end step, search your library for a permanent card, put it into the battlefield, then shuffle your library."
this.addAbility(new LoyaltyAbility( this.addAbility(new LoyaltyAbility(

View file

@ -1,5 +1,6 @@
package mage.cards.t; package mage.cards.t;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -14,8 +15,6 @@ import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID;
/** /**
* @author TheElk801 * @author TheElk801
*/ */

View file

@ -21,7 +21,7 @@ import mage.target.common.TargetCardInLibrary;
*/ */
public final class TrinketMage extends CardImpl { public final class TrinketMage extends CardImpl {
private static final FilterCard filter = new FilterCard("an artifact card with converted mana cost 1 or less"); private static final FilterCard filter = new FilterCard("artifact card with converted mana cost 1 or less");
static { static {
filter.add(CardType.ARTIFACT.getPredicate()); filter.add(CardType.ARTIFACT.getPredicate());

View file

@ -1,14 +1,12 @@
package mage.cards.v; package mage.cards.v;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord; import mage.constants.AbilityWord;
@ -19,9 +17,10 @@ import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import java.util.UUID;
/** /**
*
* @author Loki * @author Loki
*/ */
public final class VedalkenCertarch extends CardImpl { public final class VedalkenCertarch extends CardImpl {
@ -38,14 +37,14 @@ public final class VedalkenCertarch extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}");
this.subtype.add(SubType.VEDALKEN); this.subtype.add(SubType.VEDALKEN);
this.subtype.add(SubType.WIZARD); this.subtype.add(SubType.WIZARD);
this.power = new MageInt(1); this.power = new MageInt(1);
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// <i>Metalcraft</i> &mdash; {T}: Tap target artifact, creature, or land. Activate this ability only if you control three or more artifacts. // <i>Metalcraft</i> &mdash; {T}: Tap target artifact, creature, or land. Activate this ability only if you control three or more artifacts.
Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost(), MetalcraftCondition.instance); Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost(), MetalcraftCondition.instance);
ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addTarget(new TargetPermanent(filter)); ability.addTarget(new TargetPermanent(filter));
ability.setAbilityWord(AbilityWord.METALCRAFT);
ability.addHint(MetalcraftHint.instance);
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -1,6 +1,5 @@
package mage.cards.v; package mage.cards.v;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbility;
import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.AttacksTriggeredAbility;
@ -8,15 +7,18 @@ import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.continuous.LoseAllAbilitiesAllEffect; import mage.abilities.effects.common.continuous.LoseAllAbilitiesAllEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessAllEffect; import mage.abilities.effects.common.continuous.SetPowerToughnessAllEffect;
import mage.constants.SubType; import mage.abilities.hint.common.MetalcraftHint;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class VedalkenHumiliator extends CardImpl { public final class VedalkenHumiliator extends CardImpl {
@ -46,8 +48,10 @@ public final class VedalkenHumiliator extends CardImpl {
"<i>Metalcraft</i> &mdash; Whenever {this} attacks, " "<i>Metalcraft</i> &mdash; Whenever {this} attacks, "
+ "if you control three or more artifacts, " + "if you control three or more artifacts, "
+ "creatures your opponents control lose all abilities " + "creatures your opponents control lose all abilities "
+ "and have base power and toughness 1/1 until end of turn." + "and have base power and toughness 1/1 until end of turn.")
)); .setAbilityWord(AbilityWord.METALCRAFT)
.addHint(MetalcraftHint.instance)
);
} }
public VedalkenHumiliator(final VedalkenHumiliator card) { public VedalkenHumiliator(final VedalkenHumiliator card) {

View file

@ -0,0 +1,117 @@
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.GameException;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class PyromancersGauntletTest extends CardTestPlayerBase {
@Test
public void basicTest() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
// If a red instant or sorcery spell you control or a red planeswalker you control
// would deal damage to a permanent or player, it deals that much damage plus 2 to that permanent or player instead.
addCard(Zone.BATTLEFIELD, playerA, "Pyromancer's Gauntlet"); // Artifact {5}
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Pillarfield Ox");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertAllCommandsUsed();
assertLife(playerA, 20);
assertLife(playerB, 15); // Bolt 3 + 2
assertGraveyardCount(playerA, "Lightning Bolt", 2);
assertGraveyardCount(playerB, "Pillarfield Ox", 1);
}
@Test
public void opponentsPyromancersGauntletAppliedToOwnPlaneswalkerTest() {
setStrictChooseMode(true);
// +1: Elementals you control get +2/+0 until end of turn.
// 1: Add {R}{R}.
// 2: Chandra, Novice Pyromancer deals 2 damage to any target.
addCard(Zone.BATTLEFIELD, playerA, "Chandra, Novice Pyromancer"); // Planeswalker (5) {3}{R}
// If a red instant or sorcery spell you control or a red planeswalker you control
// would deal damage to a permanent or player, it deals that much damage plus 2 to that permanent or player instead.
addCard(Zone.BATTLEFIELD, playerB, "Pyromancer's Gauntlet"); // Creature 2/4 {1}{R}{R}{R}
addCard(Zone.BATTLEFIELD, playerB, "Chandra, Novice Pyromancer"); // Planeswalker (5) {3}{R}
addCard(Zone.BATTLEFIELD, playerB, "Barbarian Horde"); // Creature 3/3 {3}{R}
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-2:", playerB);
attack(2, playerB, "Barbarian Horde");
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "-2:", playerA);
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "-2:", "Barbarian Horde");
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertLife(playerA, 13); // Attack from Horde 3 + Dmage 2+2 from planeswalker
assertLife(playerB, 18); // Damage from planeswalker 2
assertPermanentCount(playerB, "Barbarian Horde", 1);
assertCounterCount(playerA, "Chandra, Novice Pyromancer", CounterType.LOYALTY, 1);
assertCounterCount(playerB, "Chandra, Novice Pyromancer", CounterType.LOYALTY, 3);
}
@Test
public void with3PlayersTest() throws GameException {
playerC = createPlayer(currentGame, playerC, "PlayerC");
setStrictChooseMode(true);
// +1: Elementals you control get +2/+0 until end of turn.
// 1: Add {R}{R}.
// 2: Chandra, Novice Pyromancer deals 2 damage to any target.
addCard(Zone.BATTLEFIELD, playerA, "Chandra, Novice Pyromancer"); // Planeswalker (5) {3}{R}
// If a red instant or sorcery spell you control or a red planeswalker you control
// would deal damage to a permanent or player, it deals that much damage plus 2 to that permanent or player instead.
addCard(Zone.BATTLEFIELD, playerC, "Pyromancer's Gauntlet"); // Creature 2/4 {1}{R}{R}{R}
addCard(Zone.BATTLEFIELD, playerB, "Chandra, Novice Pyromancer"); // Planeswalker (5) {3}{R}
addCard(Zone.BATTLEFIELD, playerB, "Barbarian Horde"); // Creature 3/3 {3}{R}
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-2:", playerB);
attack(3, playerB, "Barbarian Horde");
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerB, "-2:", playerA);
activateAbility(4, PhaseStep.PRECOMBAT_MAIN, playerA, "-2:", "Barbarian Horde");
setStopAt(4, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertLife(playerA, 15); // Attack from Horde 3 + Dmage 2 from planeswalker
assertLife(playerB, 18); // Damage from planeswalker 2
assertLife(playerC, 20);
assertPermanentCount(playerB, "Barbarian Horde", 1);
assertCounterCount(playerA, "Chandra, Novice Pyromancer", CounterType.LOYALTY, 1);
assertCounterCount(playerB, "Chandra, Novice Pyromancer", CounterType.LOYALTY, 3);
}
}

View file

@ -191,7 +191,6 @@ public class BestowTest extends CardTestPlayerBase {
addTarget(playerB, playerA); // Away addTarget(playerB, playerA); // Away
addTarget(playerA, "Nyxborn Rollicker"); addTarget(playerA, "Nyxborn Rollicker");
setStrictChooseMode(true); setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
@ -463,4 +462,26 @@ public class BestowTest extends CardTestPlayerBase {
Assert.assertFalse("The unattached Nighthowler may not have the aura subtype.", nighthowler.getSubtype(currentGame).contains(SubType.AURA)); Assert.assertFalse("The unattached Nighthowler may not have the aura subtype.", nighthowler.getSubtype(currentGame).contains(SubType.AURA));
} }
@Test
public void testCastBestowWithCostReduction() {
// Enchantment Creature Horror
// Bestow {5}{G} (If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature.)
// Trample
// Enchanted creature gets +3/+3 and has trample.
addCard(Zone.HAND, playerA, "Nylea's Emissary"); // Enchantment Creature
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // {1}{W} 2/2 creature
// Aura spells you cast cost {1} less to cast.
addCard(Zone.BATTLEFIELD, playerA, "Transcendent Envoy", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nylea's Emissary using bestow", "Silvercoat Lion");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Nylea's Emissary", 1);
assertPowerToughness(playerA, "Silvercoat Lion", 5, 5);
assertType("Nylea's Emissary", CardType.CREATURE, false);
assertType("Nylea's Emissary", CardType.ENCHANTMENT, SubType.AURA);
}
} }

View file

@ -1089,7 +1089,7 @@ public class MorphTest extends CardTestPlayerBase {
} }
@Test @Test
public void test_MorphWithCostReductionMustBePlayable_MorphCondition() { public void test_MorphWithCostReductionMustBePlayable_MorphCondition1() {
// {1}{U} creature // {1}{U} creature
// Morph {1}{U} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.) // Morph {1}{U} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)
// When Willbender is turned face up, change the target of target spell or ability with a single target. // When Willbender is turned face up, change the target of target spell or ability with a single target.
@ -1110,4 +1110,36 @@ public class MorphTest extends CardTestPlayerBase {
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1); assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
} }
@Test
public void test_MorphWithCostReductionMustBePlayable_MorphCondition2() {
// {1}{U} creature
// Morph {1}{U} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)
// When Willbender is turned face up, change the target of target spell or ability with a single target.
addCard(Zone.HAND, playerA, "Willbender", 2);
//addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
//
// The first face-down creature spell you cast each turn costs {3} less to cast.
addCard(Zone.BATTLEFIELD, playerA, "Kadena, Slinking Sorcerer");
// creature one - get cost reduce
checkPlayableAbility("can", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender", true);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender");
setChoice(playerA, "Yes"); // morph
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// creature two - do not get cost reduce
checkPlayableAbility("can't by no reduce", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender", false);
// on next turn it can cost reduce again
checkPlayableAbility("can't by not your turn", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender", false);
checkPlayableAbility("can", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender", true);
setStrictChooseMode(true);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
} }

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.abilities.oneshot.damage; package org.mage.test.cards.abilities.oneshot.damage;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
@ -11,7 +10,6 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
* *
* @author LevelX2 * @author LevelX2
*/ */
public class SatyrFiredancerTest extends CardTestPlayerBase { public class SatyrFiredancerTest extends CardTestPlayerBase {
@Test @Test
@ -57,7 +55,6 @@ public class SatyrFiredancerTest extends CardTestPlayerBase {
assertPermanentCount(playerB, "Silvercoat Lion", 1); assertPermanentCount(playerB, "Silvercoat Lion", 1);
} }
@Test @Test
public void testDamageFromOtherCreature() { public void testDamageFromOtherCreature() {
// Whenever an instant or sorcery spell you control deals damage to an opponent, Satyr Firedancer deals that much damage to target creature that player controls. // Whenever an instant or sorcery spell you control deals damage to an opponent, Satyr Firedancer deals that much damage to target creature that player controls.
@ -82,6 +79,7 @@ public class SatyrFiredancerTest extends CardTestPlayerBase {
playerC = createPlayer(currentGame, playerC, "PlayerC"); playerC = createPlayer(currentGame, playerC, "PlayerC");
addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer", 1); addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
// Price of Progress deals damage to each player equal to twice the number of nonbasic lands that player controls.
addCard(Zone.HAND, playerA, "Price of Progress", 1); addCard(Zone.HAND, playerA, "Price of Progress", 1);
addCard(Zone.BATTLEFIELD, playerB, "Taiga", 1); addCard(Zone.BATTLEFIELD, playerB, "Taiga", 1);

View file

@ -84,7 +84,7 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}, Sacrifice a permanent you control: Return target creature to its owner's hand."); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}, Sacrifice a permanent you control: Return target creature to its owner's hand.");
addTarget(playerB, "Angel of Jubilation"); // return to hand addTarget(playerB, "Angel of Jubilation"); // return to hand
setChoice(playerB, "Food Chain"); // cacrifice cost setChoice(playerB, "Food Chain"); // sacrifice cost
setStrictChooseMode(true); setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);

View file

@ -240,4 +240,60 @@ public class TappedForManaRelatedTest extends CardTestPlayerBase {
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
assertManaOptions("{Any}", manaOptions); assertManaOptions("{Any}", manaOptions);
} }
@Test
public void TestEyeOfRamos() {
setStrictChooseMode(true);
// {T}: Add {U}.
// Sacrifice Eye of Ramos: Add {U}.
addCard(Zone.BATTLEFIELD, playerA, "Eye of Ramos", 2);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
assertManaOptions("{U}{U}{U}{U}", manaOptions);
}
@Test
public void TestFarrelitePriest() {
setStrictChooseMode(true);
// {1}: Add {W}. If this ability has been activated four or more times this turn, sacrifice Farrelite Priest at the beginning of the next end step.
addCard(Zone.BATTLEFIELD, playerA, "Farrelite Priest", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
Assert.assertEquals("mana variations don't fit", 5, manaOptions.size());
assertManaOptions("{W}{W}{W}{W}", manaOptions);
assertManaOptions("{W}{W}{W}{B}", manaOptions);
assertManaOptions("{W}{W}{B}{B}", manaOptions);
assertManaOptions("{W}{B}{B}{B}", manaOptions);
assertManaOptions("{B}{B}{B}{B}", manaOptions);
}
@Test
public void TestMorselhoarder() {
setStrictChooseMode(true);
// Morselhoarder enters the battlefield with two -1/-1 counters on it.
// Remove a -1/-1 counter from Morselhoarder: Add one mana of any color.
addCard(Zone.BATTLEFIELD, playerA, "Morselhoarder", 2);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame);
Assert.assertEquals("mana variations don't fit", 1, manaOptions.size());
assertManaOptions("{B}{B}{Any}{Any}{Any}{Any}", manaOptions);
}
} }

View file

@ -0,0 +1,114 @@
package org.mage.test.cards.single.eld;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.GameException;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class TorbranThaneOfRedFellTest extends CardTestPlayerBase {
@Test
public void basicTest() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
// If a red source you control would deal damage to an opponent or a permanent an opponent controls,
// it deals that much damage plus 2 instead.
addCard(Zone.BATTLEFIELD, playerA, "Torbran, Thane of Red Fell"); // Creature 2/4 {1}{R}{R}{R}
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
attack(1, playerA, "Torbran, Thane of Red Fell");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Pillarfield Ox");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertAllCommandsUsed();
assertLife(playerA, 20);
assertLife(playerB, 11); // damage from: attack 2 + 2 Bolt 3 + 2
assertGraveyardCount(playerA, "Lightning Bolt", 2);
assertGraveyardCount(playerB, "Pillarfield Ox", 1);
}
@Test
public void opponentsTornbanAppliedToOwnPlaneswalkerTest() {
setStrictChooseMode(true);
// +1: Elementals you control get +2/+0 until end of turn.
// 1: Add {R}{R}.
// 2: Chandra, Novice Pyromancer deals 2 damage to any target.
addCard(Zone.BATTLEFIELD, playerA, "Chandra, Novice Pyromancer"); // Planeswalker (5) {3}{R}
// If a red source you control would deal damage to an opponent or a permanent an opponent controls,
// it deals that much damage plus 2 instead.
addCard(Zone.BATTLEFIELD, playerB, "Torbran, Thane of Red Fell"); // Creature 2/4 {1}{R}{R}{R}
addCard(Zone.BATTLEFIELD, playerB, "Barbarian Horde"); // Creature 3/3 {3}{R}
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-2:", playerB);
attack(2, playerB, "Barbarian Horde");
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "-2:", "Barbarian Horde");
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertLife(playerA, 15); // Attack from Horde 3+2
assertLife(playerB, 18); // Damage from planeswalker 2
assertPermanentCount(playerB, "Barbarian Horde", 1);
assertCounterCount("Chandra, Novice Pyromancer", CounterType.LOYALTY, 1);
}
@Test
public void with3PlayersTest() throws GameException {
playerC = createPlayer(currentGame, playerC, "PlayerC");
setStrictChooseMode(true);
// +1: Elementals you control get +2/+0 until end of turn.
// 1: Add {R}{R}.
// 2: Chandra, Novice Pyromancer deals 2 damage to any target.
addCard(Zone.BATTLEFIELD, playerA, "Chandra, Novice Pyromancer"); // Planeswalker (5) {3}{R}
// If a red source you control would deal damage to an opponent or a permanent an opponent controls,
// it deals that much damage plus 2 instead.
addCard(Zone.BATTLEFIELD, playerC, "Torbran, Thane of Red Fell"); // Creature 2/4 {1}{R}{R}{R}
addCard(Zone.BATTLEFIELD, playerB, "Barbarian Horde"); // Creature 3/3 {3}{R}
addCard(Zone.BATTLEFIELD, playerB, "Chandra, Novice Pyromancer"); // Planeswalker (5) {3}{R}
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-2:", playerB);
attack(3, playerB, "Barbarian Horde", playerA);
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerB, "-2:", playerA);
activateAbility(4, PhaseStep.PRECOMBAT_MAIN, playerA, "-2:", "Barbarian Horde");
setStopAt(4, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertLife(playerA, 15); // Attack from Horde 3+2
assertLife(playerB, 18); // Damage from planeswalker 2
assertPermanentCount(playerB, "Barbarian Horde", 1);
assertCounterCount(playerA, "Chandra, Novice Pyromancer", CounterType.LOYALTY, 1);
assertCounterCount(playerB, "Chandra, Novice Pyromancer", CounterType.LOYALTY, 3);
}
}

View file

@ -453,7 +453,7 @@ public interface Ability extends Controllable, Serializable {
* *
* @param abilityWord * @param abilityWord
*/ */
void setAbilityWord(AbilityWord abilityWord); Ability setAbilityWord(AbilityWord abilityWord);
/** /**
* Creates the message about the ability casting/triggering/activating to * Creates the message about the ability casting/triggering/activating to

View file

@ -8,6 +8,7 @@ import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects; import mage.abilities.effects.Effects;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.hint.Hint; import mage.abilities.hint.Hint;
import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.Card; import mage.cards.Card;
@ -34,7 +35,6 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.abilities.effects.common.ManaEffect;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -54,7 +54,7 @@ public abstract class AbilityImpl implements Ability {
protected ManaCosts<ManaCost> manaCostsToPay; protected ManaCosts<ManaCost> manaCostsToPay;
protected Costs<Cost> costs; protected Costs<Cost> costs;
protected Costs<Cost> optionalCosts; protected Costs<Cost> optionalCosts;
protected Modes modes; // access to it by GetModes only (it's can be override by some abilities) protected Modes modes; // access to it by GetModes only (it can be overridden by some abilities)
protected Zone zone; protected Zone zone;
protected String name; protected String name;
protected AbilityWord abilityWord; protected AbilityWord abilityWord;
@ -65,7 +65,7 @@ public abstract class AbilityImpl implements Ability {
protected boolean activated = false; protected boolean activated = false;
protected boolean worksFaceDown = false; protected boolean worksFaceDown = false;
protected int sourceObjectZoneChangeCounter; protected int sourceObjectZoneChangeCounter;
protected List<Watcher> watchers = new ArrayList<>(); // access to it by GetWatchers only (it's can be override by some abilities) protected List<Watcher> watchers = new ArrayList<>(); // access to it by GetWatchers only (it can be overridden by some abilities)
protected List<Ability> subAbilities = null; protected List<Ability> subAbilities = null;
protected boolean canFizzle = true; protected boolean canFizzle = true;
protected TargetAdjuster targetAdjuster = null; protected TargetAdjuster targetAdjuster = null;
@ -1022,8 +1022,9 @@ public abstract class AbilityImpl implements Ability {
} }
@Override @Override
public void setAbilityWord(AbilityWord abilityWord) { public Ability setAbilityWord(AbilityWord abilityWord) {
this.abilityWord = abilityWord; this.abilityWord = abilityWord;
return this;
} }
@Override @Override
@ -1243,10 +1244,13 @@ public abstract class AbilityImpl implements Ability {
} }
/** /**
* Dynamic cost modification for ability. * Dynamic cost modification for ability.<br>
* Example: if it need stack related info (like real targets) then must check two states (game.inCheckPlayableState): * Example: if it need stack related info (like real targets) then must
* 1. In playable state it must check all possible use cases (e.g. allow to reduce on any available target and modes) * check two states (game.inCheckPlayableState): <br>
* 2. In real cast state it must check current use case (e.g. real selected targets and modes) * 1. In playable state it must check all possible use cases (e.g. allow to
* reduce on any available target and modes) <br>
* 2. In real cast state it must check current use case (e.g. real selected
* targets and modes)
* *
* @param costAdjuster * @param costAdjuster
*/ */

View file

@ -1,18 +1,15 @@
package mage.abilities.effects.common; package mage.abilities.effects.common;
import mage.constants.Outcome; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode; import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import java.util.UUID;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -59,12 +56,13 @@ public class GainLifeTargetEffect extends OneShotEffect {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String message = life.getMessage(); String message = life.getMessage();
if (!mode.getTargets().isEmpty()) { if (!mode.getTargets().isEmpty() && mode.getTargets().get(0).getMaxNumberOfTargets() == Integer.MAX_VALUE) {
sb.append("target ").append(mode.getTargets().get(0).getTargetName()); sb.append("any number of target players each gain ");
} else if (!mode.getTargets().isEmpty()) {
sb.append("target ").append(mode.getTargets().get(0).getTargetName()).append(" gains ");
} else { } else {
sb.append("that player"); sb.append("that player gains ");
} }
sb.append(" gains ");
if (message.isEmpty() || !message.equals("1")) { if (message.isEmpty() || !message.equals("1")) {
sb.append(life.toString()).append(' '); sb.append(life.toString()).append(' ');
} }

View file

@ -18,7 +18,7 @@ import mage.util.CardUtil;
*/ */
public class AbilitiesCostReductionControllerEffect extends CostModificationEffectImpl { public class AbilitiesCostReductionControllerEffect extends CostModificationEffectImpl {
private Class activatedAbility; private final Class activatedAbility;
public AbilitiesCostReductionControllerEffect(Class activatedAbility, String activatedAbilityName) { public AbilitiesCostReductionControllerEffect(Class activatedAbility, String activatedAbilityName) {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST); super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);

View file

@ -10,8 +10,6 @@ import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID;
public class CostModificationSourceEffect extends CostModificationEffectImpl { public class CostModificationSourceEffect extends CostModificationEffectImpl {
private final Class<? extends Ability> abilityType; private final Class<? extends Ability> abilityType;

View file

@ -18,7 +18,7 @@ import mage.util.CardUtil;
public class SpellCostReductionForEachSourceEffect extends CostModificationEffectImpl { public class SpellCostReductionForEachSourceEffect extends CostModificationEffectImpl {
private final DynamicValue eachAmount; private final DynamicValue eachAmount;
private ManaCosts<ManaCost> reduceManaCosts; private final ManaCosts<ManaCost> reduceManaCosts;
private final int reduceGenericMana; private final int reduceGenericMana;
public SpellCostReductionForEachSourceEffect(int reduceGenericMana, DynamicValue eachAmount) { public SpellCostReductionForEachSourceEffect(int reduceGenericMana, DynamicValue eachAmount) {
@ -50,7 +50,6 @@ public class SpellCostReductionForEachSourceEffect extends CostModificationEffec
this.staticText = sb.toString(); this.staticText = sb.toString();
} }
protected SpellCostReductionForEachSourceEffect(final SpellCostReductionForEachSourceEffect effect) { protected SpellCostReductionForEachSourceEffect(final SpellCostReductionForEachSourceEffect effect) {
super(effect); super(effect);
this.eachAmount = effect.eachAmount; this.eachAmount = effect.eachAmount;

View file

@ -23,7 +23,7 @@ public class SpellsCostIncreasingAllEffect extends CostModificationEffectImpl {
private final FilterCard filter; private final FilterCard filter;
private final TargetController targetController; private final TargetController targetController;
private final int increaseGenericCost; private final int increaseGenericCost;
private ManaCosts<ManaCost> increaseManaCosts; private final ManaCosts<ManaCost> increaseManaCosts;
public SpellsCostIncreasingAllEffect(int increaseGenericCost, FilterCard filter, TargetController targetController) { public SpellsCostIncreasingAllEffect(int increaseGenericCost, FilterCard filter, TargetController targetController) {
super(Duration.WhileOnBattlefield, Outcome.Detriment, CostModificationType.INCREASE_COST); super(Duration.WhileOnBattlefield, Outcome.Detriment, CostModificationType.INCREASE_COST);

View file

@ -1,5 +1,7 @@
package mage.abilities.effects.common.cost; package mage.abilities.effects.common.cost;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.constants.CostModificationType; import mage.constants.CostModificationType;
@ -12,9 +14,6 @@ import mage.game.stack.Spell;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.Set;
import java.util.UUID;
/** /**
* @author JayDi85 * @author JayDi85
*/ */
@ -23,7 +22,7 @@ public class SpellsCostModificationThatTargetSourceEffect extends CostModificati
private final FilterCard spellFilter; private final FilterCard spellFilter;
private final int modificationAmount; private final int modificationAmount;
private String targetName = "{this}"; private String targetName = "{this}";
private TargetController targetController; private final TargetController targetController;
public SpellsCostModificationThatTargetSourceEffect(int modificationAmount, FilterCard spellFilter, TargetController targetController) { public SpellsCostModificationThatTargetSourceEffect(int modificationAmount, FilterCard spellFilter, TargetController targetController) {
super(Duration.WhileOnBattlefield, Outcome.Neutral, modificationAmount < 0 ? CostModificationType.REDUCE_COST : CostModificationType.INCREASE_COST); super(Duration.WhileOnBattlefield, Outcome.Neutral, modificationAmount < 0 ? CostModificationType.REDUCE_COST : CostModificationType.INCREASE_COST);

View file

@ -1,5 +1,8 @@
package mage.abilities.effects.common.cost; package mage.abilities.effects.common.cost;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import mage.Mana; import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
@ -8,16 +11,12 @@ import mage.choices.ChoiceImpl;
import mage.constants.CostModificationType; import mage.constants.CostModificationType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SpellAbilityCastMode;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.game.Game; import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
/** /**
* @author LevelX2 * @author LevelX2
*/ */
@ -123,15 +122,12 @@ public class SpellsCostReductionAllEffect extends CostModificationEffectImpl {
return false; return false;
} }
if (abilityToModify instanceof SpellAbility) { if (abilityToModify instanceof SpellAbility) {
Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);
if (spell != null) { if (spellCard != null) {
// real cast with put on stack if (((SpellAbility) abilityToModify).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
return this.filter.match(spell, game) && selectedByRuntimeData(spell, source, game); spellCard = ((SpellAbility) abilityToModify).getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCard, game);
} else { }
// get playable and other staff without put on stack return this.filter.match(spellCard, game) && selectedByRuntimeData(spellCard, source, game);
// used at least for flashback ability because Flashback ability doesn't use stack
Card sourceCard = game.getCard(abilityToModify.getSourceId());
return sourceCard != null && this.filter.match(sourceCard, game) && selectedByRuntimeData(sourceCard, source, game);
} }
} }
return false; return false;

View file

@ -1,5 +1,7 @@
package mage.abilities.effects.common.cost; package mage.abilities.effects.common.cost;
import java.util.LinkedHashSet;
import java.util.Set;
import mage.MageObject; import mage.MageObject;
import mage.Mana; import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -11,15 +13,12 @@ import mage.choices.ChoiceImpl;
import mage.constants.CostModificationType; import mage.constants.CostModificationType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SpellAbilityCastMode;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.game.Game; import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.LinkedHashSet;
import java.util.Set;
/** /**
* @author North * @author North
*/ */
@ -114,15 +113,12 @@ public class SpellsCostReductionControllerEffect extends CostModificationEffectI
public boolean applies(Ability abilityToModify, Ability source, Game game) { public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify instanceof SpellAbility) { if (abilityToModify instanceof SpellAbility) {
if (abilityToModify.isControlledBy(source.getControllerId())) { if (abilityToModify.isControlledBy(source.getControllerId())) {
Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);;
if (spell != null) { if (spellCard != null) {
// real cast with put on stack if (((SpellAbility) abilityToModify).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
return this.filter.match(spell, source.getSourceId(), source.getControllerId(), game); spellCard = ((SpellAbility) abilityToModify).getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCard, game);
} else { }
// get playable and other staff without put on stack return this.filter.match(spellCard, source.getSourceId(), source.getControllerId(), game);
// used at least for flashback ability because Flashback ability doesn't use stack
Card sourceCard = game.getCard(abilityToModify.getSourceId());
return sourceCard != null && this.filter.match(sourceCard, source.getSourceId(), source.getControllerId(), game);
} }
} }
} }

View file

@ -0,0 +1,34 @@
package mage.abilities.hint.common;
import mage.abilities.Ability;
import mage.abilities.condition.common.MetalcraftCondition;
import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
import mage.constants.CardType;
import mage.filter.FilterPermanent;
import mage.game.Game;
/**
* @author JayDi85
*/
public enum MetalcraftHint implements Hint {
instance;
private static final ConditionHint hint = new ConditionHint(MetalcraftCondition.instance, "You control three or more artifacts");
private static final FilterPermanent filter = new FilterPermanent("artifact");
static {
filter.add(CardType.ARTIFACT.getPredicate());
}
@Override
public String getText(Game game, Ability ability) {
int amount = game.getBattlefield().countAll(filter, ability.getControllerId(), game);
return hint.getText(game, ability) + " (current: " + amount + ")";
}
@Override
public Hint copy() {
return instance;
}
}

View file

@ -1,4 +1,3 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
@ -138,6 +137,14 @@ public class BestowAbility extends SpellAbility {
} }
} }
static public void becomeAura(Card card) {
if (card != null) {
card.getSubtype(null).add(SubType.AURA);
card.getCardType().remove(CardType.CREATURE);
card.getCardType().add(CardType.ENCHANTMENT);
}
}
} }
class BestowEntersBattlefieldEffect extends ReplacementEffectImpl { class BestowEntersBattlefieldEffect extends ReplacementEffectImpl {

View file

@ -1,5 +1,8 @@
package mage.abilities.mana; package mage.abilities.mana;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.Mana; import mage.Mana;
import mage.abilities.ActivatedAbilityImpl; import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
@ -13,10 +16,6 @@ import mage.game.Game;
import mage.game.stack.Spell; import mage.game.stack.Spell;
import mage.game.stack.StackObject; import mage.game.stack.StackObject;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -87,7 +86,7 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
*/ */
@Override @Override
public List<Mana> getNetMana(Game game) { public List<Mana> getNetMana(Game game) {
if (netMana.isEmpty()) { if (netMana.isEmpty() || (game != null && game.inCheckPlayableState())) {
List<Mana> dynamicNetMana = new ArrayList<>(); List<Mana> dynamicNetMana = new ArrayList<>();
for (Effect effect : getEffects()) { for (Effect effect : getEffects()) {
if (effect instanceof ManaEffect) { if (effect instanceof ManaEffect) {

View file

@ -348,26 +348,34 @@ public class ManaOptions extends ArrayList<Mana> {
private boolean subtractCostAddMana(Mana cost, Mana manaToAdd, boolean onlyManaCosts, Mana currentMana) { private boolean subtractCostAddMana(Mana cost, Mana manaToAdd, boolean onlyManaCosts, Mana currentMana) {
boolean oldManaWasReplaced = false; // true if the newly created mana includes all mana possibilities of the old boolean oldManaWasReplaced = false; // true if the newly created mana includes all mana possibilities of the old
boolean repeatable = false; boolean repeatable = false;
if (manaToAdd.getAny() == 1 && manaToAdd.count() == 1 && onlyManaCosts) { if ((manaToAdd.countColored() > 0 || manaToAdd.getAny() > 0) && manaToAdd.count() > 0 && onlyManaCosts) {
// deactivated because it does cause loops TODO: Find reason // deactivated because it does cause loops TODO: Find reason
repeatable = true; // only replace to any with mana costs only will be repeated if able repeatable = true; // only replace to any with mana costs only will be repeated if able
} }
Mana prevMana = currentMana.copy(); Mana prevMana = currentMana.copy();
if (currentMana.includesMana(cost)) { // it can be paid if (currentMana.includesMana(cost)) { // cost can be paid
// generic mana costs can be paid with different colored mana, can lead to different color combinations // generic mana costs can be paid with different colored mana, can lead to different color combinations
if (cost.getGeneric() > 0 && cost.getGeneric() > (currentMana.getGeneric() + currentMana.getColorless())) { if (cost.getGeneric() > 0 && cost.getGeneric() > (currentMana.getGeneric() + currentMana.getColorless())) {
Mana coloredCost = cost.copy();
coloredCost.setGeneric(0);
currentMana.subtract(coloredCost);
for (Mana payCombination : getPossiblePayCombinations(cost.getGeneric(), currentMana)) { for (Mana payCombination : getPossiblePayCombinations(cost.getGeneric(), currentMana)) {
Mana newMana = currentMana.copy(); Mana currentManaCopy = currentMana.copy();
while (currentManaCopy.includesMana(payCombination)) { // loop for multiple usage if possible
boolean newCombinations = false;
Mana newMana = currentManaCopy.copy();
newMana.subtract(payCombination); newMana.subtract(payCombination);
newMana.add(manaToAdd); newMana.add(manaToAdd);
Mana moreValuable = Mana.getMoreValuableMana(prevMana, newMana); // Mana moreValuable = Mana.getMoreValuableMana(currentMana, newMana);
if (!prevMana.equals(moreValuable)) { if (!isExistingManaCombination(newMana)) {
this.add(newMana); this.add(newMana); // add the new combination
if (moreValuable != null) { newCombinations = true; // repeat the while as long there are new combinations and usage is repeatable
oldManaWasReplaced = true; // the new mana includes all possibilities of the old one currentManaCopy = newMana.copy();
Mana moreValuable = Mana.getMoreValuableMana(currentMana, newMana);
if (!oldManaWasReplaced && newMana.equals(moreValuable)) {
oldManaWasReplaced = true; // the new mana includes all possibilities of the old one, so no need to add it after return
}
}
if (!newCombinations || !repeatable) {
break;
} }
} }
@ -447,6 +455,16 @@ public class ManaOptions extends ArrayList<Mana> {
return payCombinations; return payCombinations;
} }
private boolean isExistingManaCombination(Mana newMana) {
for (Mana mana : this) {
Mana moreValuable = Mana.getMoreValuableMana(mana, newMana);
if (mana.equals(moreValuable)) {
return true;
}
}
return false;
}
private void addManaCombination(Mana mana, Mana existingMana, List<Mana> payCombinations, List<String> payCombinationsStrings) { private void addManaCombination(Mana mana, Mana existingMana, List<Mana> payCombinations, List<String> payCombinationsStrings) {
Mana newMana = existingMana.copy(); Mana newMana = existingMana.copy();
newMana.add(mana); newMana.add(mana);
@ -478,4 +496,20 @@ public class ManaOptions extends ArrayList<Mana> {
} }
} }
} }
/**
* Checks if the given mana (cost) is already included in one available mana
* option
*
* @param mana
* @return
*/
public boolean enough(Mana mana) {
for (Mana avail : this) {
if (mana.enough(avail)) {
return true;
}
}
return false;
}
} }

View file

@ -1,6 +1,9 @@
package mage.constants; package mage.constants;
import mage.abilities.keyword.BestowAbility;
import mage.cards.Card;
import mage.game.Game;
/** /**
* *
* @author LevelX2 * @author LevelX2
@ -21,4 +24,12 @@ public enum SpellAbilityCastMode {
public String toString() { public String toString() {
return text; return text;
} }
public Card getTypeModifiedCardObjectCopy(Card card, Game game) {
Card cardCopy = card.copy();
if (this.equals(BESTOW)) {
BestowAbility.becomeAura(cardCopy);
}
return cardCopy;
}
} }

View file

@ -0,0 +1,24 @@
package mage.filter.predicate.other;
import mage.abilities.keyword.MorphAbility;
import mage.cards.Card;
import mage.filter.predicate.Predicate;
import mage.game.Game;
/**
* @author JayDi85
*/
public enum FaceDownCastablePredicate implements Predicate<Card> {
instance;
@Override
public boolean apply(Card input, Game game) {
// is card able to cast as face down
return input.getAbilities(game).containsClass(MorphAbility.class);
}
@Override
public String toString() {
return "Face-down";
}
}

View file

@ -1,5 +1,7 @@
package mage.game.command.planes; package mage.game.command.planes;
import java.util.ArrayList;
import java.util.List;
import mage.MageObject; import mage.MageObject;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -29,9 +31,6 @@ import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil; import mage.util.CardUtil;
import mage.watchers.common.PlanarRollWatcher; import mage.watchers.common.PlanarRollWatcher;
import java.util.ArrayList;
import java.util.List;
/** /**
* @author spjspj * @author spjspj
*/ */
@ -52,9 +51,9 @@ public class FeedingGroundsPlane extends Plane {
Effect chaosEffect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(), TargetConvertedManaCost.instance); Effect chaosEffect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(), TargetConvertedManaCost.instance);
Target chaosTarget = new TargetCreaturePermanent(1, 1, filter, false); Target chaosTarget = new TargetCreaturePermanent(1, 1, filter, false);
List<Effect> chaosEffects = new ArrayList<Effect>(); List<Effect> chaosEffects = new ArrayList<>();
chaosEffects.add(chaosEffect); chaosEffects.add(chaosEffect);
List<Target> chaosTargets = new ArrayList<Target>(); List<Target> chaosTargets = new ArrayList<>();
chaosTargets.add(chaosTarget); chaosTargets.add(chaosTarget);
ActivateIfConditionActivatedAbility chaosAbility = new ActivateIfConditionActivatedAbility(Zone.COMMAND, new RollPlanarDieEffect(chaosEffects, chaosTargets), new GenericManaCost(0), MainPhaseStackEmptyCondition.instance); ActivateIfConditionActivatedAbility chaosAbility = new ActivateIfConditionActivatedAbility(Zone.COMMAND, new RollPlanarDieEffect(chaosEffects, chaosTargets), new GenericManaCost(0), MainPhaseStackEmptyCondition.instance);

View file

@ -17,7 +17,6 @@ import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.game.Game; import mage.game.Game;
import mage.game.command.Plane; import mage.game.command.Plane;
import mage.game.stack.Spell;
import mage.target.Target; import mage.target.Target;
import mage.util.CardUtil; import mage.util.CardUtil;
import mage.watchers.common.PlanarRollWatcher; import mage.watchers.common.PlanarRollWatcher;
@ -42,9 +41,9 @@ public class TurriIslandPlane extends Plane {
Effect chaosEffect = new RevealLibraryPutIntoHandEffect(3, new FilterCreatureCard("creature cards"), Zone.GRAVEYARD); Effect chaosEffect = new RevealLibraryPutIntoHandEffect(3, new FilterCreatureCard("creature cards"), Zone.GRAVEYARD);
Target chaosTarget = null; Target chaosTarget = null;
List<Effect> chaosEffects = new ArrayList<Effect>(); List<Effect> chaosEffects = new ArrayList<>();
chaosEffects.add(chaosEffect); chaosEffects.add(chaosEffect);
List<Target> chaosTargets = new ArrayList<Target>(); List<Target> chaosTargets = new ArrayList<>();
chaosTargets.add(chaosTarget); chaosTargets.add(chaosTarget);
ActivateIfConditionActivatedAbility chaosAbility = new ActivateIfConditionActivatedAbility(Zone.COMMAND, new RollPlanarDieEffect(chaosEffects, chaosTargets), new GenericManaCost(0), MainPhaseStackEmptyCondition.instance); ActivateIfConditionActivatedAbility chaosAbility = new ActivateIfConditionActivatedAbility(Zone.COMMAND, new RollPlanarDieEffect(chaosEffects, chaosTargets), new GenericManaCost(0), MainPhaseStackEmptyCondition.instance);
@ -110,14 +109,12 @@ class TurriIslandEffect extends CostModificationEffectImpl {
if (!cPlane.getPlaneType().equals(Planes.PLANE_TURRI_ISLAND)) { if (!cPlane.getPlaneType().equals(Planes.PLANE_TURRI_ISLAND)) {
return false; return false;
} }
Card spellCard = ((SpellAbility) abilityToModify).getCharacteristics(game);
Spell spell = (Spell) game.getStack().getStackObject(abilityToModify.getId()); if (spellCard != null) {
if (spell != null) { if (((SpellAbility) abilityToModify).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
return filter.match(spell, game) && selectedByRuntimeData(spell, source, game); spellCard = ((SpellAbility) abilityToModify).getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCard, game);
} else { }
// used at least for flashback ability because Flashback ability doesn't use stack return filter.match(spellCard, game) && selectedByRuntimeData(spellCard, source, game);
Card sourceCard = game.getCard(abilityToModify.getSourceId());
return sourceCard != null && filter.match(sourceCard, game) && selectedByRuntimeData(sourceCard, source, game);
} }
} }
return false; return false;

View file

@ -472,7 +472,7 @@ public class StackAbility extends StackObjImpl implements Ability {
} }
@Override @Override
public void setAbilityWord(AbilityWord abilityWord) { public Ability setAbilityWord(AbilityWord abilityWord) {
throw new UnsupportedOperationException("Not supported."); throw new UnsupportedOperationException("Not supported.");
} }

View file

@ -3156,11 +3156,14 @@ public abstract class PlayerImpl implements Player, Serializable {
sourceObject.adjustCosts(copyAbility, game); sourceObject.adjustCosts(copyAbility, game);
game.getContinuousEffects().costModification(copyAbility, game); game.getContinuousEffects().costModification(copyAbility, game);
for (Mana mana : copyAbility.getManaCostsToPay().getOptions()) { // reduced all cost
for (Mana avail : availableMana) { if (copyAbility.getManaCostsToPay().isEmpty()) {
if (mana.enough(avail)) {
return true; return true;
} }
for (Mana mana : copyAbility.getManaCostsToPay().getOptions()) {
if (availableMana.enough(mana)) {
return true;
} }
} }
} }
@ -3195,11 +3198,14 @@ public abstract class PlayerImpl implements Player, Serializable {
sourceObject.adjustCosts(copyAbility, game); sourceObject.adjustCosts(copyAbility, game);
game.getContinuousEffects().costModification(copyAbility, game); game.getContinuousEffects().costModification(copyAbility, game);
for (Mana mana : copyAbility.getManaCostsToPay().getOptions()) { // reduced all cost
for (Mana avail : availableMana) { if (copyAbility.getManaCostsToPay().isEmpty()) {
if (mana.enough(avail)) {
return true; return true;
} }
for (Mana mana : copyAbility.getManaCostsToPay().getOptions()) {
if (availableMana.enough(mana)) {
return true;
} }
} }
} }
@ -3247,7 +3253,7 @@ public abstract class PlayerImpl implements Player, Serializable {
protected ActivatedAbility findActivatedAbilityFromAlternativeSourceCost(MageObject object, ManaOptions availableMana, Ability ability, Game game) { protected ActivatedAbility findActivatedAbilityFromAlternativeSourceCost(MageObject object, ManaOptions availableMana, Ability ability, Game game) {
// return play ability that can activate AlternativeSourceCosts // return play ability that can activate AlternativeSourceCosts
if (ability instanceof AlternativeSourceCosts && !(object instanceof Permanent)) { if (ability instanceof AlternativeSourceCosts && object != null && !(object instanceof Permanent)) {
ActivatedAbility playAbility = null; ActivatedAbility playAbility = null;
if (object.isLand()) { if (object.isLand()) {
playAbility = (PlayLandAbility) CardUtil.getAbilities(object, game).stream().filter(a -> a instanceof PlayLandAbility).findFirst().orElse(null); playAbility = (PlayLandAbility) CardUtil.getAbilities(object, game).stream().filter(a -> a instanceof PlayLandAbility).findFirst().orElse(null);
@ -3263,8 +3269,8 @@ public abstract class PlayerImpl implements Player, Serializable {
// Even mana cost can't be checked here without lookahead // Even mana cost can't be checked here without lookahead
// So make it available all the time // So make it available all the time
boolean canUse; boolean canUse;
if (ability instanceof MorphAbility) { if (ability instanceof MorphAbility && object instanceof Card && game.canPlaySorcery(getId())) {
canUse = game.canPlaySorcery(playerId) && ((MorphAbility) ability).isAvailable(playAbility, game); canUse = canPlayCardByAlternateCost((Card) object, availableMana, playAbility, game);
} else { } else {
canUse = canPlay(playAbility, availableMana, object, game); // canPlay already checks alternative source costs and all conditions canUse = canPlay(playAbility, availableMana, object, game); // canPlay already checks alternative source costs and all conditions
} }