mirror of
https://github.com/correl/mage.git
synced 2024-11-15 11:09:30 +00:00
Merge origin/master
This commit is contained in:
commit
8096d2f4aa
149 changed files with 3642 additions and 1338 deletions
|
@ -4,6 +4,7 @@
|
|||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1
|
||||
http://maven.apache.org/xsd/assembly-1.1.1.xsd">
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<id>mage-client</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
|
|
|
@ -682,6 +682,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
gamePane.watchGame(gameId);
|
||||
setActive(gamePane);
|
||||
} catch (PropertyVetoException ex) {
|
||||
LOGGER.debug("Problem starting watching game " + gameId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1068,9 +1069,11 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
if (setActive) {
|
||||
setActive(tablesPane);
|
||||
} else // if other panel was already shown, mamke sure it's topmost again
|
||||
if (topPanebefore != null) {
|
||||
{
|
||||
if (topPanebefore != null) {
|
||||
setActive(topPanebefore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void hideGames() {
|
||||
|
@ -1417,6 +1420,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
|||
break;
|
||||
case CLIENT_STOP_WATCHING:
|
||||
session.stopWatching(userRequestMessage.getGameId());
|
||||
GamePanel gamePanel = getGame(userRequestMessage.getGameId());
|
||||
if (gamePanel != null) {
|
||||
gamePanel.removeGame();
|
||||
}
|
||||
removeGame(userRequestMessage.getGameId());
|
||||
break;
|
||||
case CLIENT_EXIT:
|
||||
|
|
|
@ -78,6 +78,7 @@ public class CardGrid extends javax.swing.JLayeredPane implements MouseListener,
|
|||
|
||||
public CardGrid() {
|
||||
initComponents();
|
||||
setGUISize();
|
||||
setOpaque(false);
|
||||
}
|
||||
|
||||
|
@ -90,6 +91,14 @@ public class CardGrid extends javax.swing.JLayeredPane implements MouseListener,
|
|||
this.bigCard = null;
|
||||
}
|
||||
|
||||
public void changeGUISize() {
|
||||
setGUISize();
|
||||
}
|
||||
|
||||
private void setGUISize() {
|
||||
cardDimension = GUISizeHelper.editorCardDimension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId) {
|
||||
this.loadCards(showCards, sortSetting, bigCard, gameId, true);
|
||||
|
@ -125,9 +134,6 @@ public class CardGrid extends javax.swing.JLayeredPane implements MouseListener,
|
|||
}
|
||||
|
||||
private void addCard(CardView card, BigCard bigCard, UUID gameId, boolean drawImage) {
|
||||
if (cardDimension == null) {
|
||||
cardDimension = GUISizeHelper.editorCardDimension;
|
||||
}
|
||||
MageCard cardImg = Plugins.getInstance().getMageCard(card, bigCard, cardDimension, gameId, drawImage);
|
||||
cards.put(card.getId(), cardImg);
|
||||
cardImg.addMouseListener(this);
|
||||
|
|
|
@ -149,7 +149,6 @@ public class CardsList extends javax.swing.JPanel implements MouseListener, ICar
|
|||
|
||||
private void setGUISize() {
|
||||
mainTable.getTableHeader().setFont(GUISizeHelper.tableFont);
|
||||
mainTable.getTableHeader().setPreferredSize(new Dimension(GUISizeHelper.tableHeaderHeight, GUISizeHelper.tableHeaderHeight));
|
||||
mainTable.setFont(GUISizeHelper.tableFont);
|
||||
mainTable.setRowHeight(GUISizeHelper.getTableRowHeight());
|
||||
cardDimension = GUISizeHelper.editorCardDimension;
|
||||
|
|
|
@ -2,13 +2,29 @@ package mage.client.components;
|
|||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Point;
|
||||
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkEvent.EventType;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import javax.swing.text.html.HTMLDocument;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.gui.GuiDisplayUtil;
|
||||
import mage.components.CardInfoPane;
|
||||
import mage.utils.ThreadUtils;
|
||||
import mage.view.CardView;
|
||||
|
||||
/**
|
||||
* Enhanced {@link JTextPane} with text highlighting support.
|
||||
*
|
||||
|
@ -18,10 +34,68 @@ public class ColorPane extends JEditorPane {
|
|||
|
||||
HTMLEditorKit kit = new HTMLEditorKit();
|
||||
HTMLDocument doc = new HTMLDocument();
|
||||
private int tooltipDelay;
|
||||
|
||||
public ColorPane() {
|
||||
this.setEditorKit(kit);
|
||||
this.setDocument(doc);
|
||||
addHyperlinkListener(new HyperlinkListener() {
|
||||
|
||||
@Override
|
||||
public void hyperlinkUpdate(final HyperlinkEvent e) {
|
||||
ThreadUtils.threadPool2.submit(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
tooltipDelay = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_TOOLTIPS_DELAY, 300);
|
||||
if (tooltipDelay == 0) {
|
||||
return;
|
||||
}
|
||||
String name = e.getDescription().substring(1);
|
||||
CardInfo card = CardRepository.instance.findCard(name);
|
||||
try {
|
||||
final Component container = MageFrame.getUI().getComponent(MageComponents.POPUP_CONTAINER);
|
||||
if (e.getEventType() == EventType.EXITED) {
|
||||
setPopupVisibility(null, container, false);
|
||||
} else {
|
||||
CardInfoPane cardInfoPane = (CardInfoPane) MageFrame.getUI().getComponent(MageComponents.CARD_INFO_PANE);
|
||||
cardInfoPane.setCard(new CardView(card.getMockCard()), container);
|
||||
Point mousePosition = MageFrame.getDesktop().getMousePosition();
|
||||
int popupY = 0;
|
||||
if (mousePosition == null) { // switched to another window
|
||||
popupY = getLocationOnScreen().y;
|
||||
} else {
|
||||
popupY = mousePosition.y;
|
||||
}
|
||||
Point location = new Point(getLocationOnScreen().x - container.getWidth(), popupY);
|
||||
Component parentComponent = MageFrame.getInstance();
|
||||
location = GuiDisplayUtil.keepComponentInsideParent(location, parentComponent.getLocationOnScreen(),
|
||||
container, parentComponent);
|
||||
setPopupVisibility(location, container, true);
|
||||
}
|
||||
} catch (InterruptedException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setPopupVisibility(final Point location, final Component container, final boolean show)
|
||||
throws InterruptedException {
|
||||
final Component c = MageFrame.getUI().getComponent(MageComponents.DESKTOP_PANE);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (location != null) {
|
||||
container.setLocation(location);
|
||||
}
|
||||
container.setVisible(show);
|
||||
c.repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,6 +119,7 @@ public class ColorPane extends JEditorPane {
|
|||
|
||||
public void append(String text) {
|
||||
try {
|
||||
text = text.replaceAll("(<font color=[^>]*>([^<]*)) (\\[[0-9a-fA-F]*\\])</font>", "<a href='#$2'>$1</a> $3");
|
||||
setEditable(true);
|
||||
kit.insertHTML(doc, doc.getLength(), text, 0, 0, null);
|
||||
setEditable(false);
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.apache.log4j.Logger;
|
|||
import org.jdesktop.layout.GroupLayout;
|
||||
import org.jdesktop.layout.LayoutStyle;
|
||||
import org.jdesktop.swingx.JXPanel;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.mage.card.arcane.ManaSymbols;
|
||||
import org.mage.card.arcane.UI;
|
||||
|
||||
|
@ -434,6 +435,7 @@ public class AbilityPicker extends JXPanel implements MouseWheelListener {
|
|||
if (choice == null || choice.isEmpty()) {
|
||||
return choice;
|
||||
}
|
||||
choice = Jsoup.parse(choice).text(); // decode HTML entities and strip tags
|
||||
return choice.substring(0, 1).toUpperCase() + choice.substring(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,14 @@ import mage.util.TournamentUtil;
|
|||
*/
|
||||
public class DeckGenerator {
|
||||
|
||||
public static class DeckGeneratorException extends RuntimeException {
|
||||
|
||||
public DeckGeneratorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final int MAX_TRIES = 8196;
|
||||
private static DeckGeneratorDialog genDialog;
|
||||
private static DeckGeneratorPool genPool;
|
||||
|
@ -82,6 +90,9 @@ public class DeckGenerator {
|
|||
String format = genDialog.getSelectedFormat();
|
||||
|
||||
List<String> setsToUse = ConstructedFormats.getSetsByFormat(format);
|
||||
if (setsToUse == null) {
|
||||
throw new DeckGeneratorException("Deck sets aren't initialized; please connect to a server to update the database.");
|
||||
}
|
||||
if (setsToUse.isEmpty()) {
|
||||
// Default to using all sets
|
||||
setsToUse = ExpansionRepository.instance.getSetCodes();
|
||||
|
@ -144,7 +155,7 @@ public class DeckGenerator {
|
|||
* @return the final deck to use.
|
||||
*/
|
||||
private static Deck generateDeck(int deckSize, List<ColoredManaSymbol> allowedColors, List<String> setsToUse) {
|
||||
genPool = new DeckGeneratorPool(deckSize, allowedColors, genDialog.isSingleton());
|
||||
genPool = new DeckGeneratorPool(deckSize, allowedColors, genDialog.isSingleton(), genDialog.isColorless());
|
||||
|
||||
final String[] sets = setsToUse.toArray(new String[setsToUse.size()]);
|
||||
|
||||
|
|
|
@ -48,13 +48,13 @@ import java.util.Date;
|
|||
*/
|
||||
public class DeckGeneratorDialog {
|
||||
|
||||
private static JDialog dlg;
|
||||
private static String selectedColors;
|
||||
private static JComboBox cbSets;
|
||||
private static JComboBox cbDeckSize;
|
||||
private static JButton btnGenerate, btnCancel;
|
||||
private static JCheckBox cArtifacts, cSingleton, cNonBasicLands;
|
||||
private static SimpleDateFormat dateFormat;
|
||||
private JDialog dlg;
|
||||
private String selectedColors;
|
||||
private JComboBox<String> cbSets;
|
||||
private JComboBox<String> cbDeckSize;
|
||||
private JButton btnGenerate, btnCancel;
|
||||
private JCheckBox cArtifacts, cSingleton, cNonBasicLands, cColorless;
|
||||
private SimpleDateFormat dateFormat;
|
||||
|
||||
public DeckGeneratorDialog()
|
||||
{
|
||||
|
@ -83,7 +83,7 @@ public class DeckGeneratorDialog {
|
|||
p0.add(Box.createVerticalStrut(5));
|
||||
JPanel jPanel = new JPanel();
|
||||
JLabel text3 = new JLabel("Choose sets:");
|
||||
cbSets = new JComboBox(ConstructedFormats.getTypes());
|
||||
cbSets = new JComboBox<String>(ConstructedFormats.getTypes());
|
||||
cbSets.setSelectedIndex(0);
|
||||
cbSets.setPreferredSize(new Dimension(300, 25));
|
||||
cbSets.setMaximumSize(new Dimension(300, 25));
|
||||
|
@ -100,7 +100,7 @@ public class DeckGeneratorDialog {
|
|||
p0.add(Box.createVerticalStrut(5));
|
||||
JPanel jPanel2 = new JPanel();
|
||||
JLabel textDeckSize = new JLabel("Deck size:");
|
||||
cbDeckSize = new JComboBox(new String[]{"40","60"});
|
||||
cbDeckSize = new JComboBox<String>(new String[] { "40", "60" });
|
||||
cbDeckSize.setSelectedIndex(0);
|
||||
cbDeckSize.setPreferredSize(new Dimension(300, 25));
|
||||
cbDeckSize.setMaximumSize(new Dimension(300, 25));
|
||||
|
@ -138,8 +138,15 @@ public class DeckGeneratorDialog {
|
|||
cNonBasicLands.setSelected(Boolean.valueOf(nonBasicEnabled));
|
||||
jCheckBoxes.add(cNonBasicLands);
|
||||
|
||||
jCheckBoxes.setPreferredSize(new Dimension(300, 25));
|
||||
jCheckBoxes.setMaximumSize(new Dimension(300, 25));
|
||||
// Non-basic lands
|
||||
cColorless = new JCheckBox("Colorless mana", false);
|
||||
cColorless.setToolTipText("Allow cards with colorless mana cost.");
|
||||
String colorlessEnabled = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_COLORLESS, "false");
|
||||
cColorless.setSelected(Boolean.valueOf(colorlessEnabled));
|
||||
jCheckBoxes.add(cColorless);
|
||||
|
||||
jCheckBoxes.setPreferredSize(new Dimension(450, 25));
|
||||
jCheckBoxes.setMaximumSize(new Dimension(450, 25));
|
||||
p0.add(jCheckBoxes);
|
||||
|
||||
btnGenerate = new JButton("Ok");
|
||||
|
@ -168,7 +175,7 @@ public class DeckGeneratorDialog {
|
|||
dlg.dispose();
|
||||
}
|
||||
|
||||
public static void cleanUp() {
|
||||
public void cleanUp() {
|
||||
for (ActionListener al: btnGenerate.getActionListeners()) {
|
||||
btnGenerate.removeActionListener(al);
|
||||
}
|
||||
|
@ -187,7 +194,7 @@ public class DeckGeneratorDialog {
|
|||
tmp.createNewFile();
|
||||
deck.setName(deckName);
|
||||
Sets.saveDeck(tmp.getAbsolutePath(), deck.getDeckCardLists());
|
||||
DeckGeneratorDialog.cleanUp();
|
||||
cleanUp();
|
||||
return tmp.getAbsolutePath();
|
||||
} catch (Exception e) {
|
||||
JOptionPane.showMessageDialog(null, "Couldn't generate deck. Try again.");
|
||||
|
@ -205,6 +212,12 @@ public class DeckGeneratorDialog {
|
|||
return selected;
|
||||
}
|
||||
|
||||
public boolean isColorless() {
|
||||
boolean selected = cColorless.isSelected();
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_COLORLESS, Boolean.toString(selected));
|
||||
return selected;
|
||||
}
|
||||
|
||||
public boolean useArtifacts() {
|
||||
boolean selected = cArtifacts.isSelected();
|
||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_ARTIFACTS, Boolean.toString(selected));
|
||||
|
|
|
@ -51,6 +51,7 @@ public class DeckGeneratorPool
|
|||
private static final int NONCREATURE_COUNT_60 = 13;
|
||||
|
||||
private final List<ColoredManaSymbol> allowedColors;
|
||||
private boolean colorlessAllowed;
|
||||
private final List<DeckGeneratorCMC> poolCMCs;
|
||||
private final int creatureCount;
|
||||
private final int nonCreatureCount;
|
||||
|
@ -68,11 +69,12 @@ public class DeckGeneratorPool
|
|||
private List<Card> reserveSpells = new ArrayList<>();
|
||||
private Deck deck;
|
||||
|
||||
public DeckGeneratorPool(final int deckSize, final List<ColoredManaSymbol> allowedColors, boolean isSingleton)
|
||||
public DeckGeneratorPool(final int deckSize, final List<ColoredManaSymbol> allowedColors, boolean isSingleton, boolean colorlessAllowed)
|
||||
{
|
||||
this.deckSize = deckSize;
|
||||
this.allowedColors = allowedColors;
|
||||
this.isSingleton = isSingleton;
|
||||
this.colorlessAllowed = colorlessAllowed;
|
||||
|
||||
this.deck = new Deck();
|
||||
|
||||
|
@ -207,6 +209,9 @@ public class DeckGeneratorPool
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if (symbol.equals("C") && !colorlessAllowed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ package mage.client.deckeditor;
|
|||
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentEvent;
|
||||
|
@ -183,11 +182,11 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
|
|||
|
||||
public void changeGUISize() {
|
||||
setGUISize();
|
||||
cardGrid.changeGUISize();
|
||||
}
|
||||
|
||||
private void setGUISize() {
|
||||
mainTable.getTableHeader().setFont(GUISizeHelper.tableFont);
|
||||
mainTable.getTableHeader().setPreferredSize(new Dimension(GUISizeHelper.tableHeaderHeight, GUISizeHelper.tableHeaderHeight));
|
||||
mainTable.setFont(GUISizeHelper.tableFont);
|
||||
mainTable.setRowHeight(GUISizeHelper.getTableRowHeight());
|
||||
|
||||
|
|
|
@ -83,6 +83,8 @@
|
|||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnImport" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnGenDeck" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnAddLand" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="btnSubmit" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -110,6 +112,7 @@
|
|||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="btnImport" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnGenDeck" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnAddLand" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="btnSubmit" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
|
|
@ -60,9 +60,9 @@ import mage.client.MageFrame;
|
|||
import mage.client.cards.BigCard;
|
||||
import mage.client.cards.ICardGrid;
|
||||
import mage.client.constants.Constants.DeckEditorMode;
|
||||
import static mage.client.constants.Constants.DeckEditorMode.FREE_BUILDING;
|
||||
import static mage.client.constants.Constants.DeckEditorMode.LIMITED_BUILDING;
|
||||
import static mage.client.constants.Constants.DeckEditorMode.SIDEBOARDING;
|
||||
import mage.client.deck.generator.DeckGenerator;
|
||||
import mage.client.deck.generator.DeckGenerator.DeckGeneratorException;
|
||||
|
||||
import mage.client.dialog.AddLandDialog;
|
||||
import mage.client.plugins.impl.Plugins;
|
||||
import mage.client.util.Event;
|
||||
|
@ -171,9 +171,9 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
}
|
||||
// TODO: take from preferences
|
||||
this.cardSelector.switchToGrid();
|
||||
|
||||
this.btnExit.setVisible(false);
|
||||
this.btnImport.setVisible(false);
|
||||
this.btnGenDeck.setVisible(false);
|
||||
if (!MageFrame.getSession().isTestMode()) {
|
||||
this.btnLoad.setVisible(false);
|
||||
}
|
||||
|
@ -196,6 +196,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
//this.cardTableSelector.loadCards(this.bigCard);
|
||||
this.btnExit.setVisible(true);
|
||||
this.btnImport.setVisible(true);
|
||||
this.btnGenDeck.setVisible(true);
|
||||
if (!MageFrame.getSession().isTestMode()) {
|
||||
this.btnLoad.setVisible(true);
|
||||
}
|
||||
|
@ -505,6 +506,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
btnImport = new javax.swing.JButton();
|
||||
btnSubmit = new javax.swing.JButton();
|
||||
btnAddLand = new javax.swing.JButton();
|
||||
btnGenDeck = new javax.swing.JButton();
|
||||
txtTimeRemaining = new javax.swing.JTextField();
|
||||
|
||||
jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
|
@ -592,6 +594,15 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
btnAddLandActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
btnGenDeck.setText("Generate");
|
||||
btnGenDeck.setName("btnGenDeck");
|
||||
btnGenDeck.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
btnGenDeckActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
txtTimeRemaining.setEditable(false);
|
||||
txtTimeRemaining.setForeground(java.awt.Color.red);
|
||||
|
@ -627,6 +638,8 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
.addContainerGap()
|
||||
.addComponent(btnImport)
|
||||
.addContainerGap()
|
||||
.addComponent(btnGenDeck)
|
||||
.addContainerGap()
|
||||
.addComponent(btnAddLand)
|
||||
.addContainerGap()
|
||||
.addComponent(btnSubmit))
|
||||
|
@ -651,6 +664,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(btnImport)
|
||||
.addComponent(btnGenDeck)
|
||||
.addComponent(btnAddLand)
|
||||
.addComponent(btnSubmit))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
|
@ -802,6 +816,21 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
refreshDeck();
|
||||
}//GEN-LAST:event_btnAddLandActionPerformed
|
||||
|
||||
private void btnGenDeckActionPerformed(ActionEvent evt) {
|
||||
try {
|
||||
setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||
String path = DeckGenerator.generateDeck();
|
||||
deck = Deck.load(DeckImporterUtil.importDeck(path), true, true);
|
||||
} catch (GameException ex) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Error loading generated deck", JOptionPane.ERROR_MESSAGE);
|
||||
}catch (DeckGeneratorException ex) {
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Generator error", JOptionPane.ERROR_MESSAGE);
|
||||
} finally {
|
||||
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
refreshDeck();
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private mage.client.cards.BigCard bigCard;
|
||||
private javax.swing.JButton btnExit;
|
||||
|
@ -817,6 +846,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
private javax.swing.JTextField txtDeckName;
|
||||
private javax.swing.JButton btnSubmit;
|
||||
private javax.swing.JButton btnAddLand;
|
||||
private javax.swing.JButton btnGenDeck;
|
||||
private JComponent cardInfoPane;
|
||||
private javax.swing.JTextField txtTimeRemaining;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
|
|
@ -66,6 +66,7 @@ import static mage.client.dialog.PreferencesDialog.KEY_CONNECT_FLAG;
|
|||
import mage.client.preference.MagePreferences;
|
||||
import mage.client.util.Config;
|
||||
import mage.client.util.gui.countryBox.CountryItemEditor;
|
||||
import mage.client.util.sets.ConstructedFormats;
|
||||
import mage.remote.Connection;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
@ -442,6 +443,7 @@ public class ConnectDialog extends MageDialog {
|
|||
private void connected() {
|
||||
this.saveSettings();
|
||||
this.hideDialog();
|
||||
ConstructedFormats.ensureLists();
|
||||
}
|
||||
|
||||
private void keyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_keyTyped
|
||||
|
|
|
@ -235,6 +235,7 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
|||
public static final String KEY_NEW_DECK_GENERATOR_SINGLETON = "newDeckGeneratorSingleton";
|
||||
public static final String KEY_NEW_DECK_GENERATOR_ARTIFACTS = "newDeckGeneratorArtifacts";
|
||||
public static final String KEY_NEW_DECK_GENERATOR_NON_BASIC_LANDS = "newDeckGeneratorNonBasicLands";
|
||||
public static final String KEY_NEW_DECK_GENERATOR_COLORLESS = "newDeckGeneratorColorless";
|
||||
|
||||
// used to save and restore the settings for the cardArea (draft, sideboarding, deck builder)
|
||||
public static final String KEY_DRAFT_VIEW = "draftView";
|
||||
|
|
|
@ -104,7 +104,6 @@ public class TableWaitingDialog extends MageDialog {
|
|||
|
||||
private void setGUISize() {
|
||||
tableSeats.getTableHeader().setFont(GUISizeHelper.tableFont);
|
||||
tableSeats.getTableHeader().setPreferredSize(new Dimension(GUISizeHelper.tableHeaderHeight, GUISizeHelper.tableHeaderHeight));
|
||||
tableSeats.setFont(GUISizeHelper.tableFont);
|
||||
tableSeats.setRowHeight(GUISizeHelper.getTableRowHeight());
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane {
|
|||
}
|
||||
|
||||
public void sortLayout() {
|
||||
if (battlefield == null) {
|
||||
if (battlefield == null || this.getWidth() < 1) { // Can't do layout when panel is not sized yet
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -608,9 +608,9 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
}
|
||||
}
|
||||
PlayerView player = game.getPlayers().get(playerSeat);
|
||||
PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId, game.getPriorityTime(), this,
|
||||
new PlayAreaPanelOptions(game.isPlayer(), true, game.isRollbackTurnsAllowed()));
|
||||
players.put(player.getPlayerId(), sessionPlayer);
|
||||
PlayAreaPanel playAreaPanel = new PlayAreaPanel(player, bigCard, gameId, game.getPriorityTime(), this,
|
||||
new PlayAreaPanelOptions(game.isPlayer(), game.isPlayer(), game.isRollbackTurnsAllowed()));
|
||||
players.put(player.getPlayerId(), playAreaPanel);
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.weightx = 0.5;
|
||||
|
@ -620,8 +620,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
}
|
||||
c.gridx = col;
|
||||
c.gridy = row;
|
||||
this.pnlBattlefield.add(sessionPlayer, c);
|
||||
sessionPlayer.setVisible(true);
|
||||
this.pnlBattlefield.add(playAreaPanel, c);
|
||||
playAreaPanel.setVisible(true);
|
||||
if (oddNumber) {
|
||||
col++;
|
||||
}
|
||||
|
|
|
@ -287,7 +287,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
|||
avatar.setText(this.player.getName());
|
||||
if (!player.getUserData().getFlagName().equals(flagName)) {
|
||||
flagName = player.getUserData().getFlagName();
|
||||
this.avatar.setTopTextImage(CountryUtil.getCountryFlagIcon(flagName).getImage());
|
||||
this.avatar.setTopTextImage(CountryUtil.getCountryFlagIconSize(flagName, 11).getImage());
|
||||
}
|
||||
// TODO: Add the wins to the tooltiptext of the avatar
|
||||
String countryname = CountryUtil.getCountryName(flagName);
|
||||
|
|
|
@ -189,27 +189,31 @@ public class MageActionCallback implements ActionCallback {
|
|||
Point location = new Point((int) data.locationOnScreen.getX() + data.popupOffsetX - 40, (int) data.locationOnScreen.getY() + data.popupOffsetY - 40);
|
||||
location = GuiDisplayUtil.keepComponentInsideParent(location, parentPoint, popup2, parentComponent);
|
||||
location.translate(-parentPoint.x, -parentPoint.y);
|
||||
popupContainer.setLocation(location);
|
||||
|
||||
ThreadUtils.sleep(200);
|
||||
|
||||
final Component c = MageFrame.getUI().getComponent(MageComponents.DESKTOP_PANE);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!popupTextWindowOpen || !enlargedWindowState.equals(EnlargedWindowState.CLOSED)) {
|
||||
return;
|
||||
}
|
||||
popupContainer.setVisible(true);
|
||||
c.repaint();
|
||||
}
|
||||
}
|
||||
);
|
||||
showPopup(popupContainer, location);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.warn(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void showPopup(final Component popupContainer, final Point location) throws InterruptedException {
|
||||
final Component c = MageFrame.getUI().getComponent(MageComponents.DESKTOP_PANE);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!popupTextWindowOpen || !enlargedWindowState.equals(EnlargedWindowState.CLOSED)) {
|
||||
return;
|
||||
}
|
||||
popupContainer.setLocation(location);
|
||||
popupContainer.setVisible(true);
|
||||
c.repaint();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -123,7 +123,6 @@ public class PlayersChatPanel extends javax.swing.JPanel {
|
|||
|
||||
private void setGUISize() {
|
||||
jTablePlayers.getTableHeader().setFont(GUISizeHelper.tableFont);
|
||||
jTablePlayers.getTableHeader().setPreferredSize(new Dimension((int) jTablePlayers.getTableHeader().getPreferredSize().getWidth(), GUISizeHelper.tableHeaderHeight));
|
||||
jTablePlayers.setFont(GUISizeHelper.tableFont);
|
||||
jTablePlayers.setRowHeight(GUISizeHelper.getTableRowHeight());
|
||||
jScrollPanePlayers.getVerticalScrollBar().setPreferredSize(new Dimension(GUISizeHelper.scrollBarSize, 0));
|
||||
|
|
|
@ -294,12 +294,10 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
|
||||
private void setGUISize() {
|
||||
tableTables.getTableHeader().setFont(GUISizeHelper.tableFont);
|
||||
tableTables.getTableHeader().setPreferredSize(new Dimension(GUISizeHelper.tableHeaderHeight, GUISizeHelper.tableHeaderHeight));
|
||||
tableTables.setFont(GUISizeHelper.tableFont);
|
||||
tableTables.setRowHeight(GUISizeHelper.getTableRowHeight());
|
||||
|
||||
tableCompleted.getTableHeader().setFont(GUISizeHelper.tableFont);
|
||||
tableCompleted.getTableHeader().setPreferredSize(new Dimension(GUISizeHelper.tableHeaderHeight, GUISizeHelper.tableHeaderHeight));
|
||||
tableCompleted.setFont(GUISizeHelper.tableFont);
|
||||
tableCompleted.setRowHeight(GUISizeHelper.getTableRowHeight());
|
||||
|
||||
|
|
|
@ -154,12 +154,10 @@ public class TournamentPanel extends javax.swing.JPanel {
|
|||
|
||||
private void setGUISize() {
|
||||
tablePlayers.getTableHeader().setFont(GUISizeHelper.tableFont);
|
||||
tablePlayers.getTableHeader().setPreferredSize(new Dimension(GUISizeHelper.tableHeaderHeight, GUISizeHelper.tableHeaderHeight));
|
||||
tablePlayers.setFont(GUISizeHelper.tableFont);
|
||||
tablePlayers.setRowHeight(GUISizeHelper.getTableRowHeight());
|
||||
|
||||
tableMatches.getTableHeader().setFont(GUISizeHelper.tableFont);
|
||||
tableMatches.getTableHeader().setPreferredSize(new Dimension(GUISizeHelper.tableHeaderHeight, GUISizeHelper.tableHeaderHeight));
|
||||
tableMatches.setFont(GUISizeHelper.tableFont);
|
||||
tableMatches.setRowHeight(GUISizeHelper.getTableRowHeight());
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ public class ButtonColumn extends AbstractCellEditor implements TableCellRendere
|
|||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (table.getRowCount() >= table.getEditingRow()) {
|
||||
if (table.getRowCount() > 0 && table.getRowCount() >= table.getEditingRow()) {
|
||||
int row = table.convertRowIndexToModel(table.getEditingRow());
|
||||
fireEditingStopped();
|
||||
ActionEvent event = new ActionEvent(table, ActionEvent.ACTION_PERFORMED, "" + row);
|
||||
|
|
|
@ -24,11 +24,9 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.client.util;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -42,6 +40,7 @@ import org.apache.log4j.Logger;
|
|||
*/
|
||||
public class Config {
|
||||
|
||||
// TODO: Remove this class completely
|
||||
private static final Logger logger = Logger.getLogger(Config.class);
|
||||
|
||||
public static final String remoteServer;
|
||||
|
@ -65,33 +64,33 @@ public class Config {
|
|||
} catch (IOException ex) {
|
||||
logger.fatal("Config error ", ex);
|
||||
}
|
||||
serverName = p.getProperty("server-name");
|
||||
port = Integer.parseInt(p.getProperty("port"));
|
||||
remoteServer = p.getProperty("remote-server");
|
||||
cardScalingFactor = Double.valueOf(p.getProperty("card-scaling-factor"));
|
||||
cardScalingFactorEnlarged = Double.valueOf(p.getProperty("card-scaling-factor-enlarged"));
|
||||
handScalingFactor = Double.valueOf(p.getProperty("hand-scaling-factor"));
|
||||
defaultGameType = p.getProperty("default-game-type", "Human");
|
||||
defaultDeckPath = p.getProperty("default-deck-path");
|
||||
defaultOtherPlayerIndex = p.getProperty("default-other-player-index");
|
||||
defaultComputerName = p.getProperty("default-computer-name");
|
||||
|
||||
dimensions = new CardDimensions(cardScalingFactor);
|
||||
dimensionsEnlarged = new CardDimensions(cardScalingFactorEnlarged);
|
||||
// activate instead this part, to run the UI editor for some panels without error
|
||||
// serverName = "localhost";
|
||||
// port = 17171;
|
||||
// remoteServer = "mage-server";
|
||||
// cardScalingFactor = Double.valueOf(0.4);
|
||||
// cardScalingFactorEnlarged = Double.valueOf(0.5);
|
||||
// handScalingFactor = Double.valueOf(1.3);
|
||||
// serverName = p.getProperty("server-name");
|
||||
// port = Integer.parseInt(p.getProperty("port"));
|
||||
// remoteServer = p.getProperty("remote-server");
|
||||
// cardScalingFactor = Double.valueOf(p.getProperty("card-scaling-factor"));
|
||||
// cardScalingFactorEnlarged = Double.valueOf(p.getProperty("card-scaling-factor-enlarged"));
|
||||
// handScalingFactor = Double.valueOf(p.getProperty("hand-scaling-factor"));
|
||||
// defaultGameType = p.getProperty("default-game-type", "Human");
|
||||
// defaultDeckPath = "";
|
||||
// defaultOtherPlayerIndex = "1";
|
||||
// defaultComputerName = "Computer";
|
||||
// defaultDeckPath = p.getProperty("default-deck-path");
|
||||
// defaultOtherPlayerIndex = p.getProperty("default-other-player-index");
|
||||
// defaultComputerName = p.getProperty("default-computer-name");
|
||||
//
|
||||
// dimensions = new CardDimensions(cardScalingFactor);
|
||||
// dimensionsEnlarged = new CardDimensions(cardScalingFactorEnlarged);
|
||||
// activate instead this part, to run the UI editor for some panels without error
|
||||
serverName = "localhost";
|
||||
port = 17171;
|
||||
remoteServer = "mage-server";
|
||||
cardScalingFactor = 0.4;
|
||||
cardScalingFactorEnlarged = 0.5;
|
||||
handScalingFactor = 1.3;
|
||||
defaultGameType = p.getProperty("default-game-type", "Human");
|
||||
defaultDeckPath = "";
|
||||
defaultOtherPlayerIndex = "1";
|
||||
defaultComputerName = "Computer";
|
||||
|
||||
dimensions = new CardDimensions(cardScalingFactor);
|
||||
dimensionsEnlarged = new CardDimensions(cardScalingFactorEnlarged);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@ public class EDTExceptionHandler implements Thread.UncaughtExceptionHandler {
|
|||
|
||||
public void handle(Throwable throwable) {
|
||||
try {
|
||||
logger.fatal(null, throwable);
|
||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), throwable, "MAGE Client UI error", JOptionPane.ERROR_MESSAGE);
|
||||
logger.fatal("MAGE Client UI error", throwable);
|
||||
// JOptionPane.showMessageDialog(MageFrame.getDesktop(), throwable, "MAGE Client UI error", JOptionPane.ERROR_MESSAGE);
|
||||
} catch (Throwable t) {}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ public class CountryUtil {
|
|||
public static ImageIcon getCountryFlagIcon(String countryCode) {
|
||||
ImageIcon flagIcon = FLAG_ICON_CACHE.get(countryCode);
|
||||
if (flagIcon == null) {
|
||||
// URL url = CountryUtil.class.getResource("/flags/" + countryCode + (countryCode.endsWith(".png") ? "" : ".png"));
|
||||
Image flagImage = ImageHelper.getImageFromResources("/flags/" + countryCode + (countryCode.endsWith(".png") ? "" : ".png"));
|
||||
if (flagImage != null) {
|
||||
if (GUISizeHelper.flagHeight > 11) {
|
||||
|
@ -48,6 +47,22 @@ public class CountryUtil {
|
|||
return flagIcon;
|
||||
}
|
||||
|
||||
public static ImageIcon getCountryFlagIconSize(String countryCode, int height) {
|
||||
ImageIcon flagIcon = null;
|
||||
Image flagImage = ImageHelper.getImageFromResources("/flags/" + countryCode + (countryCode.endsWith(".png") ? "" : ".png"));
|
||||
if (flagImage != null) {
|
||||
|
||||
if (height > 11) {
|
||||
int width = Math.round(height * flagImage.getWidth(null) / flagImage.getHeight(null));
|
||||
BufferedImage resized = ImageHelper.scale((BufferedImage) flagImage, BufferedImage.TYPE_4BYTE_ABGR, width, height);
|
||||
flagIcon = new ImageIcon(resized);
|
||||
} else {
|
||||
flagIcon = new ImageIcon(flagImage);
|
||||
}
|
||||
}
|
||||
return flagIcon;
|
||||
}
|
||||
|
||||
public static void changeGUISize() {
|
||||
FLAG_ICON_CACHE.clear();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,12 @@ public class ConstructedFormats {
|
|||
|
||||
}
|
||||
|
||||
public static void ensureLists() {
|
||||
if (getSetsByFormat(ConstructedFormats.STANDARD) == null) {
|
||||
buildLists();
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildLists() {
|
||||
GregorianCalendar cutoff;
|
||||
// month is zero based so January = 0
|
||||
|
@ -60,6 +66,7 @@ public class ConstructedFormats {
|
|||
cutoff = new GregorianCalendar(calendar.get(Calendar.YEAR) - 2, Calendar.SEPTEMBER, 1);
|
||||
}
|
||||
final Map<String, ExpansionInfo> expansionInfo = new HashMap<>();
|
||||
formats.clear(); // prevent NPE on sorting if this is not the first try
|
||||
for (ExpansionInfo set : ExpansionRepository.instance.getAll()) {
|
||||
expansionInfo.put(set.getName(), set);
|
||||
formats.add(set.getName());
|
||||
|
@ -207,10 +214,11 @@ public class ConstructedFormats {
|
|||
}
|
||||
|
||||
});
|
||||
|
||||
formats.add(0, MODERN);
|
||||
formats.add(0, EXTENDED);
|
||||
formats.add(0, STANDARD);
|
||||
if (!formats.isEmpty()) {
|
||||
formats.add(0, MODERN);
|
||||
formats.add(0, EXTENDED);
|
||||
formats.add(0, STANDARD);
|
||||
}
|
||||
formats.add(0, ALL);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,16 @@ import java.awt.Image;
|
|||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -36,6 +46,7 @@ public class ManaSymbols {
|
|||
"WP", "UP", "BP", "RP", "GP", "X", "C"};
|
||||
|
||||
public static void loadImages() {
|
||||
renameSymbols(getSymbolsPath() + File.separator + "symbols");
|
||||
smallSymbolsFound = loadSymbolsImages(15);
|
||||
mediumSymbolsFound = loadSymbolsImages(25);
|
||||
|
||||
|
@ -120,14 +131,14 @@ public class ManaSymbols {
|
|||
private static boolean loadSymbolsImages(int size) {
|
||||
boolean fileErrors = false;
|
||||
HashMap<String, BufferedImage> sizedSymbols = new HashMap<>();
|
||||
String resourcePath = Constants.RESOURCE_PATH_MANA_SMALL;
|
||||
if (size > 25) {
|
||||
resourcePath = Constants.RESOURCE_PATH_MANA_LARGE;
|
||||
} else if (size > 15) {
|
||||
resourcePath = Constants.RESOURCE_PATH_MANA_MEDIUM;
|
||||
}
|
||||
for (String symbol : symbols) {
|
||||
String resourcePath = Constants.RESOURCE_PATH_MANA_SMALL;
|
||||
if (size > 25) {
|
||||
resourcePath = Constants.RESOURCE_PATH_MANA_LARGE;
|
||||
} else if (size > 15) {
|
||||
resourcePath = Constants.RESOURCE_PATH_MANA_MEDIUM;
|
||||
}
|
||||
File file = new File(getSymbolsPath() + resourcePath + "/" + symbol + ".jpg");
|
||||
File file = new File(getSymbolsPath() + resourcePath + "/" + symbol + ".gif");
|
||||
try {
|
||||
|
||||
if (size == 15 || size == 25) {
|
||||
|
@ -148,6 +159,24 @@ public class ManaSymbols {
|
|||
return !fileErrors;
|
||||
}
|
||||
|
||||
private static void renameSymbols(String path) {
|
||||
final PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**/*.jpg");
|
||||
try {
|
||||
Files.walkFileTree(Paths.get(path), new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
if (matcher.matches(file)) {
|
||||
Path gifPath = file.resolveSibling(file.getFileName().toString().replaceAll("\\.jpg$", ".gif"));
|
||||
Files.move(file, gifPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Couldn't rename mana symbols!");
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSymbolsPath() {
|
||||
return getSymbolsPath(false);
|
||||
}
|
||||
|
@ -247,9 +276,9 @@ public class ManaSymbols {
|
|||
symbolFilesFound = mediumSymbolsFound;
|
||||
}
|
||||
if (symbolFilesFound) {
|
||||
replaced = REPLACE_SYMBOLS_PATTERN.matcher(value).replaceAll("<img src='file:" + getSymbolsPath(true)
|
||||
+ "/symbols/" + resourcePath + "/$1$2.jpg' alt='$1$2' width="
|
||||
+ symbolSize + " height=" + symbolSize + ">");
|
||||
replaced = REPLACE_SYMBOLS_PATTERN.matcher(value).replaceAll(
|
||||
"<img src='file:" + getSymbolsPath(true) + "/symbols/" + resourcePath + "/$1$2.gif' alt='$1$2' width=" + symbolSize
|
||||
+ " height=" + symbolSize + ">");
|
||||
}
|
||||
replaced = replaced.replace("|source|", "{source}");
|
||||
replaced = replaced.replace("|this|", "{this}");
|
||||
|
|
|
@ -31,6 +31,7 @@ import net.xeoh.plugins.base.annotations.meta.Author;
|
|||
import org.apache.log4j.Logger;
|
||||
import org.mage.card.arcane.Animation;
|
||||
import org.mage.card.arcane.CardPanel;
|
||||
import org.mage.card.arcane.ManaSymbols;
|
||||
import org.mage.plugins.card.dl.DownloadGui;
|
||||
import org.mage.plugins.card.dl.DownloadJob;
|
||||
import org.mage.plugins.card.dl.Downloader;
|
||||
|
@ -540,6 +541,7 @@ public class CardPluginImpl implements CardPlugin {
|
|||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
g.getDownloader().dispose();
|
||||
ManaSymbols.loadImages();
|
||||
}
|
||||
});
|
||||
d.setLayout(new BorderLayout());
|
||||
|
|
|
@ -71,7 +71,7 @@ public class GathererSymbols implements Iterable<DownloadJob> {
|
|||
return computeNext();
|
||||
}
|
||||
String symbol = sym.replaceAll("/", "");
|
||||
File dst = new File(dir, symbol + ".jpg");
|
||||
File dst = new File(dir, symbol + ".gif");
|
||||
|
||||
switch (symbol) {
|
||||
case "T":
|
||||
|
|
|
@ -38,6 +38,9 @@ import java.net.URL;
|
|||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.prefs.Preferences;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
|
@ -246,11 +249,11 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
languageAliases.put("fr", "French");
|
||||
languageAliases.put("cn", "Chinese Simplified");
|
||||
languageAliases.put("de", "German");
|
||||
|
||||
}
|
||||
|
||||
private Map<String, String> getSetLinks(String cardSet) {
|
||||
Map<String, String> setLinks = new HashMap<>();
|
||||
ConcurrentHashMap<String, String> setLinks = new ConcurrentHashMap<>();
|
||||
ExecutorService executor = Executors.newFixedThreadPool(10);
|
||||
try {
|
||||
String setNames = setsAliases.get(cardSet);
|
||||
String preferedLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en");
|
||||
|
@ -262,12 +265,10 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
while (page < 999) {
|
||||
String searchUrl = "http://gatherer.wizards.com/Pages/Search/Default.aspx?page=" + page +"&output=spoiler&method=visual&action=advanced&set=+[%22" + URLSetName + "%22]";
|
||||
Document doc = getDocument(searchUrl);
|
||||
|
||||
Elements cardsImages = doc.select("img[src^=../../Handlers/]");
|
||||
if (cardsImages.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cardsImages.size(); i++) {
|
||||
Integer multiverseId = Integer.parseInt(cardsImages.get(i).attr("src").replaceAll("[^\\d]", ""));
|
||||
if (i == 0) {
|
||||
|
@ -278,12 +279,8 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
}
|
||||
String cardName = normalizeName(cardsImages.get(i).attr("alt"));
|
||||
if (cardName != null && !cardName.isEmpty()) {
|
||||
if (cardName.equals("Forest") || cardName.equals("Swamp") || cardName.equals("Mountain") || cardName.equals("Island") || cardName.equals("Plains")) {
|
||||
setLinks.putAll(getLandVariations(multiverseId, cardName));
|
||||
} else {
|
||||
Integer preferedMultiverseId = getLocalizedMultiverseId(preferedLanguage, multiverseId);
|
||||
setLinks.put(cardName.toLowerCase(), generateLink(preferedMultiverseId));
|
||||
}
|
||||
Runnable task = new GetImageLinkTask(multiverseId, cardName, preferedLanguage, setLinks);
|
||||
executor.execute(task);
|
||||
}
|
||||
}
|
||||
page++;
|
||||
|
@ -292,6 +289,16 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
} catch (IOException ex) {
|
||||
System.out.println("Exception when parsing the wizards page: " + ex.getMessage());
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
|
||||
while (!executor.isTerminated()) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
|
||||
return setLinks;
|
||||
}
|
||||
|
||||
|
@ -440,4 +447,35 @@ public class WizardCardsImageSource implements CardImageSource {
|
|||
public Float getAverageSize() {
|
||||
return 60.0f;
|
||||
}
|
||||
|
||||
private final class GetImageLinkTask implements Runnable {
|
||||
|
||||
private final Integer multiverseId;
|
||||
private final String cardName;
|
||||
private final String preferedLanguage;
|
||||
private final ConcurrentHashMap setLinks;
|
||||
|
||||
public GetImageLinkTask(Integer multiverseId, String cardName, String preferedLanguage, ConcurrentHashMap setLinks) {
|
||||
this.multiverseId = multiverseId;
|
||||
this.cardName = cardName;
|
||||
this.preferedLanguage = preferedLanguage;
|
||||
this.setLinks = setLinks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (cardName.equals("Forest") || cardName.equals("Swamp") || cardName.equals("Mountain") || cardName.equals("Island") || cardName.equals("Plains")) {
|
||||
setLinks.putAll(getLandVariations(multiverseId, cardName));
|
||||
} else {
|
||||
Integer preferedMultiverseId = getLocalizedMultiverseId(preferedLanguage, multiverseId);
|
||||
setLinks.put(cardName.toLowerCase(), generateLink(preferedMultiverseId));
|
||||
}
|
||||
} catch (IOException | NumberFormatException ex) {
|
||||
System.out.println("Exception when parsing the wizards page: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -312,14 +312,12 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab
|
|||
url.setFlippedSide(true);
|
||||
allCardsUrls.add(url);
|
||||
}
|
||||
} else {
|
||||
if (card.getCardNumber() < 1) {
|
||||
System.err.println("There was a critical error!");
|
||||
logger.error("Card has no collector ID and won't be sent to client: " + card);
|
||||
} else if (card.getSetCode().isEmpty()) {
|
||||
System.err.println("There was a critical error!");
|
||||
logger.error("Card has no set name and won't be sent to client:" + card);
|
||||
}
|
||||
} else if (card.getCardNumber() < 1) {
|
||||
System.err.println("There was a critical error!");
|
||||
logger.error("Card has no collector ID and won't be sent to client: " + card);
|
||||
} else if (card.getSetCode().isEmpty()) {
|
||||
System.err.println("There was a critical error!");
|
||||
logger.error("Card has no set name and won't be sent to client:" + card);
|
||||
}
|
||||
}
|
||||
allCardsUrls.addAll(getTokenCardUrls());
|
||||
|
|
|
@ -59,33 +59,28 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane {
|
|||
}
|
||||
currentCard = card;
|
||||
|
||||
ThreadUtils.threadPool.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
try {
|
||||
if (!card.equals(currentCard)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!card.equals(currentCard)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!card.equals(currentCard)) {
|
||||
return;
|
||||
}
|
||||
TextLines textLines = GuiDisplayUtil.getTextLinesfromCardView(card);
|
||||
StringBuilder buffer = GuiDisplayUtil.getRulefromCardView(card, textLines);
|
||||
resizeTooltipIfNeeded(container, textLines.basicTextLength, textLines.lines.size());
|
||||
setText(buffer.toString());
|
||||
setCaretPosition(0);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
TextLines textLines = GuiDisplayUtil.getTextLinesfromCardView(card);
|
||||
StringBuilder buffer = GuiDisplayUtil.getRulefromCardView(card, textLines);
|
||||
resizeTooltipIfNeeded(container, textLines.basicTextLength, textLines.lines.size());
|
||||
setText(buffer.toString());
|
||||
setCaretPosition(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void resizeTooltipIfNeeded(Component container, int ruleLength, int rules) {
|
||||
|
|
|
@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
|
|||
public final static int MAGE_VERSION_MAJOR = 1;
|
||||
public final static int MAGE_VERSION_MINOR = 4;
|
||||
public final static int MAGE_VERSION_PATCH = 9;
|
||||
public final static String MAGE_VERSION_MINOR_PATCH = "v0";
|
||||
public final static String MAGE_VERSION_MINOR_PATCH = "v1";
|
||||
public final static String MAGE_VERSION_INFO = "";
|
||||
|
||||
private final int major;
|
||||
|
|
|
@ -52,7 +52,9 @@ public class RateCard {
|
|||
*/
|
||||
public static int rateCard(Card card, List<ColoredManaSymbol> allowedColors) {
|
||||
if (allowedColors == null && rated.containsKey(card.getName())) {
|
||||
return rated.get(card.getName());
|
||||
int rate = rated.get(card.getName());
|
||||
// log.info(card.getName() + " rate: " + rate);
|
||||
return rate;
|
||||
}
|
||||
int type;
|
||||
if (card.getCardType().contains(CardType.PLANESWALKER)) {
|
||||
|
@ -136,7 +138,7 @@ public class RateCard {
|
|||
*/
|
||||
private synchronized static void readRatings() {
|
||||
if (ratings == null) {
|
||||
ratings = new HashMap<String, Integer>();
|
||||
ratings = new HashMap<>();
|
||||
readFromFile("/m13.csv");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,45 @@
|
|||
#default levels
|
||||
log4j.rootLogger=debug, console, logfile
|
||||
#log4j.rootLogger=info, console, logfile
|
||||
log4j.rootLogger=info, RollingAppender
|
||||
log4j.logger.com.j256.ormlite=warn
|
||||
log4j.logger.mage.player.ai=warn
|
||||
#log4j.logger.mage.player.ai.ComputerPlayer6=debug
|
||||
log4j.logger.mage.game=debug
|
||||
log4j.logger.mage.game.GameImpl=debug
|
||||
log4j.logger.mage.players.PlayerImpl=debug
|
||||
log4j.logger.mage.server=debug
|
||||
#log4j.logger.mage.server.UserManager=debug
|
||||
#log4j.logger.mage.server.User=debug
|
||||
#log4j.logger.mage.server.ChatSession=debug
|
||||
#log4j.logger.mage.server.ChatManager=debug
|
||||
#log4j.logger.mage.server.TableController=debug
|
||||
#log4j.logger.mage.server.TableManager=debug
|
||||
#log4j.logger.mage.server.tournament.TournamentManager=debug
|
||||
#log4j.logger.mage.server.game.GameSession=debug
|
||||
log4j.logger.mage.abilities.AbilityImpl=debug
|
||||
log4j.logger.mage.cards.decks=debug
|
||||
log4j.logger.mage.abilities.effects.common.continious.CommanderManaReplacementEffect=debug
|
||||
|
||||
#console log
|
||||
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.console.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.console.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss,SSS} %-90m =>[%t] %C{1}.%M%n
|
||||
log4j.appender.console.Threshold=info
|
||||
#log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||
#log4j.appender.console.layout=org.apache.log4j.PatternLayout
|
||||
#log4j.appender.console.layout.ConversionPattern=%-5p [%d{yyyy-MM-dd HH:mm [ss:SSS]}] %C{1}[%t]: %m%
|
||||
#log4j.appender.console.Threshold=info
|
||||
|
||||
#file log
|
||||
log4j.appender.logfile=org.apache.log4j.FileAppender
|
||||
log4j.appender.logfile.File=mageserver.log
|
||||
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.logfile.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss,SSS} %-90m =>[%t] %C{1}.%M%n
|
||||
#log4j.appender.logfile=org.apache.log4j.FileAppender
|
||||
#log4j.appender.logfile.File=mageserver.log
|
||||
#log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
|
||||
#log4j.appender.logfile.layout.ConversionPattern=%-5p [%d{yyyy-MM-dd HH:mm [ss:SSS]}] %C{1}[%t]: %m%n
|
||||
|
||||
log4j.appender.RollingAppender=org.apache.log4j.DailyRollingFileAppender
|
||||
log4j.appender.RollingAppender.File=mageserver.log
|
||||
log4j.appender.RollingAppender.DatePattern='.'yyyy-MM-dd
|
||||
log4j.appender.RollingAppender.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.RollingAppender.layout.ConversionPattern=[%p] %d %c %M - %m%n
|
||||
log4j.appender.RollingAppender.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss,SSS} %-90m =>[%t] %C{1}.%M%n
|
||||
#diagnostic log for game core classes
|
||||
#log4j.category.mage.server.game = INFO, diagfile
|
||||
#log4j.additivity.mage.server.game = false
|
||||
#log4j.appender.diagfile=org.apache.log4j.FileAppender
|
||||
#log4j.appender.diagfile.File=magediag.log
|
||||
#log4j.appender.diagfile.layout=org.apache.log4j.PatternLayout
|
||||
#log4j.appender.diagfile.layout.ConversionPattern=%-5p [%d{yyyy-MM-dd HH:mm [ss:SSS]}] %C{1}[%t]: %m%n
|
|
@ -4,6 +4,7 @@
|
|||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1
|
||||
http://maven.apache.org/xsd/assembly-1.1.1.xsd">
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<id>mage-server</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
|
|
|
@ -97,11 +97,7 @@ class AliFromCairoReplacementEffect extends ReplacementEffectImpl {
|
|||
&& (controller.getLife() > 0) &&(controller.getLife() - event.getAmount()) < 1
|
||||
&& event.getPlayerId().equals(controller.getId())
|
||||
) {
|
||||
return true;
|
||||
//unsure how to make this comply with
|
||||
// 10/1/2008: The ability doesn't change how much damage is dealt;
|
||||
// it just changes how much life that damage makes you lose.
|
||||
// An effect such as Spirit Link will see the full amount of damage being dealt.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -110,10 +106,17 @@ class AliFromCairoReplacementEffect extends ReplacementEffectImpl {
|
|||
@Override
|
||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
||||
// 10/1/2008: The ability doesn't change how much damage is dealt;
|
||||
// it just changes how much life that damage makes you lose.
|
||||
// An effect such as Spirit Link will see the full amount of damage being dealt.
|
||||
game.fireEvent(event);
|
||||
|
||||
if (controller != null) {
|
||||
event.setAmount(controller.getLife() - 1);
|
||||
controller.setLife(1, game);
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ class SecondSpellPredicate implements Predicate<Spell> {
|
|||
|
||||
@Override
|
||||
public boolean apply(Spell input, Game game) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
|
||||
if (watcher.getSpellOrder(new MageObjectReference(input.getId(), game), game) == 2) {
|
||||
return true;
|
||||
|
|
125
Mage.Sets/src/mage/sets/blessedvscursed/EerieInterlude.java
Normal file
125
Mage.Sets/src/mage/sets/blessedvscursed/EerieInterlude.java
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.blessedvscursed;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.Cards;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class EerieInterlude extends CardImpl {
|
||||
|
||||
public EerieInterlude(UUID ownerId) {
|
||||
super(ownerId, 8, "Eerie Interlude", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{W}");
|
||||
this.expansionSetCode = "DDQ";
|
||||
|
||||
// Exile any number of target creatures you control. Return those cards to the battlefield under their owner's control at the beginning of the next end step.
|
||||
this.getSpellAbility().addEffect(new EerieInterludeEffect());
|
||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, new FilterControlledCreaturePermanent(), false));
|
||||
|
||||
}
|
||||
|
||||
public EerieInterlude(final EerieInterlude card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EerieInterlude copy() {
|
||||
return new EerieInterlude(this);
|
||||
}
|
||||
}
|
||||
|
||||
class EerieInterludeEffect extends OneShotEffect {
|
||||
|
||||
public EerieInterludeEffect() {
|
||||
super(Outcome.Neutral);
|
||||
staticText = "Exile any number of target creatures you control. Return those cards to the battlefield under their owner's control at the beginning of the next end step";
|
||||
}
|
||||
|
||||
public EerieInterludeEffect(final EerieInterludeEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObject(game);
|
||||
if (sourceObject != null && controller != null) {
|
||||
Set<Card> toExile = new HashSet<>();
|
||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
||||
Permanent targetCreature = game.getPermanent(targetId);
|
||||
if (targetCreature != null) {
|
||||
toExile.add(targetCreature);
|
||||
}
|
||||
}
|
||||
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
|
||||
controller.moveCardsToExile(toExile, source, game, true, exileId, sourceObject.getIdName());
|
||||
|
||||
Cards cardsToReturn = new CardsImpl();
|
||||
for (Card exiled : toExile) {
|
||||
if (((Permanent) exiled).getZoneChangeCounter(game) == game.getState().getZoneChangeCounter(exiled.getId()) - 1) {
|
||||
cardsToReturn.add(exiled);
|
||||
}
|
||||
}
|
||||
Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect();
|
||||
effect.setTargetPointer(new FixedTargets(cardsToReturn, game));
|
||||
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect);
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EerieInterludeEffect copy() {
|
||||
return new EerieInterludeEffect(this);
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ import mage.MageInt;
|
|||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
|
@ -74,7 +74,7 @@ public class MyojinOfCleansingFire extends CardImpl {
|
|||
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
|
||||
|
||||
// Myojin of Cleansing Fire enters the battlefield with a divinity counter on it if you cast it from your hand.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
// Myojin of Cleansing Fire is indestructible as long as it has a divinity counter on it.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
|
||||
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));
|
||||
|
|
|
@ -35,7 +35,7 @@ import mage.MageInt;
|
|||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
|
@ -70,7 +70,7 @@ public class MyojinOfInfiniteRage extends CardImpl {
|
|||
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
|
||||
|
||||
// Myojin of Infinite Rage enters the battlefield with a divinity counter on it if you cast it from your hand.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
// Myojin of Infinite Rage is indestructible as long as it has a divinity counter on it.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
|
||||
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));
|
||||
|
|
|
@ -35,7 +35,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
|
@ -75,7 +75,7 @@ public class MyojinOfLifesWeb extends CardImpl {
|
|||
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
|
||||
|
||||
// Myojin of Life's Web enters the battlefield with a divinity counter on it if you cast it from your hand.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
// Myojin of Life's Web is indestructible as long as it has a divinity counter on it.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
|
||||
|
|
|
@ -35,7 +35,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
|
@ -68,7 +68,7 @@ public class MyojinOfNightsReach extends CardImpl {
|
|||
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
|
||||
|
||||
// Myojin of Night's Reach enters the battlefield with a divinity counter on it if you cast it from your hand.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
// Myojin of Night's Reach is indestructible as long as it has a divinity counter on it.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
|
||||
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));
|
||||
|
|
|
@ -35,7 +35,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
|
@ -73,7 +73,7 @@ public class MyojinOfSeeingWinds extends CardImpl {
|
|||
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
|
||||
|
||||
// Myojin of Seeing Winds enters the battlefield with a divinity counter on it if you cast it from your hand.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
|
||||
// Myojin of Seeing Winds is indestructible as long as it has a divinity counter on it.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
|
||||
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));
|
||||
|
|
86
Mage.Sets/src/mage/sets/commander/DreadCacodemon.java
Normal file
86
Mage.Sets/src/mage/sets/commander/DreadCacodemon.java
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.commander;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.DestroyAllEffect;
|
||||
import mage.abilities.effects.common.TapAllEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.AnotherPredicate;
|
||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||
import mage.watchers.common.CastFromHandWatcher;
|
||||
|
||||
/**
|
||||
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
||||
*/
|
||||
public class DreadCacodemon extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent opponentsCreatures = new FilterCreaturePermanent("creatures your opponents control");
|
||||
static {
|
||||
opponentsCreatures.add(new ControllerPredicate(TargetController.OPPONENT));
|
||||
}
|
||||
|
||||
private static final FilterCreaturePermanent otherCreaturesYouControl = new FilterCreaturePermanent("other creatures you control");
|
||||
static {
|
||||
otherCreaturesYouControl.add(new ControllerPredicate(TargetController.YOU));
|
||||
otherCreaturesYouControl.add(new AnotherPredicate());
|
||||
}
|
||||
|
||||
public DreadCacodemon(UUID ownerId) {
|
||||
super(ownerId, 79, "Dread Cacodemon", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{7}{B}{B}{B}");
|
||||
this.expansionSetCode = "CMD";
|
||||
this.subtype.add("Demon");
|
||||
this.power = new MageInt(8);
|
||||
this.toughness = new MageInt(8);
|
||||
|
||||
// When Dread Cacodemon enters the battlefield,
|
||||
// if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control.
|
||||
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(opponentsCreatures, false));
|
||||
ability.addEffect(new TapAllEffect(otherCreaturesYouControl));
|
||||
this.addAbility(new ConditionalTriggeredAbility(ability, new CastFromHandSourceCondition(),
|
||||
"When {this} enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."), new CastFromHandWatcher());
|
||||
}
|
||||
|
||||
public DreadCacodemon(final DreadCacodemon card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DreadCacodemon copy() {
|
||||
return new DreadCacodemon(this);
|
||||
}
|
||||
}
|
|
@ -53,7 +53,6 @@ public class AEtherSnap extends CardImpl {
|
|||
super(ownerId, 133, "AEther Snap", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{B}{B}");
|
||||
this.expansionSetCode = "C14";
|
||||
|
||||
|
||||
// Remove all counters from all permanents and exile all tokens.
|
||||
this.getSpellAbility().addEffect(new AEtherSnapEffect());
|
||||
}
|
||||
|
@ -88,13 +87,13 @@ class AEtherSnapEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
for (Permanent permanent :game.getBattlefield().getActivePermanents(new FilterPermanent(), controller.getId(), source.getSourceId(), game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterPermanent(), controller.getId(), source.getSourceId(), game)) {
|
||||
if (permanent instanceof PermanentToken) {
|
||||
controller.moveCardToExileWithInfo(permanent, null, "", source.getSourceId(), game, Zone.BATTLEFIELD, true);
|
||||
} else if (!permanent.getCounters().isEmpty()){
|
||||
} else if (!permanent.getCounters().isEmpty()) {
|
||||
Counters counters = permanent.getCounters().copy();
|
||||
for (Counter counter: counters.values()) {
|
||||
permanent.getCounters().removeCounter(counter.getName(), counter.getCount());
|
||||
for (Counter counter : counters.values()) {
|
||||
permanent.removeCounters(counter, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,10 +29,9 @@ package mage.sets.commander2014;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.ExileAllEffect;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
|
@ -61,10 +60,11 @@ public class AngelOfTheDireHour extends CardImpl {
|
|||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
// When Angel of the Dire Hour enters the battlefield, if you cast it from your hand, exile all attacking creatures.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new ConditionalOneShotEffect(new ExileAllEffect(new FilterAttackingCreature("attacking creatures")), new CastFromHandCondition(),
|
||||
" if you cast it from your hand, exile all attacking creatures"));
|
||||
this.addAbility(ability, new CastFromHandWatcher());
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new ExileAllEffect(new FilterAttackingCreature("attacking creatures")), false),
|
||||
new CastFromHandSourceCondition(),
|
||||
"When {this} enters the battlefield, if you cast it from your hand, exile all attacking creatures."),
|
||||
new CastFromHandWatcher());
|
||||
}
|
||||
|
||||
public AngelOfTheDireHour(final AngelOfTheDireHour card) {
|
||||
|
|
|
@ -32,8 +32,8 @@ import mage.MageInt;
|
|||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
|
||||
|
@ -64,10 +64,11 @@ public class BreachingLeviathan extends CardImpl {
|
|||
this.toughness = new MageInt(9);
|
||||
|
||||
// When Breaching Leviathan enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new ConditionalOneShotEffect(new BreachingLeviathanEffect(), new CastFromHandCondition(),
|
||||
"if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps"));
|
||||
this.addAbility(ability, new CastFromHandWatcher());
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new BreachingLeviathanEffect(), false),
|
||||
new CastFromHandSourceCondition(),
|
||||
"When {this} enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps."),
|
||||
new CastFromHandWatcher());
|
||||
}
|
||||
|
||||
public BreachingLeviathan(final BreachingLeviathan card) {
|
||||
|
@ -104,7 +105,7 @@ class BreachingLeviathanEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (Permanent creature: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
for (Permanent creature : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
creature.tap(game);
|
||||
ContinuousEffect effect = new DontUntapInControllersNextUntapStepTargetEffect();
|
||||
effect.setTargetPointer(new FixedTarget(creature.getId()));
|
||||
|
|
|
@ -57,10 +57,10 @@ public class ThiefOfBlood extends CardImpl {
|
|||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
this.subtype.add("Vampire");
|
||||
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
|
||||
// As Thief of Blood enters the battlefield, remove all counters from all permanents. Thief of Blood enters the battlefield with a +1/+1 counter on it for each counter removed this way.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ThiefOfBloodEffect(), null, "As {this} enters the battlefield, remove all counters from all permanents. {this} enters the battlefield with a +1/+1 counter on it for each counter removed this way", null));
|
||||
}
|
||||
|
@ -76,33 +76,34 @@ public class ThiefOfBlood extends CardImpl {
|
|||
}
|
||||
|
||||
class ThiefOfBloodEffect extends OneShotEffect {
|
||||
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("permanent with a counter");
|
||||
|
||||
static {
|
||||
filter.add(new CounterPredicate(null));
|
||||
}
|
||||
|
||||
|
||||
ThiefOfBloodEffect() {
|
||||
super(Outcome.BoostCreature);
|
||||
this.staticText = "remove all counters from all permanents. {this} enters the battlefield with a +1/+1 counter on it for each counter removed this way";
|
||||
}
|
||||
|
||||
|
||||
ThiefOfBloodEffect(final ThiefOfBloodEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ThiefOfBloodEffect copy() {
|
||||
return new ThiefOfBloodEffect(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int countersRemoved = 0;
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
|
||||
Counters counters = permanent.getCounters().copy();
|
||||
for (Counter counter : counters.values()) {
|
||||
permanent.getCounters().removeCounter(counter.getName(), counter.getCount());
|
||||
permanent.removeCounters(counter.getName(), counter.getCount(), game);
|
||||
countersRemoved += counter.getCount();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ class CurseOfExhaustionEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
if (enchantment != null && enchantment.getAttachedTo() != null) {
|
||||
Player player = game.getPlayer(enchantment.getAttachedTo());
|
||||
if (player != null && event.getPlayerId().equals(player.getId())) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -29,10 +29,9 @@ package mage.sets.darksteel;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.ExileAllEffect;
|
||||
import mage.abilities.keyword.AffinityForArtifactsAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
|
@ -41,9 +40,6 @@ import mage.constants.CardType;
|
|||
import mage.constants.Rarity;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.CastFromHandWatcher;
|
||||
|
||||
/**
|
||||
|
@ -51,7 +47,7 @@ import mage.watchers.common.CastFromHandWatcher;
|
|||
* @author fireshoes
|
||||
*/
|
||||
public class FurnaceDragon extends CardImpl {
|
||||
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("artifacts");
|
||||
|
||||
static {
|
||||
|
@ -67,12 +63,16 @@ public class FurnaceDragon extends CardImpl {
|
|||
|
||||
// Affinity for artifacts
|
||||
this.addAbility(new AffinityForArtifactsAbility());
|
||||
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
|
||||
// When Furnace Dragon enters the battlefield, if you cast it from your hand, exile all artifacts.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new ExileAllEffect(filter), new FurnaceDragonCondition()), false), new CastFromHandWatcher());
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new ExileAllEffect(filter), false),
|
||||
new CastFromHandSourceCondition(),
|
||||
"When {this} enters the battlefield, if you cast it from your hand, exile all artifacts."),
|
||||
new CastFromHandWatcher());
|
||||
}
|
||||
|
||||
public FurnaceDragon(final FurnaceDragon card) {
|
||||
|
@ -84,24 +84,3 @@ public class FurnaceDragon extends CardImpl {
|
|||
return new FurnaceDragon(this);
|
||||
}
|
||||
}
|
||||
|
||||
class FurnaceDragonCondition implements Condition {
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
boolean applies = false;
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
Watcher watcher = game.getState().getWatchers().get("CastFromHand", source.getSourceId());
|
||||
if (watcher != null && watcher.conditionMet()) {
|
||||
applies = true;
|
||||
}
|
||||
}
|
||||
return applies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "you cast it from your hand";
|
||||
}
|
||||
}
|
||||
|
|
60
Mage.Sets/src/mage/sets/darksteel/MetalFatigue.java
Normal file
60
Mage.Sets/src/mage/sets/darksteel/MetalFatigue.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.darksteel;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.TapAllEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterArtifactPermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author djbrez
|
||||
*/
|
||||
public class MetalFatigue extends CardImpl {
|
||||
|
||||
|
||||
public MetalFatigue(UUID ownerId) {
|
||||
super(ownerId, 8, "Metal Fatigue", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{W}");
|
||||
this.expansionSetCode = "DST";
|
||||
|
||||
// Tap all artifacts.
|
||||
this.getSpellAbility().addEffect(new TapAllEffect(new FilterArtifactPermanent("artifacts")));
|
||||
}
|
||||
|
||||
public MetalFatigue(final MetalFatigue card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetalFatigue copy() {
|
||||
return new MetalFatigue(this);
|
||||
}
|
||||
}
|
|
@ -30,10 +30,9 @@ package mage.sets.divinevsdemonic;
|
|||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.DestroyAllEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -50,9 +49,9 @@ import mage.watchers.common.CastFromHandWatcher;
|
|||
* @author daagar
|
||||
*/
|
||||
public class ReiverDemon extends CardImpl {
|
||||
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact, nonblack creatures");
|
||||
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT)));
|
||||
filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK)));
|
||||
|
@ -67,12 +66,13 @@ public class ReiverDemon extends CardImpl {
|
|||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
|
||||
// When Reiver Demon enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new ConditionalOneShotEffect(new DestroyAllEffect(filter), new CastFromHandCondition(),
|
||||
"if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated"));
|
||||
this.addAbility(ability, new CastFromHandWatcher());
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter, true), false),
|
||||
new CastFromHandSourceCondition(),
|
||||
"When {this} enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated."),
|
||||
new CastFromHandWatcher());
|
||||
}
|
||||
|
||||
public ReiverDemon(final ReiverDemon card) {
|
||||
|
|
|
@ -25,15 +25,14 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.sets.dragonsmaze;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.PopulateEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -46,11 +45,9 @@ import mage.watchers.common.CastFromHandWatcher;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
|
||||
public class ScionOfVituGhazi extends CardImpl {
|
||||
|
||||
public ScionOfVituGhazi (UUID ownerId) {
|
||||
public ScionOfVituGhazi(UUID ownerId) {
|
||||
super(ownerId, 7, "Scion of Vitu-Ghazi", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
|
||||
this.expansionSetCode = "DGM";
|
||||
this.subtype.add("Elemental");
|
||||
|
@ -58,15 +55,14 @@ public class ScionOfVituGhazi extends CardImpl {
|
|||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// When Scion of Vitu-Ghazi enters the battlefield, if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield, then populate.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new ConditionalOneShotEffect(new CreateTokenEffect(new BirdToken()), new CastFromHandCondition(),
|
||||
"if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield,"));
|
||||
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken()), false);
|
||||
ability.addEffect(new PopulateEffect("then"));
|
||||
this.addAbility(ability, new CastFromHandWatcher());
|
||||
this.addAbility(new ConditionalTriggeredAbility(ability, new CastFromHandSourceCondition(),
|
||||
"When {this} enters the battlefield, if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield, then populate."),
|
||||
new CastFromHandWatcher());
|
||||
}
|
||||
|
||||
public ScionOfVituGhazi (final ScionOfVituGhazi card) {
|
||||
public ScionOfVituGhazi(final ScionOfVituGhazi card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,8 @@ import mage.MageInt;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.DestroyAllEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -41,8 +42,6 @@ import mage.constants.Rarity;
|
|||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.AnotherPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.CastFromHandWatcher;
|
||||
|
||||
/**
|
||||
|
@ -50,9 +49,9 @@ import mage.watchers.common.CastFromHandWatcher;
|
|||
* @author jeffwadsworth
|
||||
*/
|
||||
public class DeathbringerRegent extends CardImpl {
|
||||
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures");
|
||||
|
||||
|
||||
static {
|
||||
filter.add(new AnotherPredicate());
|
||||
}
|
||||
|
@ -66,10 +65,13 @@ public class DeathbringerRegent extends CardImpl {
|
|||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
|
||||
// When Deathbringer Regent enters the battlefield, if you cast it from your hand and there are five or more other creatures on the battlefield, destroy all other creatures.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DestroyAllEffect(filter), new DeathbringerRegentCondition()), false), new CastFromHandWatcher());
|
||||
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter), false),
|
||||
new DeathbringerRegentCondition(),
|
||||
"When {this} enters the battlefield, if you cast it from your hand and there are five or more other creatures on the battlefield, destroy all other creatures."),
|
||||
new CastFromHandWatcher());
|
||||
}
|
||||
|
||||
public DeathbringerRegent(final DeathbringerRegent card) {
|
||||
|
@ -86,22 +88,7 @@ class DeathbringerRegentCondition implements Condition {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
boolean applies = false;
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
Watcher watcher = game.getState().getWatchers().get("CastFromHand", source.getSourceId());
|
||||
if (watcher != null && watcher.conditionMet()) {
|
||||
applies = true;
|
||||
}
|
||||
}
|
||||
if (applies) {
|
||||
applies = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), game).size() >= 6;
|
||||
}
|
||||
return applies;
|
||||
return new CastFromHandSourceCondition().apply(game, source)
|
||||
&& game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), game).size() >= 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "you cast it from your hand and there are five or more other creatures on the battlefield";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ class HardenedBerserkerSpellsCostReductionEffect extends CostModificationEffectI
|
|||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
if (watcher != null) {
|
||||
spellsCast = watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId());
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ class HardenedBerserkerSpellsCostReductionEffect extends CostModificationEffectI
|
|||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
if (watcher != null) {
|
||||
if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()) > spellsCast) {
|
||||
discard(); // only one use
|
||||
|
|
|
@ -29,7 +29,6 @@ package mage.sets.eventide;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
|
@ -39,14 +38,9 @@ import mage.abilities.keyword.FlyingAbility;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -69,7 +63,8 @@ public class DreamThief extends CardImpl {
|
|||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// When Dream Thief enters the battlefield, draw a card if you've cast another blue spell this turn.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), new CastBlueSpellThisTurnCondition(), rule)), new DreamThiefWatcher(this.getId()));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), new CastBlueSpellThisTurnCondition(), rule)),
|
||||
new SpellsCastWatcher());
|
||||
|
||||
}
|
||||
|
||||
|
@ -87,55 +82,14 @@ class CastBlueSpellThisTurnCondition implements Condition {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
DreamThiefWatcher watcher = (DreamThiefWatcher) game.getState().getWatchers().get("DreamThiefWatcher", source.getControllerId());
|
||||
SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getName());
|
||||
if (watcher != null) {
|
||||
return watcher.conditionMet();
|
||||
for (Spell spell : watcher.getSpellsCastThisTurn(source.getControllerId())) {
|
||||
if (!spell.getSourceId().equals(source.getSourceId()) && spell.getColor(game).isBlue()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class DreamThiefWatcher extends Watcher {
|
||||
|
||||
private static final FilterSpell filter = new FilterSpell();
|
||||
|
||||
static {
|
||||
filter.add(new ColorPredicate(ObjectColor.BLUE));
|
||||
}
|
||||
|
||||
private UUID cardId;
|
||||
|
||||
public DreamThiefWatcher(UUID cardId) {
|
||||
super("DreamThiefWatcher", WatcherScope.PLAYER);
|
||||
this.cardId = cardId;
|
||||
}
|
||||
|
||||
public DreamThiefWatcher(final DreamThiefWatcher watcher) {
|
||||
super(watcher);
|
||||
this.cardId = watcher.cardId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DreamThiefWatcher copy() {
|
||||
return new DreamThiefWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (condition == true) { //no need to check - condition has already occured
|
||||
return;
|
||||
}
|
||||
if (event.getType() == EventType.SPELL_CAST
|
||||
&& controllerId.equals(event.getPlayerId())) {
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (!spell.getSourceId().equals(cardId) && filter.match(spell, game)) {
|
||||
condition = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
}
|
||||
}
|
||||
|
|
74
Mage.Sets/src/mage/sets/exodus/PitSpawn.java
Normal file
74
Mage.Sets/src/mage/sets/exodus/PitSpawn.java
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.exodus;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.common.DealsDamageToACreatureTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.ExileTargetEffect;
|
||||
import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
|
||||
import mage.abilities.keyword.FirstStrikeAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author djbrez
|
||||
*/
|
||||
public class PitSpawn extends CardImpl {
|
||||
|
||||
public PitSpawn(UUID ownerId) {
|
||||
super(ownerId, 70, "Pit Spawn", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{B}{B}{B}");
|
||||
this.expansionSetCode = "EXO";
|
||||
this.subtype.add("Demon");
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// First strike
|
||||
this.addAbility(FirstStrikeAbility.getInstance());
|
||||
|
||||
// At the beginning of your upkeep, sacrifice Pit Spawn unless you pay {B}{B}.
|
||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{B}{B}")), TargetController.YOU, false));
|
||||
|
||||
// Whenever Pit Spawn deals damage to a creature, exile that creature.
|
||||
this.addAbility(new DealsDamageToACreatureTriggeredAbility(new ExileTargetEffect("exile that creature"), false, false, true));
|
||||
}
|
||||
|
||||
public PitSpawn(final PitSpawn card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PitSpawn copy() {
|
||||
return new PitSpawn(this);
|
||||
}
|
||||
}
|
|
@ -80,7 +80,7 @@ class OtherSpellsCastThisTurnCount implements DynamicValue {
|
|||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
return watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() - 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ class IncursionTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getPlayerId().equals(controllerId)) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
package mage.sets.innistrad;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -41,7 +38,9 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
|||
import mage.abilities.keyword.DefenderAbility;
|
||||
import mage.abilities.keyword.TransformAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
|
@ -83,6 +82,7 @@ public class LudevicsTestSubject extends CardImpl {
|
|||
}
|
||||
|
||||
class LudevicsTestSubjectEffect extends OneShotEffect {
|
||||
|
||||
LudevicsTestSubjectEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "Then if there are five or more hatchling counters on it, remove all of them and transform it";
|
||||
|
@ -97,7 +97,7 @@ class LudevicsTestSubjectEffect extends OneShotEffect {
|
|||
Permanent p = game.getPermanent(source.getSourceId());
|
||||
if (p != null) {
|
||||
if (p.getCounters().getCount(CounterType.HATCHLING) >= 5) {
|
||||
p.getCounters().removeCounter(CounterType.HATCHLING, p.getCounters().getCount(CounterType.HATCHLING));
|
||||
p.removeCounters(CounterType.HATCHLING.getName(), p.getCounters().getCount(CounterType.HATCHLING), game);
|
||||
TransformSourceEffect effect = new TransformSourceEffect(true);
|
||||
return effect.apply(game, source);
|
||||
}
|
||||
|
@ -109,4 +109,4 @@ class LudevicsTestSubjectEffect extends OneShotEffect {
|
|||
public LudevicsTestSubjectEffect copy() {
|
||||
return new LudevicsTestSubjectEffect(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,21 +83,12 @@ class RevivingVaporsEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (controller == null || sourceObject == null) {
|
||||
if (controller == null || sourceObject == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Cards cards = new CardsImpl();
|
||||
int count = Math.min(controller.getLibrary().size(), 3);
|
||||
for (int i = 0; i < count; i++) {
|
||||
Card card = controller.getLibrary().removeFromTop(game);
|
||||
if (card != null) {
|
||||
cards.add(card);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cards.addAll(controller.getLibrary().getTopCards(game, 3));
|
||||
if (!cards.isEmpty()) {
|
||||
controller.revealCards(sourceObject.getName(), cards, game);
|
||||
Card card = null;
|
||||
|
@ -112,9 +103,9 @@ class RevivingVaporsEffect extends OneShotEffect {
|
|||
}
|
||||
if (card != null) {
|
||||
cards.remove(card);
|
||||
controller.moveCards(card, Zone.LIBRARY, Zone.GRAVEYARD, source, game);
|
||||
controller.moveCards(card, Zone.HAND, source, game);
|
||||
}
|
||||
controller.moveCards(cards, Zone.LIBRARY, Zone.GRAVEYARD, source, game);
|
||||
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Rarity;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.SpiritWhiteToken;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
@ -55,7 +54,6 @@ public class CribSwap extends CardImpl {
|
|||
this.expansionSetCode = "LRW";
|
||||
this.subtype.add("Shapeshifter");
|
||||
|
||||
|
||||
// Changeling
|
||||
this.addAbility(ChangelingAbility.getInstance());
|
||||
// Exile target creature. Its controller puts a 1/1 colorless Shapeshifter creature token with changeling onto the battlefield.
|
||||
|
@ -112,7 +110,6 @@ class CribSwapShapeshifterWhiteToken extends Token {
|
|||
this.setOriginalExpansionSetCode("LRW");
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add("Shapeshifter");
|
||||
color.setWhite(true);
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
addAbility(ChangelingAbility.getInstance());
|
||||
|
|
|
@ -141,7 +141,7 @@ class AngelicArbiterCantAttackTargetEffect extends RestrictionEffect {
|
|||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
if (game.getActivePlayerId().equals(permanent.getControllerId()) && game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(permanent.getControllerId()) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ class AlhammarretHighArbiterCantCastEffect extends ContinuousRuleModifyingEffect
|
|||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.CAST_SPELL;
|
||||
return event.getType() == EventType.CAST_SPELL_LATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
package mage.sets.mirrodin;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
|
@ -39,7 +36,9 @@ import mage.abilities.costs.mana.GenericManaCost;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
|
@ -78,6 +77,7 @@ public class OblivionStone extends CardImpl {
|
|||
}
|
||||
|
||||
class OblivionStoneEffect extends OneShotEffect {
|
||||
|
||||
OblivionStoneEffect() {
|
||||
super(Outcome.DestroyPermanent);
|
||||
staticText = "Destroy each nonland permanent without a fate counter on it, then remove all fate counters from all permanents";
|
||||
|
@ -96,7 +96,7 @@ class OblivionStoneEffect extends OneShotEffect {
|
|||
}
|
||||
for (Permanent p : game.getBattlefield().getAllActivePermanents()) {
|
||||
if (p.getCounters().containsKey(CounterType.FATE)) {
|
||||
p.getCounters().removeCounter(CounterType.FATE, p.getCounters().getCount(CounterType.FATE));
|
||||
p.removeCounters(CounterType.FATE.getName(), p.getCounters().getCount(CounterType.FATE), game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -34,7 +34,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.DiesTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.condition.InvertCondition;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.GainSuspendEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
|
@ -67,7 +67,7 @@ public class Epochrasite extends CardImpl {
|
|||
// Epochrasite enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand.
|
||||
this.addAbility(new EntersBattlefieldAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)),
|
||||
new InvertCondition(new CastFromHandCondition()),
|
||||
new InvertCondition(new CastFromHandSourceCondition()),
|
||||
"{this} enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand",""),
|
||||
new CastFromHandWatcher());
|
||||
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
package mage.sets.newphyrexia;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.*;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
|
@ -37,6 +35,7 @@ import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
|
@ -50,6 +49,7 @@ import mage.target.TargetPermanent;
|
|||
* @author Loki
|
||||
*/
|
||||
public class ExclusionRitual extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("nonland permanent");
|
||||
|
||||
static {
|
||||
|
@ -60,7 +60,6 @@ public class ExclusionRitual extends CardImpl {
|
|||
super(ownerId, 10, "Exclusion Ritual", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}{W}");
|
||||
this.expansionSetCode = "NPH";
|
||||
|
||||
|
||||
// Imprint - When Exclusion Ritual enters the battlefield, exile target nonland permanent.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ExclusionRitualImprintEffect(), false);
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
|
@ -80,6 +79,7 @@ public class ExclusionRitual extends CardImpl {
|
|||
}
|
||||
|
||||
class ExclusionRitualImprintEffect extends OneShotEffect {
|
||||
|
||||
ExclusionRitualImprintEffect() {
|
||||
super(Outcome.Exile);
|
||||
staticText = "exile target nonland permanent";
|
||||
|
@ -108,6 +108,7 @@ class ExclusionRitualImprintEffect extends OneShotEffect {
|
|||
}
|
||||
|
||||
class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
ExclusionRitualReplacementEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
staticText = "Players can't cast spells with the same name as the exiled card";
|
||||
|
@ -116,12 +117,12 @@ class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl
|
|||
ExclusionRitualReplacementEffect(final ExclusionRitualReplacementEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL_LATE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
|
|
|
@ -103,13 +103,13 @@ class HexParasiteEffect extends OneShotEffect {
|
|||
for (String counterName : counterNames) {
|
||||
if (player.chooseUse(Outcome.Neutral, "Do you want to remove " + counterName + " counters?", source, game)) {
|
||||
if (permanent.getCounters().get(counterName).getCount() == 1 || toRemove == 1) {
|
||||
permanent.getCounters().removeCounter(counterName, 1);
|
||||
permanent.removeCounters(counterName, 1, game);
|
||||
removed++;
|
||||
} else {
|
||||
int amount = player.getAmount(1, Math.min(permanent.getCounters().get(counterName).getCount(), toRemove - removed), "How many?", game);
|
||||
if (amount > 0) {
|
||||
removed += amount;
|
||||
permanent.getCounters().removeCounter(counterName, amount);
|
||||
permanent.removeCounters(counterName, amount, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ class JoriEnTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getPlayerId().equals(controllerId)) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ class PyromancersAssaultTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getPlayerId().equals(controllerId)) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import mage.filter.predicate.permanent.ControllerPredicate;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.turn.Step;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
@ -110,7 +111,9 @@ class ReflectorMageEffect extends OneShotEffect {
|
|||
Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (targetCreature != null) {
|
||||
controller.moveCards(targetCreature, Zone.HAND, source, game);
|
||||
game.addEffect(new ExclusionRitualReplacementEffect(targetCreature.getName(), targetCreature.getOwnerId()), source);
|
||||
if (!targetCreature.getName().isEmpty()) { // if the creature had no name, no restrict effect will be created
|
||||
game.addEffect(new ExclusionRitualReplacementEffect(targetCreature.getName(), targetCreature.getOwnerId()), source);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -138,13 +141,17 @@ class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl
|
|||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL;
|
||||
return event.getType() == GameEvent.EventType.CAST_SPELL_LATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Card card = game.getCard(event.getSourceId());
|
||||
if (card != null) {
|
||||
Spell spell = game.getState().getStack().getSpell(event.getSourceId());
|
||||
if (spell != null && spell.isFaceDown(game)) {
|
||||
return false; // Face Down cast spell (Morph creature) has no name
|
||||
}
|
||||
return card.getName().equals(creatureName);
|
||||
}
|
||||
return false;
|
||||
|
|
94
Mage.Sets/src/mage/sets/onslaught/AphettoDredging.java
Normal file
94
Mage.Sets/src/mage/sets/onslaught/AphettoDredging.java
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.onslaught;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Quercitron
|
||||
*/
|
||||
public class AphettoDredging extends CardImpl {
|
||||
|
||||
public AphettoDredging(UUID ownerId) {
|
||||
super(ownerId, 125, "Aphetto Dredging", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{B}");
|
||||
this.expansionSetCode = "ONS";
|
||||
|
||||
// Return up to three target creature cards of the creature type of your choice from your graveyard to your hand.
|
||||
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
|
||||
effect.setText("Return up to three target creature cards of the creature type of your choice from your graveyard to your hand");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
if (ability instanceof SpellAbility) {
|
||||
Player controller = game.getPlayer(ability.getControllerId());
|
||||
if (controller != null) {
|
||||
Choice typeChoice = new ChoiceImpl(true);
|
||||
typeChoice.setMessage("Choose a creature type");
|
||||
typeChoice.setChoices(CardRepository.instance.getCreatureTypes());
|
||||
while (!controller.choose(Outcome.PutCreatureInPlay, typeChoice, game)) {
|
||||
if (!controller.canRespond()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
String chosenType = typeChoice.getChoice();
|
||||
|
||||
FilterCreatureCard filter = new FilterCreatureCard(chosenType + " cards");
|
||||
filter.add(new SubtypePredicate(chosenType));
|
||||
ability.addTarget(new TargetCardInYourGraveyard(0, 3, filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AphettoDredging(final AphettoDredging card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AphettoDredging copy() {
|
||||
return new AphettoDredging(this);
|
||||
}
|
||||
}
|
52
Mage.Sets/src/mage/sets/pdsslivers/AphettoDredging.java
Normal file
52
Mage.Sets/src/mage/sets/pdsslivers/AphettoDredging.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.pdsslivers;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Quercitron
|
||||
*/
|
||||
public class AphettoDredging extends mage.sets.onslaught.AphettoDredging {
|
||||
|
||||
public AphettoDredging(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 28;
|
||||
this.expansionSetCode = "PDS";
|
||||
}
|
||||
|
||||
public AphettoDredging(final AphettoDredging card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AphettoDredging copy() {
|
||||
return new AphettoDredging(this);
|
||||
}
|
||||
}
|
52
Mage.Sets/src/mage/sets/pdsslivers/WildPair.java
Normal file
52
Mage.Sets/src/mage/sets/pdsslivers/WildPair.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.pdsslivers;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fenhl
|
||||
*/
|
||||
public class WildPair extends mage.sets.planarchaos.WildPair {
|
||||
|
||||
public WildPair(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 30;
|
||||
this.expansionSetCode = "H09";
|
||||
}
|
||||
|
||||
public WildPair(final WildPair card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WildPair copy() {
|
||||
return new WildPair(this);
|
||||
}
|
||||
}
|
175
Mage.Sets/src/mage/sets/planarchaos/WildPair.java
Normal file
175
Mage.Sets/src/mage/sets/planarchaos/WildPair.java
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.planarchaos;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardsImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.IntComparePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.watchers.common.CastFromHandWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fenhl
|
||||
*/
|
||||
public class WildPair extends CardImpl {
|
||||
|
||||
public WildPair(UUID ownerID) {
|
||||
super(ownerID, 30, "Wild Pair", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}{G}");
|
||||
this.expansionSetCode = "PLC";
|
||||
|
||||
// Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library.
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new WildPairEffect(), new FilterCreaturePermanent("a creature"), true, SetTargetPointer.PERMANENT, ""),
|
||||
new CastFromHandTargetCondition(),
|
||||
"Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library."
|
||||
), new CastFromHandWatcher());
|
||||
}
|
||||
|
||||
public WildPair(final WildPair card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WildPair copy() {
|
||||
return new WildPair(this);
|
||||
}
|
||||
}
|
||||
|
||||
class WildPairEffect extends OneShotEffect {
|
||||
|
||||
public WildPairEffect() {
|
||||
super(Outcome.PutCreatureInPlay);
|
||||
this.staticText = "search your library for a creature card with the same total power and toughness and put it onto the battlefield";
|
||||
}
|
||||
|
||||
public WildPairEffect(final WildPairEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WildPairEffect copy() {
|
||||
return new WildPairEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source));
|
||||
if (permanent != null) {
|
||||
int totalPT = permanent.getPower().getValue() + permanent.getToughness().getValue();
|
||||
FilterCreatureCard filter = new FilterCreatureCard("creature card with total power and toughness " + totalPT);
|
||||
filter.add(new TotalPowerAndToughnessPredicate(Filter.ComparisonType.Equal, totalPT));
|
||||
TargetCardInLibrary target = new TargetCardInLibrary(1, filter);
|
||||
if (controller.searchLibrary(target, game)) {
|
||||
if (target.getTargets().size() > 0) {
|
||||
controller.moveCards(new CardsImpl(target.getTargets()), Zone.BATTLEFIELD, source, game);
|
||||
}
|
||||
}
|
||||
controller.shuffleLibrary(game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fenhl
|
||||
*/
|
||||
class TotalPowerAndToughnessPredicate extends IntComparePredicate<MageObject> {
|
||||
|
||||
public TotalPowerAndToughnessPredicate(Filter.ComparisonType type, int value) {
|
||||
super(type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getInputValue(MageObject input) {
|
||||
return input.getPower().getValue() + input.getToughness().getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TotalPowerAndToughness" + super.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class CastFromHandTargetCondition implements Condition {
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
UUID targetId = source.getEffects().get(0).getTargetPointer().getFirst(game, source);
|
||||
Permanent permanent = game.getPermanentEntering(targetId);
|
||||
int zccDiff = 0;
|
||||
if (permanent == null) {
|
||||
permanent = game.getPermanentOrLKIBattlefield(targetId); // can be alredy again removed from battlefield so also check LKI
|
||||
zccDiff = -1;
|
||||
}
|
||||
if (permanent != null) {
|
||||
// check that the spell is still in the LKI
|
||||
Spell spell = game.getStack().getSpell(targetId);
|
||||
if (spell == null || spell.getZoneChangeCounter(game) != permanent.getZoneChangeCounter(game) + zccDiff) {
|
||||
if (game.getLastKnownInformation(targetId, Zone.STACK, permanent.getZoneChangeCounter(game) + zccDiff) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CastFromHandWatcher watcher = (CastFromHandWatcher) game.getState().getWatchers().get(CastFromHandWatcher.class.getName());
|
||||
if (watcher != null && watcher.spellWasCastFromHand(targetId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "you cast it from your hand";
|
||||
}
|
||||
|
||||
}
|
|
@ -101,8 +101,8 @@ class DescendantOfMasumaroEffect extends OneShotEffect {
|
|||
}
|
||||
Player targetOpponent = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (targetOpponent != null && targetOpponent.getHand().size() > 0) {
|
||||
sourcePermanent.getCounters().removeCounter(CounterType.P1P1, targetOpponent.getHand().size());
|
||||
game.informPlayers(controller.getLogName() + " removes " + targetOpponent.getHand().size() + " +1/+1 counters from " + sourcePermanent.getLogName());
|
||||
sourcePermanent.removeCounters(CounterType.P1P1.getName(), targetOpponent.getHand().size(), game);
|
||||
game.informPlayers(controller.getLogName() + " removes " + targetOpponent.getHand().size() + " +1/+1 counters from " + sourcePermanent.getLogName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ class ErayoSoratamiAscendantTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
return watcher != null && watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() == 4;
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ class ErayosEssenceTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (game.getOpponents(getControllerId()).contains(event.getPlayerId())) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 1) {
|
||||
for (Effect effect : getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getTargetId()));
|
||||
|
|
|
@ -33,8 +33,8 @@ import mage.MageObject;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DiesTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ExileSourceEffect;
|
||||
|
@ -75,13 +75,14 @@ public class InameAsOne extends CardImpl {
|
|||
this.toughness = new MageInt(8);
|
||||
|
||||
// When Iname as One enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new ConditionalOneShotEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, filter), false),
|
||||
new CastFromHandCondition()));
|
||||
this.addAbility(ability, new CastFromHandWatcher());
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, filter)), true),
|
||||
new CastFromHandSourceCondition(),
|
||||
"When {this} enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library."),
|
||||
new CastFromHandWatcher());
|
||||
|
||||
// When Iname as One dies, you may exile it. If you do, return target Spirit permanent card from your graveyard to the battlefield.
|
||||
ability = new DiesTriggeredAbility(new InameAsOneEffect(), false);
|
||||
Ability ability = new DiesTriggeredAbility(new InameAsOneEffect(), false);
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ class ImpatienceCondition implements Condition {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
|
||||
return watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(game.getActivePlayerId()) == 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.shadowsoverinnistrad;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class EerieInterlude extends mage.sets.blessedvscursed.EerieInterlude {
|
||||
|
||||
public EerieInterlude(UUID ownerId) {
|
||||
super(ownerId);
|
||||
this.cardNumber = 994; //TODO: Fix card number
|
||||
this.expansionSetCode = "SOI";
|
||||
}
|
||||
|
||||
public EerieInterlude(final EerieInterlude card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EerieInterlude copy() {
|
||||
return new EerieInterlude(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.shadowsoverinnistrad;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.common.DeliriumCondition;
|
||||
import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class InvasiveSurgery extends CardImpl {
|
||||
|
||||
private final static FilterSpell filter = new FilterSpell("sorcery spell");
|
||||
|
||||
static {
|
||||
filter.add(new CardTypePredicate(CardType.SORCERY));
|
||||
}
|
||||
|
||||
public InvasiveSurgery(UUID ownerId) {
|
||||
super(ownerId, 68, "Invasive Surgery", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{U}");
|
||||
this.expansionSetCode = "SOI";
|
||||
|
||||
// Counter target sorcery spell.
|
||||
// <i>Delirium</i> — If there are four or more card types among cards in your graveyard, search the graveyard, hand, and library of that spell's controller for any number of cards with the same name as that spell, exile those cards, then that player shuffles his or her library.
|
||||
this.getSpellAbility().addEffect(new InvasiveSurgeryEffect());
|
||||
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
||||
|
||||
}
|
||||
|
||||
public InvasiveSurgery(final InvasiveSurgery card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvasiveSurgery copy() {
|
||||
return new InvasiveSurgery(this);
|
||||
}
|
||||
}
|
||||
|
||||
class InvasiveSurgeryEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExileEffect {
|
||||
|
||||
public InvasiveSurgeryEffect() {
|
||||
super(true, "that spell's controller", "all cards with the same name as that spell");
|
||||
}
|
||||
|
||||
public InvasiveSurgeryEffect(final InvasiveSurgeryEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvasiveSurgeryEffect copy() {
|
||||
return new InvasiveSurgeryEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
String cardName = "";
|
||||
UUID spellController = null;
|
||||
if (source.getTargets().get(0) instanceof TargetSpell) {
|
||||
UUID objectId = source.getFirstTarget();
|
||||
StackObject stackObject = game.getStack().getStackObject(objectId);
|
||||
if (stackObject != null) {
|
||||
MageObject targetObject = game.getObject(stackObject.getSourceId());
|
||||
if (targetObject instanceof Card) {
|
||||
cardName = targetObject.getName();
|
||||
}
|
||||
spellController = stackObject.getControllerId();
|
||||
game.getStack().counter(objectId, source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the Delirium condition
|
||||
if (!DeliriumCondition.getInstance().apply(game, source)) {
|
||||
return true;
|
||||
}
|
||||
return this.applySearchAndExile(game, source, cardName, spellController);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Mode mode) {
|
||||
return "Counter target sorcery spell.<br><br>"
|
||||
+ "<i>Delirium</i> — If there are four or more card types among cards in your graveyard, "
|
||||
+ "search the graveyard, hand, and library of that spell's controller for any number of cards "
|
||||
+ "with the same name as that spell, exile those cards, then that player shuffles his or her library";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.shadowsoverinnistrad;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldTappedAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
|
||||
import mage.abilities.effects.common.TapTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.ControllerPredicate;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class StichedMangler extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls");
|
||||
|
||||
static {
|
||||
filter.add(new ControllerPredicate(TargetController.OPPONENT));
|
||||
}
|
||||
|
||||
public StichedMangler(UUID ownerId) {
|
||||
super(ownerId, 89, "Stiched Mangler", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{U}");
|
||||
this.expansionSetCode = "SOI";
|
||||
this.subtype.add("Zombie");
|
||||
this.subtype.add("Horror");
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Stitched Mangler enters the battlefield tapped.
|
||||
this.addAbility(new EntersBattlefieldTappedAbility());
|
||||
|
||||
// When Stitched Mangler enters the battlefield, tap target creature an opponent controls. That creature doesn't untap during its controller's next untap step.
|
||||
EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect());
|
||||
ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect());
|
||||
ability.addTarget(new TargetCreaturePermanent(filter));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public StichedMangler(final StichedMangler card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StichedMangler copy() {
|
||||
return new StichedMangler(this);
|
||||
}
|
||||
}
|
|
@ -30,16 +30,13 @@ package mage.sets.sorinvstibalt;
|
|||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.BasicManaEffect;
|
||||
import mage.abilities.effects.common.ExileAllEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterAttackingCreature;
|
||||
import mage.watchers.common.CastFromHandWatcher;
|
||||
|
||||
/**
|
||||
|
@ -56,10 +53,11 @@ public class CoalStoker extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// When Coal Stoker enters the battlefield, if you cast it from your hand, add {R}{R}{R} to your mana pool.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new ConditionalOneShotEffect(new BasicManaEffect(new Mana(3, 0, 0, 0, 0, 0, 0, 0)), new CastFromHandCondition(),
|
||||
" if you cast it from your hand, add {R}{R}{R} to your mana pool."));
|
||||
this.addAbility(ability, new CastFromHandWatcher());
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new BasicManaEffect(new Mana(3, 0, 0, 0, 0, 0, 0, 0)), false),
|
||||
new CastFromHandSourceCondition(),
|
||||
"When {this} enters the battlefield, if you cast it from your hand, add {R}{R}{R} to your mana pool."),
|
||||
new CastFromHandWatcher());
|
||||
}
|
||||
|
||||
public CoalStoker(final CoalStoker card) {
|
||||
|
|
|
@ -73,10 +73,9 @@ public class CrovaxTheCursed extends CardImpl {
|
|||
Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new CrovaxTheCursedEffect(), TargetController.YOU, false);
|
||||
this.addAbility(ability);
|
||||
|
||||
|
||||
// {B}: Crovax gains flying until end of turn.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{B}")));
|
||||
|
||||
|
||||
}
|
||||
|
||||
public CrovaxTheCursed(final CrovaxTheCursed card) {
|
||||
|
@ -118,11 +117,9 @@ class CrovaxTheCursedEffect extends OneShotEffect {
|
|||
game.informPlayers(controller.getLogName() + " puts a +1/+1 counter on " + sourceObject.getName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (sourceObject != null && sourceObject.getCounters().containsKey(CounterType.P1P1)) {
|
||||
sourceObject.getCounters().removeCounter(CounterType.P1P1, 1);
|
||||
game.informPlayers(controller.getLogName() + " removes a +1/+1 counter from " + sourceObject.getName());
|
||||
}
|
||||
} else if (sourceObject != null && sourceObject.getCounters().containsKey(CounterType.P1P1)) {
|
||||
sourceObject.removeCounters(CounterType.P1P1.getName(), 1, game);
|
||||
game.informPlayers(controller.getLogName() + " removes a +1/+1 counter from " + sourceObject.getName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -107,10 +107,10 @@ class MagmasaurEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Permanent sourceObject = (Permanent)source.getSourceObjectIfItStillExists(game);
|
||||
Permanent sourceObject = (Permanent) source.getSourceObjectIfItStillExists(game);
|
||||
if (sourceObject != null && controller != null) {
|
||||
if (controller.chooseUse(outcome, "Remove a +1/+1 counter from " + sourceObject.getLogName() + "?", source, game)) {
|
||||
sourceObject.getCounters().removeCounter(CounterType.P1P1, 1);
|
||||
sourceObject.removeCounters(CounterType.P1P1.getName(), 1, game);
|
||||
} else {
|
||||
int counters = sourceObject.getCounters().getCount(CounterType.P1P1);
|
||||
sourceObject.sacrifice(source.getSourceId(), game);
|
||||
|
|
|
@ -33,7 +33,7 @@ import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
|
|||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.InvertCondition;
|
||||
import mage.abilities.condition.common.CastFromHandCondition;
|
||||
import mage.abilities.condition.common.CastFromHandSourceCondition;
|
||||
import mage.abilities.decorator.ConditionalTriggeredAbility;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.effects.common.LoseGameSourceControllerEffect;
|
||||
|
@ -62,7 +62,7 @@ public class PhageTheUntouchable extends CardImpl {
|
|||
// When Phage the Untouchable enters the battlefield, if you didn't cast it from your hand, you lose the game.
|
||||
this.addAbility(new ConditionalTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new LoseGameSourceControllerEffect(), false),
|
||||
new InvertCondition(new CastFromHandCondition()),
|
||||
new InvertCondition(new CastFromHandSourceCondition()),
|
||||
"When {this} enters the battlefield, if you didn't cast it from your hand, you lose the game"
|
||||
), new CastFromHandWatcher());
|
||||
|
||||
|
|
131
Mage.Sets/src/mage/sets/timespiral/LiegeOfThePit.java
Normal file
131
Mage.Sets/src/mage/sets/timespiral/LiegeOfThePit.java
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.timespiral;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.MorphAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.AnotherPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author djbrez
|
||||
*/
|
||||
public class LiegeOfThePit extends CardImpl {
|
||||
|
||||
public LiegeOfThePit(UUID ownerId) {
|
||||
super(ownerId, 113, "Liege of the Pit", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{B}{B}{B}");
|
||||
this.expansionSetCode = "TSP";
|
||||
this.subtype.add("Demon");
|
||||
this.power = new MageInt(7);
|
||||
this.toughness = new MageInt(7);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
// At the beginning of your upkeep, sacrifice a creature other than Liege of the Pit. If you can't, Liege of the Pit deals 7 damage to you.
|
||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new LiegeOfThePitEffect(), TargetController.YOU, false));
|
||||
// Morph {B}{B}{B}{B}
|
||||
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{B}{B}{B}{B}")));
|
||||
}
|
||||
|
||||
public LiegeOfThePit(final LiegeOfThePit card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiegeOfThePit copy() {
|
||||
return new LiegeOfThePit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LiegeOfThePitEffect extends OneShotEffect {
|
||||
|
||||
public LiegeOfThePitEffect() {
|
||||
super(Outcome.Damage);
|
||||
this.staticText = "Sacrifice a creature other than {this}. If you can't {this} deals 7 damage to you.";
|
||||
}
|
||||
|
||||
public LiegeOfThePitEffect(final LiegeOfThePitEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiegeOfThePitEffect copy() {
|
||||
return new LiegeOfThePitEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (sourcePermanent == null) {
|
||||
sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
|
||||
}
|
||||
if (player == null || sourcePermanent == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature other than " + sourcePermanent.getName());
|
||||
filter.add(new AnotherPredicate());
|
||||
|
||||
Target target = new TargetControlledCreaturePermanent(1, 1, filter, true);
|
||||
if (target.canChoose(source.getSourceId(), player.getId(), game)) {
|
||||
player.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.sacrifice(source.getSourceId(), game);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
player.damage(7, source.getSourceId(), game, false, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
207
Mage.Sets/src/mage/sets/timespiral/VesuvanShapeshifter.java
Normal file
207
Mage.Sets/src/mage/sets/timespiral/VesuvanShapeshifter.java
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.timespiral;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.AsTurnedFaceUpEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CopyEffect;
|
||||
import mage.abilities.effects.common.CopyPermanentEffect;
|
||||
import mage.abilities.keyword.MorphAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.AnotherPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.functions.ApplyToPermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public class VesuvanShapeshifter extends CardImpl {
|
||||
|
||||
protected Ability turnFaceUpAbility = null;
|
||||
private static final String effectText = "as a copy of any creature on the battlefield until {this} is turned faced down";
|
||||
|
||||
public VesuvanShapeshifter(UUID ownerId) {
|
||||
super(ownerId, 90, "Vesuvan Shapeshifter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
|
||||
this.expansionSetCode = "TSP";
|
||||
this.subtype.add("Shapeshifter");
|
||||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(0);
|
||||
|
||||
// Morph {1}{U}
|
||||
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{1}{U}")));
|
||||
|
||||
// As Vesuvan Shapeshifter turned face up, may choose another creature. If you do, until Vesuvan Shapeshifter is turned face down, it becomes a copy of that creature
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new AsTurnedFaceUpEffect(new VesuvanShapeshifterEffect(), false));
|
||||
ability.setWorksFaceDown(true);
|
||||
this.addAbility(ability);
|
||||
|
||||
// As Vesuvan Shapeshifter etbs, may choose another creature. If you do, until Vesuvan Shapeshifter is turned face down, it becomes a copy of that creature
|
||||
Effect effect = new CopyPermanentEffect(new FilterCreaturePermanent());
|
||||
effect.setText(effectText);
|
||||
ability = new EntersBattlefieldAbility(effect, true);
|
||||
ability.setWorksFaceDown(false);
|
||||
this.addAbility(ability);
|
||||
|
||||
// At the beginning of your upkeep, you may turn this creature face down
|
||||
effect = new VesuvanShapeshifterFaceDownEffect();
|
||||
ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, true);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
public VesuvanShapeshifter(final VesuvanShapeshifter card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VesuvanShapeshifter copy() {
|
||||
return new VesuvanShapeshifter(this);
|
||||
}
|
||||
}
|
||||
|
||||
class VesuvanShapeshifterEffect extends OneShotEffect {
|
||||
|
||||
public VesuvanShapeshifterEffect() {
|
||||
super(Outcome.Copy);
|
||||
staticText = "have {this} become a copy of a creature and gain this ability";
|
||||
}
|
||||
|
||||
public VesuvanShapeshifterEffect(final VesuvanShapeshifterEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VesuvanShapeshifterEffect copy() {
|
||||
return new VesuvanShapeshifterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
||||
ApplyToPermanent vesuvanShapeShifterFaceUpApplier = new ApplyToPermanent() {
|
||||
@Override
|
||||
public Boolean apply(Game game, Permanent permanent) {
|
||||
Effect effect = new VesuvanShapeshifterFaceDownEffect();
|
||||
Ability ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, true);
|
||||
permanent.getAbilities().add(ability);
|
||||
permanent.addAbility(new MorphAbility(permanent, new ManaCostsImpl("{1}{U}")), permanent.getId(), game);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Game game, MageObject mageObject) {
|
||||
Effect effect = new VesuvanShapeshifterFaceDownEffect();
|
||||
Ability ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, true);
|
||||
mageObject.getAbilities().add(ability);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Permanent copyToCreature = game.getPermanent(source.getSourceId());
|
||||
if (copyToCreature != null) {
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature");
|
||||
filter.add(new AnotherPredicate());
|
||||
|
||||
TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false);
|
||||
|
||||
if (controller.chooseTarget(Outcome.BecomeCreature, target, source, game) && !target.getTargets().isEmpty()) {
|
||||
Permanent copyFromCreature = game.getPermanentOrLKIBattlefield(target.getFirstTarget());
|
||||
if (copyFromCreature != null) {
|
||||
game.copyPermanent(Duration.Custom, copyFromCreature, copyToCreature.getId(), source, vesuvanShapeShifterFaceUpApplier);
|
||||
source.getTargets().clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class VesuvanShapeshifterFaceDownEffect extends OneShotEffect {
|
||||
|
||||
public VesuvanShapeshifterFaceDownEffect() {
|
||||
super(Outcome.Copy);
|
||||
staticText = "have {this} become a morphed, faced down creature";
|
||||
}
|
||||
|
||||
public VesuvanShapeshifterFaceDownEffect(final VesuvanShapeshifterFaceDownEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VesuvanShapeshifterFaceDownEffect copy() {
|
||||
return new VesuvanShapeshifterFaceDownEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (controller != null && permanent != null) {
|
||||
permanent.removeAllAbilities(source.getSourceId(), game);
|
||||
|
||||
// Set any previous copy effects to 'discarded'
|
||||
for (Effect effect : game.getState().getContinuousEffects().getLayeredEffects(game)) {
|
||||
if (effect instanceof CopyEffect) {
|
||||
CopyEffect copyEffect = (CopyEffect) effect;
|
||||
if (copyEffect.getSourceId().equals(permanent.getId())) {
|
||||
copyEffect.discard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
permanent.turnFaceDown(game, source.getControllerId());
|
||||
permanent.setManifested(false);
|
||||
permanent.setMorphed(true);
|
||||
return permanent.isFaceDown(game);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
74
Mage.Sets/src/mage/sets/weatherlight/Abjure.java
Normal file
74
Mage.Sets/src/mage/sets/weatherlight/Abjure.java
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.weatherlight;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.common.CounterTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.target.common.TargetControlledPermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author djbrez
|
||||
*/
|
||||
public class Abjure extends CardImpl {
|
||||
|
||||
private static final FilterControlledPermanent filter = new FilterControlledPermanent("a blue permanent");
|
||||
|
||||
static {
|
||||
filter.add(new ColorPredicate(ObjectColor.BLUE));
|
||||
}
|
||||
|
||||
public Abjure(UUID ownerId) {
|
||||
super(ownerId, 31, "Abjure", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{U}");
|
||||
this.expansionSetCode = "WTH";
|
||||
|
||||
// As an additional cost to cast Abjure, sacrifice a blue permanent.
|
||||
this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledPermanent(1,1,filter, true)));
|
||||
|
||||
// Counter target spell.
|
||||
this.getSpellAbility().addEffect(new CounterTargetEffect());
|
||||
this.getSpellAbility().addTarget(new TargetSpell());
|
||||
}
|
||||
|
||||
public Abjure(final Abjure card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abjure copy() {
|
||||
return new Abjure(this);
|
||||
}
|
||||
}
|
|
@ -27,25 +27,20 @@
|
|||
*/
|
||||
package mage.sets.worldwake;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.ColoredManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
|
||||
import mage.abilities.effects.common.TapTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.PermanentsEnteredBattlefieldWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -58,16 +53,13 @@ public class PermafrostTrap extends CardImpl {
|
|||
this.expansionSetCode = "WWK";
|
||||
this.subtype.add("Trap");
|
||||
|
||||
|
||||
// If an opponent had a green creature enter the battlefield under his or her control this turn, you may pay {U} rather than pay Permafrost Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(new PermafrostTrapAlternativeCost());
|
||||
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{U}"), PermafrostTrapCondition.getInstance()), new PermanentsEnteredBattlefieldWatcher());
|
||||
|
||||
// Tap up to two target creatures. Those creatures don't untap during their controller's next untap step.
|
||||
TargetCreaturePermanent target = new TargetCreaturePermanent(0, 2);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
this.getSpellAbility().addEffect(new PermafrostTrapEffect());
|
||||
|
||||
this.getSpellAbility().addWatcher(new PermafrostTrapWatcher());
|
||||
this.getSpellAbility().addEffect(new TapTargetEffect());
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2));
|
||||
this.getSpellAbility().addEffect(new DontUntapInControllersNextUntapStepTargetEffect());
|
||||
}
|
||||
|
||||
public PermafrostTrap(final PermafrostTrap card) {
|
||||
|
@ -80,99 +72,34 @@ public class PermafrostTrap extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class PermafrostTrapWatcher extends Watcher {
|
||||
class PermafrostTrapCondition implements Condition {
|
||||
|
||||
public PermafrostTrapWatcher() {
|
||||
super("PermafrostTrapWatcher", WatcherScope.GAME);
|
||||
}
|
||||
private static final PermafrostTrapCondition fInstance = new PermafrostTrapCondition();
|
||||
|
||||
public PermafrostTrapWatcher(final PermafrostTrapWatcher watcher) {
|
||||
super(watcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermafrostTrapWatcher copy() {
|
||||
return new PermafrostTrapWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (condition == true) { // no need to check - condition has already occured
|
||||
return;
|
||||
}
|
||||
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
|
||||
Permanent perm = game.getPermanent(event.getTargetId());
|
||||
if (perm.getCardType().contains(CardType.CREATURE) && perm.getColor(game).contains(ObjectColor.GREEN) && !perm.getControllerId().equals(controllerId)) {
|
||||
condition = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
condition = false;
|
||||
}
|
||||
}
|
||||
|
||||
class PermafrostTrapAlternativeCost extends AlternativeCostImpl<Cost> {
|
||||
|
||||
public PermafrostTrapAlternativeCost() {
|
||||
super("you may pay {U} rather than pay Permafrost Trap's mana cost");
|
||||
this.add(new ColoredManaCost(ColoredManaSymbol.U));
|
||||
}
|
||||
|
||||
public PermafrostTrapAlternativeCost(final PermafrostTrapAlternativeCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermafrostTrapAlternativeCost copy() {
|
||||
return new PermafrostTrapAlternativeCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Game game, Ability source) {
|
||||
PermafrostTrapWatcher watcher = (PermafrostTrapWatcher) game.getState().getWatchers().get("PermafrostTrapWatcher");
|
||||
if (watcher != null && watcher.conditionMet()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "If an opponent had a green creature enter the battlefield under his or her control this turn, you may pay {U} rather than pay Permafrost Trap's mana cost";
|
||||
}
|
||||
}
|
||||
|
||||
class PermafrostTrapEffect extends OneShotEffect {
|
||||
|
||||
public PermafrostTrapEffect() {
|
||||
super(Outcome.Detriment);
|
||||
staticText = "Tap up to two target creatures. Those creatures don't untap during their controller's next untap step";
|
||||
}
|
||||
|
||||
public PermafrostTrapEffect(final PermafrostTrapEffect effect) {
|
||||
super(effect);
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (UUID targetId : this.targetPointer.getTargets(game, source)) {
|
||||
Permanent creature = game.getPermanent(targetId);
|
||||
if (creature != null) {
|
||||
creature.tap(game);
|
||||
DontUntapInControllersNextUntapStepTargetEffect effect = new DontUntapInControllersNextUntapStepTargetEffect();
|
||||
effect.setTargetPointer(new FixedTarget(targetId));
|
||||
game.addEffect(effect, source);
|
||||
PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getName());
|
||||
if (watcher != null) {
|
||||
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
|
||||
List<Permanent> permanents = watcher.getThisTurnEnteringPermanents(opponentId);
|
||||
if (permanents != null) {
|
||||
for (Permanent permanent : permanents) {
|
||||
if (permanent.getCardType().contains(CardType.CREATURE) && permanent.getColor(game).isGreen()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermafrostTrapEffect copy() {
|
||||
return new PermafrostTrapEffect(this);
|
||||
public String toString() {
|
||||
return "If an opponent had a green creature enter the battlefield under his or her control this turn";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,13 +27,12 @@
|
|||
*/
|
||||
package mage.sets.worldwake;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostImpl;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.PreventionEffectImpl;
|
||||
|
@ -42,7 +41,6 @@ import mage.constants.CardType;
|
|||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
@ -51,7 +49,7 @@ import mage.game.stack.StackObject;
|
|||
import mage.players.Player;
|
||||
import mage.target.TargetSource;
|
||||
import mage.target.common.TargetCreatureOrPlayer;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -65,13 +63,11 @@ public class RefractionTrap extends CardImpl {
|
|||
this.subtype.add("Trap");
|
||||
|
||||
// If an opponent cast a red instant or sorcery spell this turn, you may pay {W} rather than pay Refraction Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(new RefractionTrapAlternativeCost());
|
||||
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{W}"), RefractionTrapCondition.getInstance()), new SpellsCastWatcher());
|
||||
|
||||
// Prevent the next 3 damage that a source of your choice would deal to you and/or permanents you control this turn. If damage is prevented this way, Refraction Trap deals that much damage to target creature or player.
|
||||
this.getSpellAbility().addEffect(new RefractionTrapPreventDamageEffect(Duration.EndOfTurn, 3));
|
||||
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
|
||||
|
||||
this.getSpellAbility().addWatcher(new RefractionTrapWatcher());
|
||||
}
|
||||
|
||||
public RefractionTrap(final RefractionTrap card) {
|
||||
|
@ -84,89 +80,43 @@ public class RefractionTrap extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class RefractionTrapWatcher extends Watcher {
|
||||
class RefractionTrapCondition implements Condition {
|
||||
|
||||
Set<UUID> playersMetCondition = new HashSet<>();
|
||||
private static final RefractionTrapCondition fInstance = new RefractionTrapCondition();
|
||||
|
||||
public RefractionTrapWatcher() {
|
||||
super("RefractionTrapWatcher", WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public RefractionTrapWatcher(final RefractionTrapWatcher watcher) {
|
||||
super(watcher);
|
||||
this.playersMetCondition.addAll(watcher.playersMetCondition);
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefractionTrapWatcher copy() {
|
||||
return new RefractionTrapWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (spell.getColor(game).isRed()) {
|
||||
if (spell.getCardType().contains(CardType.INSTANT)
|
||||
|| spell.getCardType().contains(CardType.SORCERY)) {
|
||||
playersMetCondition.add(event.getPlayerId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean conditionMetForAnOpponent(UUID controllerId, Game game) {
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller != null) {
|
||||
for (UUID playerId : playersMetCondition) {
|
||||
if (controller.hasOpponent(playerId, game)) {
|
||||
return true;
|
||||
public boolean apply(Game game, Ability source) {
|
||||
SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getName());
|
||||
if (watcher != null) {
|
||||
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
|
||||
List<Spell> spells = watcher.getSpellsCastThisTurn(opponentId);
|
||||
if (spells != null) {
|
||||
for (Spell spell : spells) {
|
||||
if ((spell.getCardType().contains(CardType.SORCERY) || spell.getCardType().contains(CardType.INSTANT))
|
||||
&& spell.getColor(game).isRed()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
playersMetCondition.clear();
|
||||
super.reset();
|
||||
}
|
||||
}
|
||||
|
||||
class RefractionTrapAlternativeCost extends AlternativeCostImpl {
|
||||
|
||||
public RefractionTrapAlternativeCost() {
|
||||
super("You may pay {W} rather than pay Refraction Trap's mana cost");
|
||||
this.add(new ManaCostsImpl<ManaCost>("{W}"));
|
||||
}
|
||||
|
||||
public RefractionTrapAlternativeCost(final RefractionTrapAlternativeCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RefractionTrapAlternativeCost copy() {
|
||||
return new RefractionTrapAlternativeCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Game game, Ability source) {
|
||||
RefractionTrapWatcher watcher = (RefractionTrapWatcher) game.getState().getWatchers().get("RefractionTrapWatcher");
|
||||
return watcher != null && watcher.conditionMetForAnOpponent(source.getControllerId(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "If an opponent cast a red instant or sorcery spell this turn, you may pay {W} rather than pay {this} mana cost";
|
||||
public String toString() {
|
||||
return "If an opponent cast a red instant or sorcery spell this turn";
|
||||
}
|
||||
}
|
||||
|
||||
class RefractionTrapPreventDamageEffect extends PreventionEffectImpl {
|
||||
|
||||
private final TargetSource target;
|
||||
private int amount;
|
||||
private final int amount;
|
||||
|
||||
public RefractionTrapPreventDamageEffect(Duration duration, int amount) {
|
||||
super(duration, amount, false, false);
|
||||
|
|
|
@ -27,26 +27,22 @@
|
|||
*/
|
||||
package mage.sets.worldwake;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.ColoredManaCost;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.ChooseNewTargetsTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.predicate.mageobject.NumberOfTargetsPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.target.TargetSpell;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -65,15 +61,14 @@ public class RicochetTrap extends CardImpl {
|
|||
this.expansionSetCode = "WWK";
|
||||
this.subtype.add("Trap");
|
||||
|
||||
|
||||
// If an opponent cast a blue spell this turn, you may pay {R} rather than pay Ricochet Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(new RicochetTrapAlternativeCost());
|
||||
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{R}"), RicochetTrapCondition.getInstance()));
|
||||
|
||||
// Change the target of target spell with a single target.
|
||||
this.getSpellAbility().addEffect(new ChooseNewTargetsTargetEffect(true, true));
|
||||
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
||||
|
||||
this.getSpellAbility().addWatcher(new RicochetTrapWatcher());
|
||||
this.getSpellAbility().addWatcher(new SpellsCastWatcher());
|
||||
}
|
||||
|
||||
public RicochetTrap(final RicochetTrap card) {
|
||||
|
@ -86,70 +81,34 @@ public class RicochetTrap extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class RicochetTrapWatcher extends Watcher {
|
||||
class RicochetTrapCondition implements Condition {
|
||||
|
||||
public RicochetTrapWatcher() {
|
||||
super("RicochetTrapWatcher", WatcherScope.GAME);
|
||||
}
|
||||
private static final RicochetTrapCondition fInstance = new RicochetTrapCondition();
|
||||
|
||||
public RicochetTrapWatcher(final RicochetTrapWatcher watcher) {
|
||||
super(watcher);
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RicochetTrapWatcher copy() {
|
||||
return new RicochetTrapWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (condition == true) //no need to check - condition has already occured
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (event.getType() == EventType.SPELL_CAST
|
||||
&& game.getOpponents(controllerId).contains(event.getPlayerId())) {
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (spell.getColor(game).isBlue()) {
|
||||
condition = true;
|
||||
public boolean apply(Game game, Ability source) {
|
||||
SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getName());
|
||||
if (watcher != null) {
|
||||
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
|
||||
List<Spell> spells = watcher.getSpellsCastThisTurn(opponentId);
|
||||
if (spells != null) {
|
||||
for (Spell spell : spells) {
|
||||
if (spell.getColor(game).isBlue()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
condition = false;
|
||||
}
|
||||
}
|
||||
|
||||
class RicochetTrapAlternativeCost extends AlternativeCostImpl<Cost> {
|
||||
|
||||
public RicochetTrapAlternativeCost() {
|
||||
super("You may pay {R} rather than pay Ricochet Trap's mana cost");
|
||||
this.add(new ColoredManaCost(ColoredManaSymbol.R));
|
||||
}
|
||||
|
||||
public RicochetTrapAlternativeCost(final RicochetTrapAlternativeCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RicochetTrapAlternativeCost copy() {
|
||||
return new RicochetTrapAlternativeCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Game game, Ability source) {
|
||||
RicochetTrapWatcher watcher = (RicochetTrapWatcher) game.getState().getWatchers().get("RicochetTrapWatcher");
|
||||
if (watcher != null && watcher.conditionMet()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "If an opponent cast a blue spell this turn, you may pay {R} rather than pay {this} mana cost";
|
||||
public String toString() {
|
||||
return "If an opponent cast a blue spell this turn";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,17 +27,16 @@
|
|||
*/
|
||||
package mage.sets.worldwake;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.common.FilterAttackingCreature;
|
||||
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||
import mage.game.Game;
|
||||
|
@ -61,9 +60,8 @@ public class SlingbowTrap extends CardImpl {
|
|||
this.expansionSetCode = "WWK";
|
||||
this.subtype.add("Trap");
|
||||
|
||||
|
||||
// If a black creature with flying is attacking, you may pay {G} rather than pay Slingbow Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(new SlingbowTrapAlternativeCost());
|
||||
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{G}"), SlingbowTrapCondition.getInstance()));
|
||||
|
||||
// Destroy target attacking creature with flying.
|
||||
this.getSpellAbility().addEffect(new DestroyTargetEffect());
|
||||
|
@ -80,37 +78,29 @@ public class SlingbowTrap extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class SlingbowTrapAlternativeCost extends AlternativeCostImpl<Cost> {
|
||||
class SlingbowTrapCondition implements Condition {
|
||||
|
||||
public SlingbowTrapAlternativeCost() {
|
||||
super("you may pay {G} rather than pay {this}'s mana cost");
|
||||
this.add(new ManaCostsImpl("{G}"));
|
||||
}
|
||||
private static final SlingbowTrapCondition fInstance = new SlingbowTrapCondition();
|
||||
|
||||
public SlingbowTrapAlternativeCost(final SlingbowTrapAlternativeCost cost) {
|
||||
super(cost);
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlingbowTrapAlternativeCost copy() {
|
||||
return new SlingbowTrapAlternativeCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Game game, Ability source) {
|
||||
List<UUID> attackers = game.getCombat().getAttackers();
|
||||
for (UUID creatureId : attackers) {
|
||||
Permanent creature = game.getPermanent(creatureId);
|
||||
if (creature.getColor(game).isBlack()
|
||||
&& creature.getAbilities().contains(FlyingAbility.getInstance())) {
|
||||
return true;
|
||||
public boolean apply(Game game, Ability source) {
|
||||
for (UUID attackingCreatureId : game.getCombat().getAttackers()) {
|
||||
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
|
||||
if (attackingCreature != null) {
|
||||
if (attackingCreature.getColor(game).isBlack() && attackingCreature.hasAbility(FlyingAbility.getInstance().getId(), game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "If a black creature with flying is attacking, you may pay {G} rather than pay Slingbow Trap's mana cost";
|
||||
public String toString() {
|
||||
return "If a black creature with flying is attacking";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ package mage.sets.zendikar;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostImpl;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DamageMultiEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -50,7 +51,7 @@ public class ArrowVolleyTrap extends CardImpl {
|
|||
this.subtype.add("Trap");
|
||||
|
||||
// If four or more creatures are attacking, you may pay {1}{W} rather than pay Arrow Volley Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(new ArrowVolleyTrapAlternativeCost());
|
||||
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{1}{W}"), ArrowVolleyTrapCondition.getInstance()));
|
||||
|
||||
// Arrow Volley Trap deals 5 damage divided as you choose among any number of target attacking creatures.
|
||||
this.getSpellAbility().addEffect(new DamageMultiEffect(5));
|
||||
|
@ -68,29 +69,21 @@ public class ArrowVolleyTrap extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class ArrowVolleyTrapAlternativeCost extends AlternativeCostImpl {
|
||||
class ArrowVolleyTrapCondition implements Condition {
|
||||
|
||||
public ArrowVolleyTrapAlternativeCost() {
|
||||
super("you may pay {1}{W} rather than pay Arrow Volley Trap's mana cost");
|
||||
this.add(new ManaCostsImpl("{1}{W}"));
|
||||
}
|
||||
private static final ArrowVolleyTrapCondition fInstance = new ArrowVolleyTrapCondition();
|
||||
|
||||
public ArrowVolleyTrapAlternativeCost(final ArrowVolleyTrapAlternativeCost cost) {
|
||||
super(cost);
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrowVolleyTrapAlternativeCost copy() {
|
||||
return new ArrowVolleyTrapAlternativeCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Game game, Ability source) {
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return game.getCombat().getAttackers().size() > 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "If four or more creatures are attacking, you may pay {1}{W} rather than pay {this}'s mana cost";
|
||||
public String toString() {
|
||||
return "If four or more creatures are attacking";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,20 +27,20 @@
|
|||
*/
|
||||
package mage.sets.zendikar;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostImpl;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.BeastToken2;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.PermanentsEnteredBattlefieldWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -54,8 +54,7 @@ public class BalothCageTrap extends CardImpl {
|
|||
this.subtype.add("Trap");
|
||||
|
||||
// If an opponent had an artifact enter the battlefield under his or her control this turn, you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(new BalothCageTrapAlternativeCost());
|
||||
this.getSpellAbility().addWatcher(new BalothCageTrapWatcher());
|
||||
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{1}{G}"), BalothCageTrapCondition.getInstance()), new PermanentsEnteredBattlefieldWatcher());
|
||||
|
||||
// Put a 4/4 green Beast creature token onto the battlefield.
|
||||
this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken2()));
|
||||
|
@ -71,68 +70,34 @@ public class BalothCageTrap extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class BalothCageTrapWatcher extends Watcher {
|
||||
class BalothCageTrapCondition implements Condition {
|
||||
|
||||
public BalothCageTrapWatcher() {
|
||||
super("BalothCageTrapWatcher", WatcherScope.GAME);
|
||||
}
|
||||
private static final BalothCageTrapCondition fInstance = new BalothCageTrapCondition();
|
||||
|
||||
public BalothCageTrapWatcher(final BalothCageTrapWatcher watcher) {
|
||||
super(watcher);
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BalothCageTrapWatcher copy() {
|
||||
return new BalothCageTrapWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (condition == true) { // no need to check - condition has already occured
|
||||
return;
|
||||
}
|
||||
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
|
||||
Permanent perm = game.getPermanent(event.getTargetId());
|
||||
if (perm.getCardType().contains(CardType.ARTIFACT) && !perm.getControllerId().equals(controllerId)) {
|
||||
condition = true;
|
||||
public boolean apply(Game game, Ability source) {
|
||||
PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getName());
|
||||
if (watcher != null) {
|
||||
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
|
||||
List<Permanent> permanents = watcher.getThisTurnEnteringPermanents(opponentId);
|
||||
if (permanents != null) {
|
||||
for (Permanent permanent : permanents) {
|
||||
if (permanent.getCardType().contains(CardType.ARTIFACT)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
condition = false;
|
||||
}
|
||||
}
|
||||
|
||||
class BalothCageTrapAlternativeCost extends AlternativeCostImpl {
|
||||
|
||||
public BalothCageTrapAlternativeCost() {
|
||||
super("you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost");
|
||||
this.add(new ManaCostsImpl("{1}{G}"));
|
||||
}
|
||||
|
||||
public BalothCageTrapAlternativeCost(final BalothCageTrapAlternativeCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BalothCageTrapAlternativeCost copy() {
|
||||
return new BalothCageTrapAlternativeCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Game game, Ability source) {
|
||||
BalothCageTrapWatcher watcher = (BalothCageTrapWatcher) game.getState().getWatchers().get("BalothCageTrapWatcher");
|
||||
if (watcher != null && watcher.conditionMet()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "If an opponent had an artifact enter the battlefield under his or her control this turn, you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost";
|
||||
public String toString() {
|
||||
return "If an opponent had an artifact enter the battlefield under his or her control this turn";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,25 +27,24 @@
|
|||
*/
|
||||
package mage.sets.zendikar;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.ColoredManaCost;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.SnakeToken;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
|
@ -59,11 +58,9 @@ public class CobraTrap extends CardImpl {
|
|||
this.expansionSetCode = "ZEN";
|
||||
this.subtype.add("Trap");
|
||||
|
||||
|
||||
// If a noncreature permanent under your control was destroyed this turn by a spell or ability an opponent controlled, you may pay {G} rather than pay Cobra Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(
|
||||
new CobraTrapAlternativeCost());
|
||||
this.getSpellAbility().addWatcher(new CobraTrapWatcher());
|
||||
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{G}"), CobraTrapCondition.getInstance()), new CobraTrapWatcher());
|
||||
|
||||
// Put four 1/1 green Snake creature tokens onto the battlefield.
|
||||
this.getSpellAbility().addEffect(new CreateTokenEffect(new SnakeToken(), 4));
|
||||
}
|
||||
|
@ -78,10 +75,33 @@ public class CobraTrap extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class CobraTrapCondition implements Condition {
|
||||
|
||||
private static final CobraTrapCondition fInstance = new CobraTrapCondition();
|
||||
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
CobraTrapWatcher watcher = (CobraTrapWatcher) game.getState().getWatchers().get(CobraTrapWatcher.class.getName());
|
||||
return watcher != null && watcher.conditionMet(source.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "If a noncreature permanent under your control was destroyed this turn by a spell or ability an opponent controlled";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CobraTrapWatcher extends Watcher {
|
||||
|
||||
Set<UUID> players = new HashSet<>();
|
||||
|
||||
public CobraTrapWatcher() {
|
||||
super("noncreature permanent destroyed", WatcherScope.PLAYER);
|
||||
super(CobraTrapWatcher.class.getName(), WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public CobraTrapWatcher(final CobraTrapWatcher watcher) {
|
||||
|
@ -95,51 +115,26 @@ class CobraTrapWatcher extends Watcher {
|
|||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (condition == true) { // no need to check - condition has already occured
|
||||
return;
|
||||
}
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player != null && event.getType() == EventType.DESTROYED_PERMANENT) {
|
||||
Permanent perm = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
|
||||
if (event.getType() == EventType.DESTROYED_PERMANENT) {
|
||||
Permanent perm = (Permanent) game.getPermanentOrLKIBattlefield(event.getTargetId()); // can regenerate or be indestructible
|
||||
if (perm != null && !perm.getCardType().contains(CardType.CREATURE)) {
|
||||
if (game.getStack().size() > 0) {
|
||||
StackObject spell = game.getStack().getStackObject(event.getSourceId());
|
||||
if (spell != null && game.getOpponents(controllerId).contains(spell.getControllerId())) {
|
||||
condition = true;
|
||||
if (spell != null && game.getOpponents(perm.getControllerId()).contains(spell.getControllerId())) {
|
||||
players.add(perm.getControllerId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CobraTrapAlternativeCost extends AlternativeCostImpl<Cost> {
|
||||
|
||||
public CobraTrapAlternativeCost() {
|
||||
super("you may pay {G} rather than pay Cobra Trap's mana cost");
|
||||
this.add(new ColoredManaCost(ColoredManaSymbol.G));
|
||||
}
|
||||
|
||||
public CobraTrapAlternativeCost(final CobraTrapAlternativeCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CobraTrapAlternativeCost copy() {
|
||||
return new CobraTrapAlternativeCost(this);
|
||||
public void reset() {
|
||||
super.reset();
|
||||
players.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Game game, Ability source) {
|
||||
Watcher watcher = game.getState().getWatchers().get("noncreature permanent destroyed", source.getControllerId());
|
||||
if (watcher != null && watcher.conditionMet()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "If a noncreature permanent under your control was destroyed this turn by a spell or ability an opponent controlled, you may pay {G} rather than pay Cobra Trap's mana cost";
|
||||
public boolean conditionMet(UUID playerId) {
|
||||
return players.contains(playerId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,15 +28,14 @@
|
|||
package mage.sets.zendikar;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostImpl;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
@ -54,11 +53,10 @@ public class InfernoTrap extends CardImpl {
|
|||
this.expansionSetCode = "ZEN";
|
||||
this.subtype.add("Trap");
|
||||
|
||||
|
||||
// If you've been dealt damage by two or more creatures this turn, you may pay {R} rather than pay Inferno Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(new InfernoTrapAlternativeCost());
|
||||
this.getSpellAbility().addWatcher(new ControllerDamagedByCreatureWatcher());
|
||||
|
||||
|
||||
// Inferno Trap deals 4 damage to target creature.
|
||||
this.getSpellAbility().addEffect(new DamageTargetEffect(4));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
|
|
|
@ -27,26 +27,23 @@
|
|||
*/
|
||||
package mage.sets.zendikar;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.AlternativeCostImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DamageAllEffect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.common.FilterLandPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetLandPermanent;
|
||||
import mage.watchers.Watcher;
|
||||
import mage.watchers.common.PermanentsEnteredBattlefieldWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -60,8 +57,7 @@ public class LavaballTrap extends CardImpl {
|
|||
this.subtype.add("Trap");
|
||||
|
||||
// If an opponent had two or more lands enter the battlefield under his or her control this turn, you may pay {3}{R}{R} rather than pay Lavaball Trap's mana cost.
|
||||
this.getSpellAbility().addAlternativeCost(new LavaballTrapAlternativeCost());
|
||||
this.getSpellAbility().addWatcher(new LavaballTrapWatcher());
|
||||
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{3}{R}{R}"), LavaballTrapCondition.getInstance()), new PermanentsEnteredBattlefieldWatcher());
|
||||
|
||||
// Destroy two target lands. Lavaball Trap deals 4 damage to each creature.
|
||||
this.getSpellAbility().addEffect(new DestroyTargetEffect());
|
||||
|
@ -80,87 +76,38 @@ public class LavaballTrap extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class LavaballTrapWatcher extends Watcher {
|
||||
class LavaballTrapCondition implements Condition {
|
||||
|
||||
private Map<UUID, Integer> amountOfLandsPlayedThisTurn = new HashMap<>();
|
||||
private static final LavaballTrapCondition fInstance = new LavaballTrapCondition();
|
||||
|
||||
public LavaballTrapWatcher() {
|
||||
super("LavaballTrapWatcher", WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public LavaballTrapWatcher(final LavaballTrapWatcher watcher) {
|
||||
super(watcher);
|
||||
for (Map.Entry<UUID, Integer> entry : watcher.amountOfLandsPlayedThisTurn.entrySet()) {
|
||||
amountOfLandsPlayedThisTurn.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
public static Condition getInstance() {
|
||||
return fInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LavaballTrapWatcher copy() {
|
||||
return new LavaballTrapWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
|
||||
Permanent perm = game.getPermanent(event.getTargetId());
|
||||
if (perm.getCardType().contains(CardType.LAND)) {
|
||||
Integer amount = amountOfLandsPlayedThisTurn.get(perm.getControllerId());
|
||||
if (amount == null) {
|
||||
amount = 1;
|
||||
} else {
|
||||
++amount;
|
||||
public boolean apply(Game game, Ability source) {
|
||||
PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getName());
|
||||
if (watcher != null) {
|
||||
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
|
||||
List<Permanent> permanents = watcher.getThisTurnEnteringPermanents(opponentId);
|
||||
if (permanents != null) {
|
||||
int count = 0;
|
||||
for (Permanent permanent : permanents) {
|
||||
if (permanent.getCardType().contains(CardType.LAND)) {
|
||||
count++;
|
||||
if (count == 2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
amountOfLandsPlayedThisTurn.put(perm.getControllerId(), amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int maxLandsAnOpponentPlayedThisTurn(UUID playerId, Game game) {
|
||||
int maxLands = 0;
|
||||
for (UUID opponentId : game.getOpponents(playerId)) {
|
||||
Integer amount = amountOfLandsPlayedThisTurn.get(opponentId);
|
||||
if (amount != null && amount > maxLands) {
|
||||
maxLands = amount;
|
||||
}
|
||||
}
|
||||
return maxLands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
amountOfLandsPlayedThisTurn.clear();
|
||||
}
|
||||
}
|
||||
|
||||
class LavaballTrapAlternativeCost extends AlternativeCostImpl<Cost> {
|
||||
|
||||
public LavaballTrapAlternativeCost() {
|
||||
super("you may pay {3}{R}{R} rather than pay Lavaball Trap's mana cost");
|
||||
this.add(new ManaCostsImpl("{3}{R}{R}"));
|
||||
}
|
||||
|
||||
public LavaballTrapAlternativeCost(final LavaballTrapAlternativeCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LavaballTrapAlternativeCost copy() {
|
||||
return new LavaballTrapAlternativeCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Game game, Ability source) {
|
||||
LavaballTrapWatcher watcher = (LavaballTrapWatcher) game.getState().getWatchers().get("LavaballTrapWatcher");
|
||||
if (watcher != null && watcher.maxLandsAnOpponentPlayedThisTurn(source.getControllerId(), game) > 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "If an opponent had two or more lands enter the battlefield under his or her control this turn, you may pay {3}{R}{R} rather than pay Lavaball Trap's mana cost";
|
||||
public String toString() {
|
||||
return "If an opponent had two or more lands enter the battlefield under his or her control this turn";
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue