Merge branch 'magefree/master'
|
|
@ -27,7 +27,7 @@ public class MageRoundPane extends JPanel {
|
||||||
|
|
||||||
private int X_OFFSET = 30;
|
private int X_OFFSET = 30;
|
||||||
private int Y_OFFSET = 30;
|
private int Y_OFFSET = 30;
|
||||||
private final Color defaultBackgroundColor = new Color(255, 255, 255, 200);
|
private final Color defaultBackgroundColor = new Color(141, 130, 112, 200);
|
||||||
private Color backgroundColor = defaultBackgroundColor;
|
private Color backgroundColor = defaultBackgroundColor;
|
||||||
private final int alpha = 0;
|
private final int alpha = 0;
|
||||||
private static Map<ShadowKey, BufferedImage> SHADOW_IMAGE_CACHE;
|
private static Map<ShadowKey, BufferedImage> SHADOW_IMAGE_CACHE;
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,16 @@
|
||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSubmitActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSubmitActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="JComponent" name="cardInfoPane">
|
<Component class="javax.swing.JButton" name="btnSubmitTimer">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" value="Submit in 1 minute"/>
|
||||||
|
<Property name="name" type="java.lang.String" value="btnSubmitTimer" noResource="true"/>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnSubmitTimerActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="JComponent" name="cardInfoPane">
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JTextField" name="txtTimeRemaining">
|
<Component class="javax.swing.JTextField" name="txtTimeRemaining">
|
||||||
</Component>
|
</Component>
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,25 @@
|
||||||
*/
|
*/
|
||||||
package mage.client.deckeditor;
|
package mage.client.deckeditor;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import javax.swing.filechooser.FileFilter;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.Sets;
|
import mage.cards.Sets;
|
||||||
import mage.cards.decks.Deck;
|
import mage.cards.decks.Deck;
|
||||||
|
|
@ -39,8 +58,8 @@ import mage.client.SessionHandler;
|
||||||
import mage.client.cards.BigCard;
|
import mage.client.cards.BigCard;
|
||||||
import mage.client.cards.ICardGrid;
|
import mage.client.cards.ICardGrid;
|
||||||
import mage.client.constants.Constants.DeckEditorMode;
|
import mage.client.constants.Constants.DeckEditorMode;
|
||||||
import mage.client.deck.generator.DeckGenerator;
|
|
||||||
import mage.client.deck.generator.DeckGenerator.DeckGeneratorException;
|
import mage.client.deck.generator.DeckGenerator.DeckGeneratorException;
|
||||||
|
import mage.client.deck.generator.DeckGenerator;
|
||||||
import mage.client.dialog.AddLandDialog;
|
import mage.client.dialog.AddLandDialog;
|
||||||
import mage.client.plugins.impl.Plugins;
|
import mage.client.plugins.impl.Plugins;
|
||||||
import mage.client.util.Event;
|
import mage.client.util.Event;
|
||||||
|
|
@ -52,22 +71,6 @@ import mage.remote.Session;
|
||||||
import mage.view.CardView;
|
import mage.view.CardView;
|
||||||
import mage.view.SimpleCardView;
|
import mage.view.SimpleCardView;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import javax.swing.Timer;
|
|
||||||
import javax.swing.filechooser.FileFilter;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.awt.event.WindowAdapter;
|
|
||||||
import java.awt.event.WindowEvent;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CancellationException;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
|
@ -84,6 +87,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
private int timeout;
|
private int timeout;
|
||||||
private Timer countdown;
|
private Timer countdown;
|
||||||
private UpdateDeckTask updateDeckTask;
|
private UpdateDeckTask updateDeckTask;
|
||||||
|
private int timeToSubmit = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form DeckEditorPanel
|
* Creates new form DeckEditorPanel
|
||||||
|
|
@ -160,6 +164,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
this.txtTimeRemaining.setVisible(true);
|
this.txtTimeRemaining.setVisible(true);
|
||||||
case SIDEBOARDING:
|
case SIDEBOARDING:
|
||||||
this.btnSubmit.setVisible(true);
|
this.btnSubmit.setVisible(true);
|
||||||
|
this.btnSubmitTimer.setVisible(true);
|
||||||
if (deck != null) {
|
if (deck != null) {
|
||||||
this.cardSelector.loadSideboard(new ArrayList<>(deck.getSideboard()), this.bigCard);
|
this.cardSelector.loadSideboard(new ArrayList<>(deck.getSideboard()), this.bigCard);
|
||||||
}
|
}
|
||||||
|
|
@ -187,6 +192,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
case FREE_BUILDING:
|
case FREE_BUILDING:
|
||||||
this.deckArea.setOrientation(/*limitedBuildingOrientation = */false);
|
this.deckArea.setOrientation(/*limitedBuildingOrientation = */false);
|
||||||
this.btnSubmit.setVisible(false);
|
this.btnSubmit.setVisible(false);
|
||||||
|
this.btnSubmitTimer.setVisible(false);
|
||||||
this.btnAddLand.setVisible(true);
|
this.btnAddLand.setVisible(true);
|
||||||
this.cardSelector.loadCards(this.bigCard);
|
this.cardSelector.loadCards(this.bigCard);
|
||||||
//this.cardTableSelector.loadCards(this.bigCard);
|
//this.cardTableSelector.loadCards(this.bigCard);
|
||||||
|
|
@ -484,6 +490,11 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
if (s == 60) {
|
if (s == 60) {
|
||||||
AudioManager.playOnCountdown1();
|
AudioManager.playOnCountdown1();
|
||||||
}
|
}
|
||||||
|
if (timeToSubmit > 0) {
|
||||||
|
timeToSubmit --;
|
||||||
|
btnSubmitTimer.setText("Submit (" + timeToSubmit + ")");
|
||||||
|
btnSubmitTimer.setToolTipText("Submit your deck in " + timeToSubmit + " seconds!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
|
@ -501,6 +512,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
btnExit = new javax.swing.JButton();
|
btnExit = new javax.swing.JButton();
|
||||||
btnImport = new javax.swing.JButton();
|
btnImport = new javax.swing.JButton();
|
||||||
btnSubmit = new javax.swing.JButton();
|
btnSubmit = new javax.swing.JButton();
|
||||||
|
btnSubmitTimer = new javax.swing.JButton();
|
||||||
btnAddLand = new javax.swing.JButton();
|
btnAddLand = new javax.swing.JButton();
|
||||||
btnGenDeck = new javax.swing.JButton();
|
btnGenDeck = new javax.swing.JButton();
|
||||||
txtTimeRemaining = new javax.swing.JTextField();
|
txtTimeRemaining = new javax.swing.JTextField();
|
||||||
|
|
@ -594,6 +606,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
});
|
});
|
||||||
|
|
||||||
btnSubmit.setText("Submit");
|
btnSubmit.setText("Submit");
|
||||||
|
btnSubmitTimer.setToolTipText("Submit your deck now!");
|
||||||
btnSubmit.setName("btnSubmit"); // NOI18N
|
btnSubmit.setName("btnSubmit"); // NOI18N
|
||||||
btnSubmit.addActionListener(new java.awt.event.ActionListener() {
|
btnSubmit.addActionListener(new java.awt.event.ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -602,6 +615,16 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
btnSubmitTimer.setText("Submit (60s)");
|
||||||
|
btnSubmitTimer.setToolTipText("Submit your deck in one minute!");
|
||||||
|
btnSubmitTimer.setName("btnSubmitTimer");
|
||||||
|
btnSubmitTimer.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
btnSubmitTimerActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
btnAddLand.setText("Add Land");
|
btnAddLand.setText("Add Land");
|
||||||
btnAddLand.setName("btnAddLand"); // NOI18N
|
btnAddLand.setName("btnAddLand"); // NOI18N
|
||||||
btnAddLand.addActionListener(new java.awt.event.ActionListener() {
|
btnAddLand.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
|
@ -610,7 +633,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
btnAddLandActionPerformed(evt);
|
btnAddLandActionPerformed(evt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
btnGenDeck.setText("Generate");
|
btnGenDeck.setText("Generate");
|
||||||
btnGenDeck.setName("btnGenDeck");
|
btnGenDeck.setName("btnGenDeck");
|
||||||
btnGenDeck.addActionListener(new java.awt.event.ActionListener() {
|
btnGenDeck.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
|
@ -658,7 +681,9 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addComponent(btnAddLand)
|
.addComponent(btnAddLand)
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addComponent(btnSubmit))
|
.addComponent(btnSubmit)
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(btnSubmitTimer))
|
||||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addComponent(txtTimeRemaining))
|
.addComponent(txtTimeRemaining))
|
||||||
|
|
@ -682,7 +707,8 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
.addComponent(btnImport)
|
.addComponent(btnImport)
|
||||||
.addComponent(btnGenDeck)
|
.addComponent(btnGenDeck)
|
||||||
.addComponent(btnAddLand)
|
.addComponent(btnAddLand)
|
||||||
.addComponent(btnSubmit))
|
.addComponent(btnSubmit)
|
||||||
|
.addComponent(btnSubmitTimer))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addComponent(txtTimeRemaining))
|
.addComponent(txtTimeRemaining))
|
||||||
|
|
@ -847,6 +873,26 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
}//GEN-LAST:event_btnSubmitActionPerformed
|
}//GEN-LAST:event_btnSubmitActionPerformed
|
||||||
|
|
||||||
|
private void btnSubmitTimerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSubmitTimerActionPerformed
|
||||||
|
|
||||||
|
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
|
||||||
|
timeToSubmit = 60;
|
||||||
|
this.btnSubmitTimer.setEnabled(false);
|
||||||
|
|
||||||
|
ScheduledFuture scheduledFuture = scheduledExecutorService.schedule(new Callable() {
|
||||||
|
public Object call() throws Exception {
|
||||||
|
if (updateDeckTask != null) {
|
||||||
|
updateDeckTask.cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SessionHandler.submitDeck(tableId, deck.getDeckCardLists())) {
|
||||||
|
removeDeckEditor();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, 60, TimeUnit.SECONDS);
|
||||||
|
}//GEN-LAST:event_btnSubmitTimerActionPerformed
|
||||||
|
|
||||||
private void btnAddLandActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddLandActionPerformed
|
private void btnAddLandActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddLandActionPerformed
|
||||||
AddLandDialog addLand = new AddLandDialog();
|
AddLandDialog addLand = new AddLandDialog();
|
||||||
addLand.showDialog(deck, mode);
|
addLand.showDialog(deck, mode);
|
||||||
|
|
@ -867,7 +913,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
refreshDeck();
|
refreshDeck();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private mage.client.cards.BigCard bigCard;
|
private mage.client.cards.BigCard bigCard;
|
||||||
private javax.swing.JButton btnExit;
|
private javax.swing.JButton btnExit;
|
||||||
|
|
@ -882,6 +928,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
||||||
private javax.swing.JLabel lblDeckName;
|
private javax.swing.JLabel lblDeckName;
|
||||||
private javax.swing.JTextField txtDeckName;
|
private javax.swing.JTextField txtDeckName;
|
||||||
private javax.swing.JButton btnSubmit;
|
private javax.swing.JButton btnSubmit;
|
||||||
|
private javax.swing.JButton btnSubmitTimer;
|
||||||
private javax.swing.JButton btnAddLand;
|
private javax.swing.JButton btnAddLand;
|
||||||
private javax.swing.JButton btnGenDeck;
|
private javax.swing.JButton btnGenDeck;
|
||||||
private JComponent cardInfoPane;
|
private JComponent cardInfoPane;
|
||||||
|
|
|
||||||
|
|
@ -916,33 +916,33 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private void updateSkipButtons(boolean turn, boolean endOfTurn, boolean nextMain, boolean allTurns, boolean stack, boolean endStepBeforeYourStep) {
|
private void updateSkipButtons(boolean turn, boolean endOfTurn, boolean nextMain, boolean allTurns, boolean stack, boolean endStepBeforeYourStep) {
|
||||||
if (turn) { //F4
|
if (turn) { //F4
|
||||||
btnSkipToNextTurn.setBorder(new LineBorder(Color.red, BORDER_SIZE));
|
btnSkipToNextTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE));
|
||||||
} else {
|
} else {
|
||||||
btnSkipToNextTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
btnSkipToNextTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
||||||
}
|
}
|
||||||
if (endOfTurn) { // F5
|
if (endOfTurn) { // F5
|
||||||
btnSkipToEndTurn.setBorder(new LineBorder(Color.red, BORDER_SIZE));
|
btnSkipToEndTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE));
|
||||||
} else {
|
} else {
|
||||||
btnSkipToEndTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
btnSkipToEndTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
||||||
}
|
}
|
||||||
if (nextMain) { // F7
|
if (nextMain) { // F7
|
||||||
btnSkipToNextMain.setBorder(new LineBorder(Color.red, BORDER_SIZE));
|
btnSkipToNextMain.setBorder(new LineBorder(Color.orange, BORDER_SIZE));
|
||||||
} else {
|
} else {
|
||||||
btnSkipToNextMain.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
btnSkipToNextMain.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
||||||
}
|
}
|
||||||
if (stack) { // F8
|
if (stack) { // F8
|
||||||
btnSkipStack.setBorder(new LineBorder(Color.red, BORDER_SIZE));
|
btnSkipStack.setBorder(new LineBorder(Color.orange, BORDER_SIZE));
|
||||||
} else {
|
} else {
|
||||||
btnSkipStack.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
btnSkipStack.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
||||||
}
|
}
|
||||||
if (allTurns) { // F9
|
if (allTurns) { // F9
|
||||||
btnSkipToYourTurn.setBorder(new LineBorder(Color.red, BORDER_SIZE));
|
btnSkipToYourTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE));
|
||||||
} else {
|
} else {
|
||||||
btnSkipToYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
btnSkipToYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endStepBeforeYourStep) { // F11
|
if (endStepBeforeYourStep) { // F11
|
||||||
btnSkipToEndStepBeforeYourTurn.setBorder(new LineBorder(Color.red, BORDER_SIZE));
|
btnSkipToEndStepBeforeYourTurn.setBorder(new LineBorder(Color.orange, BORDER_SIZE));
|
||||||
} else {
|
} else {
|
||||||
btnSkipToEndStepBeforeYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
btnSkipToEndStepBeforeYourTurn.setBorder(new EmptyBorder(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,8 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
||||||
private static final Border GREEN_BORDER = new LineBorder(Color.green, 3);
|
private static final Border GREEN_BORDER = new LineBorder(Color.green, 3);
|
||||||
private static final Border RED_BORDER = new LineBorder(Color.red, 2);
|
private static final Border RED_BORDER = new LineBorder(Color.red, 2);
|
||||||
private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(0, 0, 0, 0);
|
private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(0, 0, 0, 0);
|
||||||
private final Color greenBackgroundColor = new Color(180, 255, 180, 200);
|
private final Color greenBackgroundColor = new Color(206, 192, 174, 200);
|
||||||
private final Color deadBackgroundColor = new Color(200, 180, 180, 200);
|
private final Color deadBackgroundColor = new Color(131, 94, 83, 200);
|
||||||
|
|
||||||
private int avatarId = -1;
|
private int avatarId = -1;
|
||||||
private String flagName;
|
private String flagName;
|
||||||
|
|
@ -430,7 +430,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
||||||
|
|
||||||
// Poison count
|
// Poison count
|
||||||
poisonLabel.setText("0");
|
poisonLabel.setText("0");
|
||||||
r = new Rectangle(14, 14);
|
r = new Rectangle(18, 18);
|
||||||
poisonLabel.setToolTipText("Poison");
|
poisonLabel.setToolTipText("Poison");
|
||||||
Image imagePoison = ImageHelper.getImageFromResources("/info/poison.png");
|
Image imagePoison = ImageHelper.getImageFromResources("/info/poison.png");
|
||||||
BufferedImage resizedPoison = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(imagePoison, BufferedImage.TYPE_INT_ARGB), r);
|
BufferedImage resizedPoison = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(imagePoison, BufferedImage.TYPE_INT_ARGB), r);
|
||||||
|
|
@ -650,8 +650,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
||||||
.addGap(9)
|
.addGap(9)
|
||||||
.addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING)
|
.addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING)
|
||||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||||
.addGap(3)
|
.addComponent(poison, GroupLayout.PREFERRED_SIZE, 18, GroupLayout.PREFERRED_SIZE))
|
||||||
.addComponent(poison, GroupLayout.PREFERRED_SIZE, 14, GroupLayout.PREFERRED_SIZE))
|
|
||||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||||
.addGap(2)
|
.addGap(2)
|
||||||
.addComponent(btnWhiteMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE))
|
.addComponent(btnWhiteMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE))
|
||||||
|
|
@ -720,7 +719,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
||||||
.addComponent(avatar, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 80, Short.MAX_VALUE))
|
.addComponent(avatar, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 80, Short.MAX_VALUE))
|
||||||
// .addGroup(gl_panelBackground.createSequentialGroup()
|
// .addGroup(gl_panelBackground.createSequentialGroup()
|
||||||
// .addComponent(avatarFlag, GroupLayout.PREFERRED_SIZE, 16, GroupLayout.PREFERRED_SIZE))
|
// .addComponent(avatarFlag, GroupLayout.PREFERRED_SIZE, 16, GroupLayout.PREFERRED_SIZE))
|
||||||
.addGap(14))
|
.addGap(8))
|
||||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||||
.addGap(6)
|
.addGap(6)
|
||||||
.addComponent(zonesPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
|
.addComponent(zonesPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||||
|
|
@ -734,7 +733,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
||||||
.addPreferredGap(ComponentPlacement.RELATED)
|
.addPreferredGap(ComponentPlacement.RELATED)
|
||||||
.addComponent(btnPlayer)
|
.addComponent(btnPlayer)
|
||||||
.addComponent(timerLabel)
|
.addComponent(timerLabel)
|
||||||
.addGap(1)
|
.addGap(2)
|
||||||
// Life & Hand
|
// Life & Hand
|
||||||
.addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING)
|
.addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING)
|
||||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||||
|
|
@ -749,15 +748,15 @@ public class PlayerPanelExt extends javax.swing.JPanel {
|
||||||
// Poison
|
// Poison
|
||||||
.addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING)
|
.addGroup(gl_panelBackground.createParallelGroup(Alignment.LEADING)
|
||||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||||
.addGap(4)
|
.addGap(2)
|
||||||
.addComponent(poison, GroupLayout.PREFERRED_SIZE, 14, GroupLayout.PREFERRED_SIZE)
|
.addComponent(poison, GroupLayout.PREFERRED_SIZE, 18, GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(4)
|
.addGap(4)
|
||||||
.addComponent(btnWhiteMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)
|
.addComponent(btnWhiteMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(2)
|
.addGap(2)
|
||||||
.addComponent(btnBlueMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)
|
.addComponent(btnBlueMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(2)
|
.addGap(2)
|
||||||
.addComponent(btnBlackMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)
|
.addComponent(btnBlackMana, GroupLayout.PREFERRED_SIZE, 15, GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(5)
|
.addGap(3)
|
||||||
.addComponent(grave, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE)
|
.addComponent(grave, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE)
|
||||||
)
|
)
|
||||||
.addGroup(gl_panelBackground.createSequentialGroup()
|
.addGroup(gl_panelBackground.createSequentialGroup()
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 926 B After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 21 KiB |
|
|
@ -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_MAJOR = 1;
|
||||||
public final static int MAGE_VERSION_MINOR = 4;
|
public final static int MAGE_VERSION_MINOR = 4;
|
||||||
public final static int MAGE_VERSION_PATCH = 15;
|
public final static int MAGE_VERSION_PATCH = 15;
|
||||||
public final static String MAGE_VERSION_MINOR_PATCH = "v2";
|
public final static String MAGE_VERSION_MINOR_PATCH = "v4";
|
||||||
public final static String MAGE_VERSION_INFO = "";
|
public final static String MAGE_VERSION_INFO = "";
|
||||||
|
|
||||||
private final int major;
|
private final int major;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ package mage.view;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.ObjectColor;
|
import mage.ObjectColor;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
|
|
@ -55,7 +54,6 @@ import mage.game.stack.Spell;
|
||||||
import mage.game.stack.StackAbility;
|
import mage.game.stack.StackAbility;
|
||||||
import mage.target.Target;
|
import mage.target.Target;
|
||||||
import mage.target.Targets;
|
import mage.target.Targets;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
|
@ -81,7 +79,7 @@ public class CardView extends SimpleCardView {
|
||||||
protected List<String> manaCost;
|
protected List<String> manaCost;
|
||||||
protected int convertedManaCost;
|
protected int convertedManaCost;
|
||||||
protected Rarity rarity;
|
protected Rarity rarity;
|
||||||
|
|
||||||
protected MageObjectType mageObjectType = MageObjectType.NULL;
|
protected MageObjectType mageObjectType = MageObjectType.NULL;
|
||||||
|
|
||||||
protected boolean isAbility;
|
protected boolean isAbility;
|
||||||
|
|
@ -323,7 +321,8 @@ public class CardView extends SimpleCardView {
|
||||||
this.mageObjectType = MageObjectType.SPELL;
|
this.mageObjectType = MageObjectType.SPELL;
|
||||||
Spell spell = (Spell) card;
|
Spell spell = (Spell) card;
|
||||||
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
|
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
|
||||||
for (Mode mode : spellAbility.getModes().getSelectedModes()) {
|
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = spellAbility.getModes().get(modeId);
|
||||||
if (mode.getTargets().size() > 0) {
|
if (mode.getTargets().size() > 0) {
|
||||||
setTargets(spellAbility.getTargets());
|
setTargets(spellAbility.getTargets());
|
||||||
}
|
}
|
||||||
|
|
@ -331,18 +330,19 @@ public class CardView extends SimpleCardView {
|
||||||
}
|
}
|
||||||
// show for modal spell, which mode was choosen
|
// show for modal spell, which mode was choosen
|
||||||
if (spell.getSpellAbility().isModal()) {
|
if (spell.getSpellAbility().isModal()) {
|
||||||
for (Mode mode : spell.getSpellAbility().getModes().getSelectedModes()) {
|
for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) {
|
||||||
|
Mode mode = spell.getSpellAbility().getModes().get(modeId);
|
||||||
this.rules.add("<span color='green'><i>Chosen mode: " + mode.getEffects().getText(mode) + "</i></span>");
|
this.rules.add("<span color='green'><i>Chosen mode: " + mode.getEffects().getText(mode) + "</i></span>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Frame color
|
// Frame color
|
||||||
this.frameColor = card.getFrameColor(game);
|
this.frameColor = card.getFrameColor(game);
|
||||||
|
|
||||||
// Frame style
|
// Frame style
|
||||||
this.frameStyle = card.getFrameStyle();
|
this.frameStyle = card.getFrameStyle();
|
||||||
|
|
||||||
// Get starting loyalty
|
// Get starting loyalty
|
||||||
this.startingLoyalty = "" + card.getStartingLoyalty();
|
this.startingLoyalty = "" + card.getStartingLoyalty();
|
||||||
}
|
}
|
||||||
|
|
@ -355,7 +355,7 @@ public class CardView extends SimpleCardView {
|
||||||
this.mageObjectType = MageObjectType.PERMANENT;
|
this.mageObjectType = MageObjectType.PERMANENT;
|
||||||
this.power = Integer.toString(object.getPower().getValue());
|
this.power = Integer.toString(object.getPower().getValue());
|
||||||
this.toughness = Integer.toString(object.getToughness().getValue());
|
this.toughness = Integer.toString(object.getToughness().getValue());
|
||||||
this.loyalty = Integer.toString(((Permanent) object).getCounters((Game)null).getCount(CounterType.LOYALTY));
|
this.loyalty = Integer.toString(((Permanent) object).getCounters((Game) null).getCount(CounterType.LOYALTY));
|
||||||
} else {
|
} else {
|
||||||
this.power = object.getPower().toString();
|
this.power = object.getPower().toString();
|
||||||
this.toughness = object.getToughness().toString();
|
this.toughness = object.getToughness().toString();
|
||||||
|
|
@ -488,7 +488,7 @@ public class CardView extends SimpleCardView {
|
||||||
this.rarity = Rarity.NA;
|
this.rarity = Rarity.NA;
|
||||||
this.type = token.getTokenType();
|
this.type = token.getTokenType();
|
||||||
this.tokenDescriptor = token.getTokenDescriptor();
|
this.tokenDescriptor = token.getTokenDescriptor();
|
||||||
this.tokenSetCode = token.getOriginalExpansionSetCode();
|
this.tokenSetCode = token.getOriginalExpansionSetCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void setTargets(Targets targets) {
|
protected final void setTargets(Targets targets) {
|
||||||
|
|
@ -547,7 +547,7 @@ public class CardView extends SimpleCardView {
|
||||||
public String getLoyalty() {
|
public String getLoyalty() {
|
||||||
return loyalty;
|
return loyalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStartingLoyalty() {
|
public String getStartingLoyalty() {
|
||||||
return startingLoyalty;
|
return startingLoyalty;
|
||||||
}
|
}
|
||||||
|
|
@ -567,7 +567,7 @@ public class CardView extends SimpleCardView {
|
||||||
public ObjectColor getColor() {
|
public ObjectColor getColor() {
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectColor getFrameColor() {
|
public ObjectColor getFrameColor() {
|
||||||
return frameColor;
|
return frameColor;
|
||||||
}
|
}
|
||||||
|
|
@ -807,4 +807,3 @@ public class CardView extends SimpleCardView {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,8 @@ public class StackAbilityView extends CardView {
|
||||||
|
|
||||||
private void updateTargets(Game game, StackAbility ability) {
|
private void updateTargets(Game game, StackAbility ability) {
|
||||||
List<String> names = new ArrayList<>();
|
List<String> names = new ArrayList<>();
|
||||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = ability.getModes().get(modeId);
|
||||||
if (mode.getTargets().size() > 0) {
|
if (mode.getTargets().size() > 0) {
|
||||||
setTargets(mode.getTargets());
|
setTargets(mode.getTargets());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -132,7 +133,8 @@ public class StackAbilityView extends CardView {
|
||||||
// show for modal ability, which mode was choosen
|
// show for modal ability, which mode was choosen
|
||||||
if (ability.isModal()) {
|
if (ability.isModal()) {
|
||||||
Modes modes = ability.getModes();
|
Modes modes = ability.getModes();
|
||||||
for (Mode mode : modes.getSelectedModes()) {
|
for (UUID modeId : modes.getSelectedModes()) {
|
||||||
|
Mode mode = modes.get(modeId);
|
||||||
this.rules.add("<span color='green'><i>Chosen mode: " + mode.getEffects().getText(mode) + "</i></span>");
|
this.rules.add("<span color='green'><i>Chosen mode: " + mode.getEffects().getText(mode) + "</i></span>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1516,7 +1516,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
||||||
//TODO: improve this;
|
//TODO: improve this;
|
||||||
AvailableMode:
|
AvailableMode:
|
||||||
for (Mode mode : modes.getAvailableModes(source, game)) {
|
for (Mode mode : modes.getAvailableModes(source, game)) {
|
||||||
for (Mode selectedMode : modes.getSelectedModes()) {
|
for (UUID selectedModeId : modes.getSelectedModes()) {
|
||||||
|
Mode selectedMode = modes.get(selectedModeId);
|
||||||
if (selectedMode.getId().equals(mode.getId())) {
|
if (selectedMode.getId().equals(mode.getId())) {
|
||||||
continue AvailableMode;
|
continue AvailableMode;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -730,11 +730,14 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkPassStep(Game game) {
|
private boolean checkPassStep(Game game) {
|
||||||
if (playerId.equals(game.getActivePlayerId())) {
|
if (game.getStep() != null) {
|
||||||
return !this.getUserData().getUserSkipPrioritySteps().getYourTurn().isPhaseStepSet(game.getStep().getType());
|
if (playerId.equals(game.getActivePlayerId())) {
|
||||||
} else {
|
return !this.getUserData().getUserSkipPrioritySteps().getYourTurn().isPhaseStepSet(game.getStep().getType());
|
||||||
return !this.getUserData().getUserSkipPrioritySteps().getOpponentTurn().isPhaseStepSet(game.getStep().getType());
|
} else {
|
||||||
|
return !this.getUserData().getUserSkipPrioritySteps().getOpponentTurn().isPhaseStepSet(game.getStep().getType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -1323,7 +1326,8 @@ public class HumanPlayer extends PlayerImpl {
|
||||||
AvailableModes:
|
AvailableModes:
|
||||||
for (Mode mode : modes.getAvailableModes(source, game)) {
|
for (Mode mode : modes.getAvailableModes(source, game)) {
|
||||||
int timesSelected = 0;
|
int timesSelected = 0;
|
||||||
for (Mode selectedMode : modes.getSelectedModes()) {
|
for (UUID selectedModeId : modes.getSelectedModes()) {
|
||||||
|
Mode selectedMode = modes.get(selectedModeId);
|
||||||
if (mode.getId().equals(selectedMode.getId())) {
|
if (mode.getId().equals(selectedMode.getId())) {
|
||||||
if (modes.isEachModeMoreThanOnce()) {
|
if (modes.isEachModeMoreThanOnce()) {
|
||||||
timesSelected++;
|
timesSelected++;
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@
|
||||||
<draftCube name="MTGO Legacy Cube March 2015" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeMarch2015"/>
|
<draftCube name="MTGO Legacy Cube March 2015" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeMarch2015"/>
|
||||||
<draftCube name="MTGO Legacy Cube September 2015" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeSeptember2015"/>
|
<draftCube name="MTGO Legacy Cube September 2015" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeSeptember2015"/>
|
||||||
<draftCube name="MTGO Legacy Cube January 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeJanuary2016"/>
|
<draftCube name="MTGO Legacy Cube January 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeJanuary2016"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube September 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegacyCubeSeptember2016"/>
|
||||||
<draftCube name="MTGO Legendary Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCube"/>
|
<draftCube name="MTGO Legendary Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCube"/>
|
||||||
<draftCube name="MTGO Legendary Cube April 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCubeApril2016"/>
|
<draftCube name="MTGO Legendary Cube April 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCubeApril2016"/>
|
||||||
<draftCube name="MTGO Vintage Cube 2013" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCube2013"/>
|
<draftCube name="MTGO Vintage Cube 2013" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.VintageCube2013"/>
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@
|
||||||
<draftCube name="MTGO Legacy Cube March 2015" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeMarch2015"/>
|
<draftCube name="MTGO Legacy Cube March 2015" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeMarch2015"/>
|
||||||
<draftCube name="MTGO Legacy Cube September 2015" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeSeptember2015"/>
|
<draftCube name="MTGO Legacy Cube September 2015" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeSeptember2015"/>
|
||||||
<draftCube name="MTGO Legacy Cube January 2016" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeJanuary2016"/>
|
<draftCube name="MTGO Legacy Cube January 2016" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeJanuary2016"/>
|
||||||
|
<draftCube name="MTGO Legacy Cube September 2016" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.LegacyCubeSeptember2016"/>
|
||||||
<draftCube name="MTGO Legendary Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCube"/>
|
<draftCube name="MTGO Legendary Cube" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCube"/>
|
||||||
<draftCube name="MTGO Legendary Cube April 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCubeApril2016"/>
|
<draftCube name="MTGO Legendary Cube April 2016" jar="mage-tournament-booster-draft.jar" className="mage.tournament.cubes.LegendaryCubeApril2016"/>
|
||||||
<draftCube name="MTGO Vintage Cube 2013" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCube2013"/>
|
<draftCube name="MTGO Vintage Cube 2013" jar="mage-tournament-booster-draft-${project.version}.jar" className="mage.tournament.cubes.VintageCube2013"/>
|
||||||
|
|
|
||||||
|
|
@ -567,7 +567,7 @@ public class TableController {
|
||||||
String creator = null;
|
String creator = null;
|
||||||
StringBuilder opponent = new StringBuilder();
|
StringBuilder opponent = new StringBuilder();
|
||||||
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) { // no AI players
|
for (Entry<UUID, UUID> entry : userPlayerMap.entrySet()) { // no AI players
|
||||||
if (!match.getPlayer(entry.getValue()).hasQuit()) {
|
if (match.getPlayer(entry.getValue()) != null && !match.getPlayer(entry.getValue()).hasQuit()) {
|
||||||
User user = UserManager.getInstance().getUser(entry.getKey());
|
User user = UserManager.getInstance().getUser(entry.getKey());
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
user.ccGameStarted(match.getGame().getId(), entry.getValue());
|
user.ccGameStarted(match.getGame().getId(), entry.getValue());
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,8 @@ class ZadaHedronGrinderTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
if (isControlledInstantOrSorcery(spell)) {
|
if (isControlledInstantOrSorcery(spell)) {
|
||||||
boolean targetsSource = false;
|
boolean targetsSource = false;
|
||||||
for (Ability ability : spell.getSpellAbilities()) {
|
for (Ability ability : spell.getSpellAbilities()) {
|
||||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = ability.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
if (!target.isNotTarget()) {
|
if (!target.isNotTarget()) {
|
||||||
for (UUID targetId : target.getTargets()) {
|
for (UUID targetId : target.getTargets()) {
|
||||||
|
|
@ -167,7 +168,8 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
|
||||||
Target usedTarget = null;
|
Target usedTarget = null;
|
||||||
setUsedTarget:
|
setUsedTarget:
|
||||||
for (Ability ability : spell.getSpellAbilities()) {
|
for (Ability ability : spell.getSpellAbilities()) {
|
||||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = ability.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
if (!target.isNotTarget() && target.getFirstTarget().equals(source.getSourceId())) {
|
if (!target.isNotTarget() && target.getFirstTarget().equals(source.getSourceId())) {
|
||||||
usedTarget = target.copy();
|
usedTarget = target.copy();
|
||||||
|
|
@ -185,7 +187,8 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
|
||||||
Spell copy = spell.copySpell(source.getControllerId());
|
Spell copy = spell.copySpell(source.getControllerId());
|
||||||
game.getStack().push(copy);
|
game.getStack().push(copy);
|
||||||
setTarget:
|
setTarget:
|
||||||
for (Mode mode : copy.getSpellAbility().getModes().getSelectedModes()) {
|
for (UUID modeId : copy.getSpellAbility().getModes().getSelectedModes()) {
|
||||||
|
Mode mode = copy.getSpellAbility().getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
if (target.getClass().equals(usedTarget.getClass())) {
|
if (target.getClass().equals(usedTarget.getClass())) {
|
||||||
target.clearChosen(); // For targets with Max > 1 we need to clear before the text is comapred
|
target.clearChosen(); // For targets with Max > 1 we need to clear before the text is comapred
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@
|
||||||
package mage.sets.championsofkamigawa;
|
package mage.sets.championsofkamigawa;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import mage.constants.*;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.EntersBattlefieldAbility;
|
import mage.abilities.common.EntersBattlefieldAbility;
|
||||||
|
|
@ -40,15 +38,17 @@ import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||||
import mage.abilities.effects.common.PutOntoBattlefieldTargetEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||||
import mage.abilities.keyword.IndestructibleAbility;
|
import mage.abilities.keyword.IndestructibleAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardsImpl;
|
||||||
|
import mage.constants.*;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.common.FilterCreatureCard;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.game.Game;
|
||||||
import mage.filter.predicate.other.OwnerPredicate;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInHand;
|
import mage.target.common.TargetCardInHand;
|
||||||
import mage.watchers.common.CastFromHandWatcher;
|
import mage.watchers.common.CastFromHandWatcher;
|
||||||
|
|
||||||
|
|
@ -57,12 +57,6 @@ import mage.watchers.common.CastFromHandWatcher;
|
||||||
*/
|
*/
|
||||||
public class MyojinOfLifesWeb extends CardImpl {
|
public class MyojinOfLifesWeb extends CardImpl {
|
||||||
|
|
||||||
private static final FilterCard filter = new FilterCard("any number of creature cards from your hand");
|
|
||||||
static {
|
|
||||||
filter.add(new CardTypePredicate(CardType.CREATURE));
|
|
||||||
filter.add(new OwnerPredicate(TargetController.YOU));
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyojinOfLifesWeb(UUID ownerId) {
|
public MyojinOfLifesWeb(UUID ownerId) {
|
||||||
super(ownerId, 229, "Myojin of Life's Web", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{6}{G}{G}{G}");
|
super(ownerId, 229, "Myojin of Life's Web", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{6}{G}{G}{G}");
|
||||||
this.expansionSetCode = "CHK";
|
this.expansionSetCode = "CHK";
|
||||||
|
|
@ -79,10 +73,10 @@ public class MyojinOfLifesWeb extends CardImpl {
|
||||||
// Myojin of Life's Web is indestructible as long as it has a divinity counter on it.
|
// Myojin of Life's Web is indestructible as long as it has a divinity counter on it.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||||
new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
|
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")));
|
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));
|
||||||
// Remove a divinity counter from Myojin of Life's Web: Put any number of creature cards from your hand onto the battlefield.
|
// Remove a divinity counter from Myojin of Life's Web: Put any number of creature cards from your hand onto the battlefield.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutOntoBattlefieldTargetEffect(false), new RemoveCountersSourceCost(CounterType.DIVINITY.createInstance()));
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MyojinOfLifesWebPutCreatureOnBattlefieldEffect(), new RemoveCountersSourceCost(CounterType.DIVINITY.createInstance()));
|
||||||
ability.addTarget(new TargetCardInHand(0, Integer.MAX_VALUE, filter));
|
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,3 +89,35 @@ public class MyojinOfLifesWeb extends CardImpl {
|
||||||
return new MyojinOfLifesWeb(this);
|
return new MyojinOfLifesWeb(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MyojinOfLifesWebPutCreatureOnBattlefieldEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public MyojinOfLifesWebPutCreatureOnBattlefieldEffect() {
|
||||||
|
super(Outcome.PutCreatureInPlay);
|
||||||
|
this.staticText = "Put any number of creature cards from your hand onto the battlefield";
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyojinOfLifesWebPutCreatureOnBattlefieldEffect(final MyojinOfLifesWebPutCreatureOnBattlefieldEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MyojinOfLifesWebPutCreatureOnBattlefieldEffect copy() {
|
||||||
|
return new MyojinOfLifesWebPutCreatureOnBattlefieldEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetCardInHand target = new TargetCardInHand(0, Integer.MAX_VALUE, new FilterCreatureCard("creature cards from your hand to put onto the battlefield"));
|
||||||
|
if (controller.choose(Outcome.PutCreatureInPlay, target, source.getSourceId(), game)) {
|
||||||
|
return controller.moveCards(new CardsImpl(target.getTargets()).getCards(game),
|
||||||
|
Zone.BATTLEFIELD, source, game, false, false, false, null);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ public class GoblinArtisans extends CardImpl {
|
||||||
|
|
||||||
// {tap}: Flip a coin. If you win the flip, draw a card. If you lose the flip, counter target artifact spell you control that isn't the target of an ability from another creature named Goblin Artisans.
|
// {tap}: Flip a coin. If you win the flip, draw a card. If you lose the flip, counter target artifact spell you control that isn't the target of an ability from another creature named Goblin Artisans.
|
||||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GoblinArtisansEffect(), new TapSourceCost()));
|
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GoblinArtisansEffect(), new TapSourceCost()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GoblinArtisans(final GoblinArtisans card) {
|
public GoblinArtisans(final GoblinArtisans card) {
|
||||||
|
|
@ -83,15 +83,14 @@ public class GoblinArtisans extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class GoblinArtisansEffect extends OneShotEffect {
|
class GoblinArtisansEffect extends OneShotEffect {
|
||||||
|
|
||||||
private static final FilterPermanent filter = new FilterPermanent("permanent named Goblin Artisans");
|
private static final FilterPermanent filter = new FilterPermanent("permanent named Goblin Artisans");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new NamePredicate("Goblin Artisans"));
|
filter.add(new NamePredicate("Goblin Artisans"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public GoblinArtisansEffect() {
|
public GoblinArtisansEffect() {
|
||||||
super(Outcome.Damage);
|
super(Outcome.Damage);
|
||||||
staticText = "Flip a coin. If you win the flip, draw a card. If you lose the flip, counter target artifact spell you control that isn't the target of an ability from another creature named Goblin Artisans.";
|
staticText = "Flip a coin. If you win the flip, draw a card. If you lose the flip, counter target artifact spell you control that isn't the target of an ability from another creature named Goblin Artisans.";
|
||||||
|
|
@ -109,37 +108,38 @@ class GoblinArtisansEffect extends OneShotEffect {
|
||||||
controller.drawCards(1, game);
|
controller.drawCards(1, game);
|
||||||
} else {
|
} else {
|
||||||
List<Permanent> artifacts = game.getBattlefield().getActivePermanents(new FilterControlledArtifactPermanent(), source.getControllerId(), game);
|
List<Permanent> artifacts = game.getBattlefield().getActivePermanents(new FilterControlledArtifactPermanent(), source.getControllerId(), game);
|
||||||
if (artifacts.isEmpty()){//Don't even bother if there is no artifact to 'counter'/sacrifice
|
if (artifacts.isEmpty()) {//Don't even bother if there is no artifact to 'counter'/sacrifice
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
filter.add(Predicates.not(new PermanentIdPredicate(source.getSourceId())));
|
filter.add(Predicates.not(new PermanentIdPredicate(source.getSourceId())));
|
||||||
//removed the activating instance of Artisans, btw, wasn't that filter declared as static final? How come I can do this here? :)
|
//removed the activating instance of Artisans, btw, wasn't that filter declared as static final? How come I can do this here? :)
|
||||||
List<Permanent> list = game.getBattlefield().getAllActivePermanents(filter, game);
|
List<Permanent> list = game.getBattlefield().getAllActivePermanents(filter, game);
|
||||||
for (Permanent perm : list){ // should I limit below for a particular kind of ability? Going for the most general, it's unlikely there'll be any other artisans anyway, so not concerned about efficiency :p
|
for (Permanent perm : list) { // should I limit below for a particular kind of ability? Going for the most general, it's unlikely there'll be any other artisans anyway, so not concerned about efficiency :p
|
||||||
for (Ability abil : perm.getAbilities(game)){//below is copied from TargetsPermanentPredicate, but why only "selectedModes"? Shouldnt be more general as well?
|
for (Ability abil : perm.getAbilities(game)) {//below is copied from TargetsPermanentPredicate, but why only "selectedModes"? Shouldnt be more general as well?
|
||||||
for (Mode mode : abil.getModes().getSelectedModes()){
|
for (UUID modeId : abil.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = abil.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetId : target.getTargets()) {
|
for (UUID targetId : target.getTargets()) {
|
||||||
artifacts.remove(game.getPermanentOrLKIBattlefield(targetId));
|
artifacts.remove(game.getPermanentOrLKIBattlefield(targetId));
|
||||||
}// we could
|
}// we could
|
||||||
}// remove this
|
}// remove this
|
||||||
}//closing bracers
|
}//closing bracers
|
||||||
}// pyramid, if it's bothering anyone
|
}// pyramid, if it's bothering anyone
|
||||||
} //they are all one-liners after all :)
|
} //they are all one-liners after all :)
|
||||||
if (!artifacts.isEmpty()){
|
if (!artifacts.isEmpty()) {
|
||||||
Cards cards=new CardsImpl();
|
Cards cards = new CardsImpl();
|
||||||
for (Permanent perm : artifacts){
|
for (Permanent perm : artifacts) {
|
||||||
cards.add(perm.getId());
|
cards.add(perm.getId());
|
||||||
}
|
}
|
||||||
TargetCard target = new TargetCard(Zone.BATTLEFIELD, new FilterCard());
|
TargetCard target = new TargetCard(Zone.BATTLEFIELD, new FilterCard());
|
||||||
controller.choose(Outcome.Sacrifice, cards, target, game);
|
controller.choose(Outcome.Sacrifice, cards, target, game);
|
||||||
game.getPermanent(target.getFirstTarget()).sacrifice(source.getSourceId(), game);
|
game.getPermanent(target.getFirstTarget()).sacrifice(source.getSourceId(), game);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ class JelevaNephaliasScourgeEffect extends OneShotEffect {
|
||||||
for (int i = 0; i < cardsToExile; i++) {
|
for (int i = 0; i < cardsToExile; i++) {
|
||||||
Card card = player.getLibrary().removeFromTop(game);
|
Card card = player.getLibrary().removeFromTop(game);
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
card.moveToExile(CardUtil.getCardExileZoneId(game, source), sourceCard.getName(), source.getSourceId(), game);
|
card.moveToExile(CardUtil.getCardExileZoneId(game, source), sourceCard.getIdName(), source.getSourceId(), game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
*/
|
*/
|
||||||
package mage.sets.conspiracytakethecrown;
|
package mage.sets.conspiracytakethecrown;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
|
@ -41,8 +40,7 @@ import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.common.CardsAmountDrawnThisTurnWatcher;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -60,7 +58,7 @@ public class LeovoldEmissaryOfTrest extends CardImpl {
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
// Each opponent can't draw more than one card each turn. (Based on SpiritOfTheLabyrinth)
|
// Each opponent can't draw more than one card each turn. (Based on SpiritOfTheLabyrinth)
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LeovoldEmissaryOfTrestEffect()), new LeovoldEmissaryOfTrestWatcher());
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LeovoldEmissaryOfTrestEffect()), new CardsAmountDrawnThisTurnWatcher());
|
||||||
|
|
||||||
// Whenever you or a permanent you control becomes the target of a spell or ability an opponent controls, you may draw a card.
|
// Whenever you or a permanent you control becomes the target of a spell or ability an opponent controls, you may draw a card.
|
||||||
this.addAbility(new LeovoldEmissaryOfTrestTriggeredAbility());
|
this.addAbility(new LeovoldEmissaryOfTrestTriggeredAbility());
|
||||||
|
|
@ -76,47 +74,6 @@ public class LeovoldEmissaryOfTrest extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LeovoldEmissaryOfTrestWatcher extends Watcher {
|
|
||||||
|
|
||||||
private final HashSet<UUID> playersThatDrewCard;
|
|
||||||
|
|
||||||
public LeovoldEmissaryOfTrestWatcher() {
|
|
||||||
super("DrewCard", WatcherScope.GAME);
|
|
||||||
this.playersThatDrewCard = new HashSet<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LeovoldEmissaryOfTrestWatcher(final LeovoldEmissaryOfTrestWatcher watcher) {
|
|
||||||
super(watcher);
|
|
||||||
this.playersThatDrewCard = new HashSet<>();
|
|
||||||
playersThatDrewCard.addAll(watcher.playersThatDrewCard);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LeovoldEmissaryOfTrestWatcher copy() {
|
|
||||||
return new LeovoldEmissaryOfTrestWatcher(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void watch(GameEvent event, Game game) {
|
|
||||||
if (event.getType() == GameEvent.EventType.DREW_CARD ) {
|
|
||||||
playersThatDrewCard.add(event.getPlayerId());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
super.reset();
|
|
||||||
playersThatDrewCard.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasPlayerDrewCardThisTurn(UUID playerId) {
|
|
||||||
return playersThatDrewCard.contains(playerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class LeovoldEmissaryOfTrestEffect extends ContinuousRuleModifyingEffectImpl {
|
class LeovoldEmissaryOfTrestEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
public LeovoldEmissaryOfTrestEffect() {
|
public LeovoldEmissaryOfTrestEffect() {
|
||||||
|
|
@ -133,11 +90,6 @@ class LeovoldEmissaryOfTrestEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
return new LeovoldEmissaryOfTrestEffect(this);
|
return new LeovoldEmissaryOfTrestEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checksEventType(GameEvent event, Game game) {
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
return event.getType() == GameEvent.EventType.DRAW_CARD;
|
return event.getType() == GameEvent.EventType.DRAW_CARD;
|
||||||
|
|
@ -145,10 +97,9 @@ class LeovoldEmissaryOfTrestEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
LeovoldEmissaryOfTrestWatcher watcher = (LeovoldEmissaryOfTrestWatcher) game.getState().getWatchers().get("DrewCard");
|
CardsAmountDrawnThisTurnWatcher watcher = (CardsAmountDrawnThisTurnWatcher) game.getState().getWatchers().get(CardsAmountDrawnThisTurnWatcher.BASIC_KEY);
|
||||||
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
return watcher != null && controller != null && watcher.hasPlayerDrewCardThisTurn(event.getPlayerId())
|
return watcher != null && controller != null && watcher.getAmountCardsDrawn(event.getPlayerId()) >= 1
|
||||||
&& game.isOpponent(controller, event.getPlayerId());
|
&& game.isOpponent(controller, event.getPlayerId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,9 +129,10 @@ class LeovoldEmissaryOfTrestTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
Player controller = game.getPlayer(this.getControllerId());
|
Player controller = game.getPlayer(this.getControllerId());
|
||||||
Player targetter = game.getPlayer(event.getPlayerId());
|
Player targetter = game.getPlayer(event.getPlayerId());
|
||||||
if (controller != null && targetter != null && !controller.getId().equals(targetter.getId())) {
|
if (controller != null && targetter != null
|
||||||
|
&& game.isOpponent(controller, targetter.getId())) {
|
||||||
if (event.getTargetId().equals(controller.getId())) {
|
if (event.getTargetId().equals(controller.getId())) {
|
||||||
return true;
|
return true; // Player was targeted
|
||||||
}
|
}
|
||||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
||||||
if (permanent != null && this.getControllerId().equals(permanent.getControllerId())) {
|
if (permanent != null && this.getControllerId().equals(permanent.getControllerId())) {
|
||||||
|
|
@ -192,6 +144,6 @@ class LeovoldEmissaryOfTrestTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "Whenever you or a permanent you control becomes the target of a spell or ability an opponent controls, you may draw a card.";
|
return "Whenever you or a permanent you control becomes the target of a spell or ability an opponent controls, " + super.getRule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ import mage.choices.ChoiceImpl;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
@ -95,6 +96,12 @@ class ChooseNumberEffect extends OneShotEffect {
|
||||||
|
|
||||||
int numberChoice = controller.announceXMana(0, Integer.MAX_VALUE, "Choose a number. Noncreature spells with the chosen converted mana cost can't be cast", game, source);
|
int numberChoice = controller.announceXMana(0, Integer.MAX_VALUE, "Choose a number. Noncreature spells with the chosen converted mana cost can't be cast", game, source);
|
||||||
game.getState().setValue(source.getSourceId().toString(), numberChoice);
|
game.getState().setValue(source.getSourceId().toString(), numberChoice);
|
||||||
|
|
||||||
|
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
||||||
|
permanent.addInfo("chosen players", "<font color = 'blue'>Chosen Number: "+ numberChoice +"</font>", game);
|
||||||
|
|
||||||
|
game.informPlayers(permanent.getLogName() + ", chosen number: "+numberChoice);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,13 @@ import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.mana.DynamicManaAbility;
|
import mage.abilities.mana.DynamicManaAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
import mage.filter.FilterPermanent;
|
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.ObjectSourcePlayer;
|
import mage.filter.predicate.ObjectSourcePlayer;
|
||||||
|
|
@ -48,7 +48,6 @@ import mage.filter.predicate.permanent.AnotherPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.targetpointer.FixedTarget;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -56,8 +55,8 @@ import mage.target.targetpointer.FixedTarget;
|
||||||
*/
|
*/
|
||||||
public class SelvalaHeartOfTheWilds extends CardImpl {
|
public class SelvalaHeartOfTheWilds extends CardImpl {
|
||||||
|
|
||||||
|
|
||||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature");
|
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(new AnotherPredicate());
|
filter.add(new AnotherPredicate());
|
||||||
filter.add(new GreatestPowerPredicate());
|
filter.add(new GreatestPowerPredicate());
|
||||||
|
|
@ -75,12 +74,14 @@ public class SelvalaHeartOfTheWilds extends CardImpl {
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
// Whenever another creature enters the battlefield, its controller may draw a card if its power is greater than each other creature's power.
|
// Whenever another creature enters the battlefield, its controller may draw a card if its power is greater than each other creature's power.
|
||||||
|
|
||||||
this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new SelvalaHeartOfTheWildsEffect(), filter, false, SetTargetPointer.PERMANENT, rule));
|
this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new SelvalaHeartOfTheWildsEffect(), filter, false, SetTargetPointer.PERMANENT, rule));
|
||||||
|
|
||||||
// {G}, {T}: Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control.
|
// {G}, {T}: Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control.
|
||||||
this.addAbility(new DynamicManaAbility(new Mana(0,0,0,0,0,0,1, 0), new GreatestPowerYouControlValue(), new TapSourceCost(),
|
Ability ability = new DynamicManaAbility(new Mana(0, 0, 0, 0, 0, 0, 1, 0), new GreatestPowerYouControlValue(), new ManaCostsImpl<>("{G}"),
|
||||||
"Add X mana in any combination of colors to your mana pool, where X is the number of creatures with defender you control."));
|
"Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control.");
|
||||||
|
ability.addCost(new TapSourceCost());
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SelvalaHeartOfTheWilds(final SelvalaHeartOfTheWilds card) {
|
public SelvalaHeartOfTheWilds(final SelvalaHeartOfTheWilds card) {
|
||||||
|
|
@ -112,12 +113,12 @@ class SelvalaHeartOfTheWildsEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
|
Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
|
||||||
if(permanent == null){
|
if (permanent == null) {
|
||||||
permanent = (Permanent)game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.BATTLEFIELD);
|
permanent = (Permanent) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.BATTLEFIELD);
|
||||||
}
|
}
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
Player cardowner = game.getPlayer(permanent.getControllerId());
|
Player cardowner = game.getPlayer(permanent.getControllerId());
|
||||||
if(cardowner.chooseUse(Outcome.DrawCard, "Would you like to draw a card?", source, game)){
|
if (cardowner.chooseUse(Outcome.DrawCard, "Would you like to draw a card?", source, game)) {
|
||||||
cardowner.drawCards(1, game);
|
cardowner.drawCards(1, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,18 +126,17 @@ class SelvalaHeartOfTheWildsEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class GreatestPowerPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<Permanent>> {
|
class GreatestPowerPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<Permanent>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
|
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
|
||||||
int pow = input.getObject().getPower().getValue();
|
int pow = input.getObject().getPower().getValue();
|
||||||
|
|
||||||
for (UUID id :game.getPlayerList()){
|
for (UUID id : game.getPlayerList()) {
|
||||||
Player player = game.getPlayer(id);
|
Player player = game.getPlayer(id);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
for (Permanent p : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), id, game)) {
|
for (Permanent p : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), id, game)) {
|
||||||
if(p.getPower().getValue() >= pow && !p.equals(input.getObject())){
|
if (p.getPower().getValue() >= pow && !p.equals(input.getObject())) {
|
||||||
return false; //we found something with equal/more power
|
return false; //we found something with equal/more power
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -144,6 +144,7 @@ class GreatestPowerPredicate implements ObjectSourcePlayerPredicate<ObjectSource
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Greatest Power";
|
return "Greatest Power";
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,8 @@ class IcefallRegentCostIncreaseEffect extends CostModificationEffectImpl {
|
||||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||||
if (abilityToModify instanceof SpellAbility) {
|
if (abilityToModify instanceof SpellAbility) {
|
||||||
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
|
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
|
||||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = abilityToModify.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetUUID : target.getTargets()) {
|
for (UUID targetUUID : target.getTargets()) {
|
||||||
if (targetUUID.equals(source.getSourceId())) {
|
if (targetUUID.equals(source.getSourceId())) {
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ class ReconnaissanceRemoveFromCombatEffect extends OneShotEffect {
|
||||||
|
|
||||||
public ReconnaissanceRemoveFromCombatEffect() {
|
public ReconnaissanceRemoveFromCombatEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
this.staticText = "Remove target attacking creature from combat and untap it";
|
this.staticText = "Remove target attacking creature you control from combat and untap it";
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReconnaissanceRemoveFromCombatEffect(final ReconnaissanceRemoveFromCombatEffect effect) {
|
public ReconnaissanceRemoveFromCombatEffect(final ReconnaissanceRemoveFromCombatEffect effect) {
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,8 @@ class MonasterySiegeCostIncreaseEffect extends CostModificationEffectImpl {
|
||||||
if (new ModeChoiceSourceCondition("Dragons").apply(game, source)) {
|
if (new ModeChoiceSourceCondition("Dragons").apply(game, source)) {
|
||||||
if (abilityToModify instanceof SpellAbility) {
|
if (abilityToModify instanceof SpellAbility) {
|
||||||
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
|
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
|
||||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = abilityToModify.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetUUID : target.getTargets()) {
|
for (UUID targetUUID : target.getTargets()) {
|
||||||
if (targetUUID.equals(source.getControllerId())) {
|
if (targetUUID.equals(source.getControllerId())) {
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ class AetherbornMarauderEffect extends OneShotEffect {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Permanent sourceObject = game.getPermanent(source.getSourceId());
|
Permanent sourceObject = game.getPermanent(source.getSourceId());
|
||||||
if (controller != null && sourceObject != null) {
|
if (controller != null && sourceObject != null) {
|
||||||
FilterControlledPermanent filter = new FilterControlledPermanent("permanent you control from where you like to remove +1/+1 counters");
|
FilterControlledPermanent filter = new FilterControlledPermanent("permanent you control to remove +1/+1 counters from");
|
||||||
filter.add(new AnotherPredicate());
|
filter.add(new AnotherPredicate());
|
||||||
filter.add(new CounterPredicate(CounterType.P1P1));
|
filter.add(new CounterPredicate(CounterType.P1P1));
|
||||||
boolean firstRun = true;
|
boolean firstRun = true;
|
||||||
|
|
@ -109,16 +109,19 @@ class AetherbornMarauderEffect extends OneShotEffect {
|
||||||
if (controller.chooseUse(outcome, "Move " + (firstRun ? "any" : "more") + " +1/+1 counters from other permanents you control to " + sourceObject.getLogName() + "?", source, game)) {
|
if (controller.chooseUse(outcome, "Move " + (firstRun ? "any" : "more") + " +1/+1 counters from other permanents you control to " + sourceObject.getLogName() + "?", source, game)) {
|
||||||
firstRun = false;
|
firstRun = false;
|
||||||
TargetControlledPermanent target = new TargetControlledPermanent(filter);
|
TargetControlledPermanent target = new TargetControlledPermanent(filter);
|
||||||
Permanent fromPermanent = game.getPermanent(target.getFirstTarget());
|
target.setNotTarget(true);
|
||||||
if (fromPermanent != null) {
|
if (target.choose(Outcome.Neutral, source.getControllerId(), source.getSourceId(), game)) {
|
||||||
int numberOfCounters = fromPermanent.getCounters(game).getCount(CounterType.P1P1);
|
Permanent fromPermanent = game.getPermanent(target.getFirstTarget());
|
||||||
int numberToMove = 1;
|
if (fromPermanent != null) {
|
||||||
if (numberOfCounters > 1) {
|
int numberOfCounters = fromPermanent.getCounters(game).getCount(CounterType.P1P1);
|
||||||
numberToMove = controller.getAmount(0, numberOfCounters, "How many +1/+1 counters do you want to move?", game);
|
int numberToMove = 1;
|
||||||
}
|
if (numberOfCounters > 1) {
|
||||||
if (numberToMove > 0) {
|
numberToMove = controller.getAmount(0, numberOfCounters, "How many +1/+1 counters do you want to move?", game);
|
||||||
fromPermanent.removeCounters(CounterType.P1P1.createInstance(numberToMove), game);
|
}
|
||||||
sourceObject.addCounters(CounterType.P1P1.createInstance(numberToMove), game);
|
if (numberToMove > 0) {
|
||||||
|
fromPermanent.removeCounters(CounterType.P1P1.createInstance(numberToMove), game);
|
||||||
|
sourceObject.addCounters(CounterType.P1P1.createInstance(numberToMove), game);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,146 +1,151 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
* permitted provided that the following conditions are met:
|
* permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
* conditions and the following disclaimer.
|
* conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
* 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
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
* provided with the distribution.
|
* provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* 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
|
* 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
|
* 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
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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
|
* 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
|
* 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
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
package mage.sets.kaladesh;
|
package mage.sets.kaladesh;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AttacksTriggeredAbility;
|
import mage.abilities.common.AttacksTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.DiscardHandCost;
|
import mage.abilities.costs.common.DiscardHandCost;
|
||||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||||
import mage.abilities.costs.mana.ColoredManaCost;
|
import mage.abilities.costs.mana.ColoredManaCost;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.keyword.HasteAbility;
|
import mage.abilities.keyword.HasteAbility;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.ColoredManaSymbol;
|
import mage.constants.ColoredManaSymbol;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.ExileZone;
|
||||||
import mage.players.Player;
|
import mage.game.Game;
|
||||||
import mage.util.CardUtil;
|
import mage.players.Player;
|
||||||
|
import mage.util.CardUtil;
|
||||||
/**
|
|
||||||
*
|
/**
|
||||||
* @author emerald000
|
*
|
||||||
*/
|
* @author emerald000
|
||||||
public class BomatCourier extends CardImpl {
|
*/
|
||||||
|
public class BomatCourier extends CardImpl {
|
||||||
public BomatCourier(UUID ownerId) {
|
|
||||||
super(ownerId, 199, "Bomat Courier", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}");
|
public BomatCourier(UUID ownerId) {
|
||||||
this.expansionSetCode = "KLD";
|
super(ownerId, 199, "Bomat Courier", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}");
|
||||||
this.subtype.add("Construct");
|
this.expansionSetCode = "KLD";
|
||||||
this.power = new MageInt(1);
|
this.subtype.add("Construct");
|
||||||
this.toughness = new MageInt(1);
|
this.power = new MageInt(1);
|
||||||
|
this.toughness = new MageInt(1);
|
||||||
// Haste
|
|
||||||
this.addAbility(HasteAbility.getInstance());
|
// Haste
|
||||||
|
this.addAbility(HasteAbility.getInstance());
|
||||||
// Whenever Bomat Courier attacks, exile the top card of your library face down.
|
|
||||||
this.addAbility(new AttacksTriggeredAbility(new BomatCourierExileEffect(), false));
|
// Whenever Bomat Courier attacks, exile the top card of your library face down.
|
||||||
|
this.addAbility(new AttacksTriggeredAbility(new BomatCourierExileEffect(), false));
|
||||||
// {R}, Discard your hand, Sacrifice Bomat Courier: Put all cards exiled with Bomat Courier into their owners' hands.
|
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BomatCourierReturnEffect(), new ColoredManaCost(ColoredManaSymbol.R));
|
// {R}, Discard your hand, Sacrifice Bomat Courier: Put all cards exiled with Bomat Courier into their owners' hands.
|
||||||
ability.addCost(new DiscardHandCost());
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BomatCourierReturnEffect(), new ColoredManaCost(ColoredManaSymbol.R));
|
||||||
ability.addCost(new SacrificeSourceCost());
|
ability.addCost(new DiscardHandCost());
|
||||||
this.addAbility(ability);
|
ability.addCost(new SacrificeSourceCost());
|
||||||
}
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
public BomatCourier(final BomatCourier card) {
|
|
||||||
super(card);
|
public BomatCourier(final BomatCourier card) {
|
||||||
}
|
super(card);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public BomatCourier copy() {
|
@Override
|
||||||
return new BomatCourier(this);
|
public BomatCourier copy() {
|
||||||
}
|
return new BomatCourier(this);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
class BomatCourierExileEffect extends OneShotEffect {
|
|
||||||
|
class BomatCourierExileEffect extends OneShotEffect {
|
||||||
BomatCourierExileEffect() {
|
|
||||||
super(Outcome.Exile);
|
BomatCourierExileEffect() {
|
||||||
this.staticText = "exile the top card of your library face down";
|
super(Outcome.Exile);
|
||||||
}
|
this.staticText = "exile the top card of your library face down";
|
||||||
|
}
|
||||||
BomatCourierExileEffect(final BomatCourierExileEffect effect) {
|
|
||||||
super(effect);
|
BomatCourierExileEffect(final BomatCourierExileEffect effect) {
|
||||||
}
|
super(effect);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public BomatCourierExileEffect copy() {
|
@Override
|
||||||
return new BomatCourierExileEffect(this);
|
public BomatCourierExileEffect copy() {
|
||||||
}
|
return new BomatCourierExileEffect(this);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
@Override
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
public boolean apply(Game game, Ability source) {
|
||||||
MageObject sourceObject = source.getSourceObject(game);
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null && sourceObject != null) {
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
Card card = controller.getLibrary().getFromTop(game);
|
if (controller != null && sourceObject != null) {
|
||||||
if (card != null) {
|
Card card = controller.getLibrary().getFromTop(game);
|
||||||
UUID exileZoneId = CardUtil.getCardExileZoneId(game, source);
|
if (card != null) {
|
||||||
card.setFaceDown(true, game);
|
UUID exileZoneId = CardUtil.getCardExileZoneId(game, source);
|
||||||
controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName());
|
card.setFaceDown(true, game);
|
||||||
card.setFaceDown(true, game);
|
controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName());
|
||||||
return true;
|
card.setFaceDown(true, game);
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
class BomatCourierReturnEffect extends OneShotEffect {
|
|
||||||
|
class BomatCourierReturnEffect extends OneShotEffect {
|
||||||
BomatCourierReturnEffect() {
|
|
||||||
super(Outcome.DrawCard);
|
BomatCourierReturnEffect() {
|
||||||
this.staticText = "Put all cards exiled with {this} into their owners' hands";
|
super(Outcome.DrawCard);
|
||||||
}
|
this.staticText = "Put all cards exiled with {this} into their owners' hands";
|
||||||
|
}
|
||||||
BomatCourierReturnEffect(final BomatCourierReturnEffect effect) {
|
|
||||||
super(effect);
|
BomatCourierReturnEffect(final BomatCourierReturnEffect effect) {
|
||||||
}
|
super(effect);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public BomatCourierReturnEffect copy() {
|
@Override
|
||||||
return new BomatCourierReturnEffect(this);
|
public BomatCourierReturnEffect copy() {
|
||||||
}
|
return new BomatCourierReturnEffect(this);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
@Override
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
public boolean apply(Game game, Ability source) {
|
||||||
if (controller != null) {
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
return controller.moveCards(game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source.getSourceId(), true)), Zone.HAND, source, game);
|
if (controller != null) {
|
||||||
}
|
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source.getSourceId(), true));
|
||||||
return false;
|
if (exileZone != null) {
|
||||||
}
|
controller.moveCards(exileZone, Zone.HAND, source, game);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.AttachEffect;
|
import mage.abilities.effects.common.AttachEffect;
|
||||||
import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect;
|
import mage.abilities.effects.common.combat.CantAttackAttachedEffect;
|
||||||
import mage.abilities.keyword.EnchantAbility;
|
import mage.abilities.keyword.EnchantAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.AttachmentType;
|
import mage.constants.AttachmentType;
|
||||||
|
|
@ -81,8 +81,8 @@ public class CapturedByTheConsulate extends CardImpl {
|
||||||
Ability ability = new EnchantAbility(auraTarget.getTargetName());
|
Ability ability = new EnchantAbility(auraTarget.getTargetName());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
// Enchanted creature can't attack or block.
|
// Enchanted creature can't attack.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackBlockAttachedEffect(AttachmentType.AURA)));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackAttachedEffect(AttachmentType.AURA)));
|
||||||
|
|
||||||
// Whenever an opponent casts a spell, if it has a single target, change the target to enchanted creature if able.
|
// Whenever an opponent casts a spell, if it has a single target, change the target to enchanted creature if able.
|
||||||
this.addAbility(new CapturedByTheConsulateTriggeredAbility(Zone.BATTLEFIELD, new CapturedByTheConsulateEffect()));
|
this.addAbility(new CapturedByTheConsulateTriggeredAbility(Zone.BATTLEFIELD, new CapturedByTheConsulateEffect()));
|
||||||
|
|
@ -141,7 +141,8 @@ class CapturedByTheConsulateTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
}
|
}
|
||||||
if (stackObject != null) {
|
if (stackObject != null) {
|
||||||
int numberOfTargets = 0;
|
int numberOfTargets = 0;
|
||||||
for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||||
|
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
numberOfTargets += target.getTargets().size();
|
numberOfTargets += target.getTargets().size();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ class CombustibleGearhulkEffect extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||||
if (controller != null && sourcePermanent != null) {
|
if (controller != null && sourcePermanent != null) {
|
||||||
UUID opponentId;
|
UUID opponentId;
|
||||||
if (game.getOpponents(controller.getId()).size() == 1) {
|
if (game.getOpponents(controller.getId()).size() == 1) {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ import mage.constants.Zone;
|
||||||
import mage.filter.common.FilterControlledPermanent;
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
import mage.filter.predicate.Predicates;
|
import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
|
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -52,21 +53,21 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
*/
|
*/
|
||||||
public class EraOfInnovation extends CardImpl {
|
public class EraOfInnovation extends CardImpl {
|
||||||
|
|
||||||
private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact or creature");
|
private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact or Artificer");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT),
|
filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT),
|
||||||
new CardTypePredicate(CardType.CREATURE)));
|
new SubtypePredicate("Artificer")));
|
||||||
}
|
}
|
||||||
|
|
||||||
public EraOfInnovation(UUID ownerId) {
|
public EraOfInnovation(UUID ownerId) {
|
||||||
super(ownerId, 45, "Era of Innovation", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}");
|
super(ownerId, 45, "Era of Innovation", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}");
|
||||||
this.expansionSetCode = "KLD";
|
this.expansionSetCode = "KLD";
|
||||||
|
|
||||||
// Whenever an artifact or creature enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}.
|
// Whenever an artifact or Artificer enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}.
|
||||||
Effect effect = new DoIfCostPaid(new GetEnergyCountersControllerEffect(2), new GenericManaCost(1));
|
Effect effect = new DoIfCostPaid(new GetEnergyCountersControllerEffect(2), new GenericManaCost(1));
|
||||||
this.addAbility(new EntersBattlefieldAllTriggeredAbility(effect, filter,
|
this.addAbility(new EntersBattlefieldAllTriggeredAbility(effect, filter,
|
||||||
"Whenever an artifact or creature enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}."));
|
"Whenever an artifact or Artificer enters the battlefield under you control, you may pay {1}. If you do, you get {E}{E}."));
|
||||||
|
|
||||||
// {E}{E}{E}{E}{E}{E}, Sacrifice Era of Innovation: Draw three cards.
|
// {E}{E}{E}{E}{E}{E}, Sacrifice Era of Innovation: Draw three cards.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(3), new PayEnergyCost(6));
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(3), new PayEnergyCost(6));
|
||||||
|
|
|
||||||
|
|
@ -1,82 +1,81 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
* permitted provided that the following conditions are met:
|
* permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
* conditions and the following disclaimer.
|
* conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
* 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
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
* provided with the distribution.
|
* provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
* 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
|
* 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
|
* 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
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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
|
* 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
|
* 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
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* The views and conclusions contained in the software and documentation are those of the
|
* 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
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
* or implied, of BetaSteward_at_googlemail.com.
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
*/
|
*/
|
||||||
package mage.sets.kaladesh;
|
package mage.sets.kaladesh;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
|
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
import mage.abilities.effects.common.AttachEffect;
|
import mage.abilities.effects.common.AttachEffect;
|
||||||
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
|
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
|
||||||
import mage.abilities.keyword.EquipAbility;
|
import mage.abilities.keyword.EquipAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SetTargetPointer;
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author emerald000
|
* @author emerald000
|
||||||
*/
|
*/
|
||||||
public class InventorsGoggles extends CardImpl {
|
public class InventorsGoggles extends CardImpl {
|
||||||
|
|
||||||
public InventorsGoggles(UUID ownerId) {
|
public InventorsGoggles(UUID ownerId) {
|
||||||
super(ownerId, 218, "Inventor's Goggles", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}");
|
super(ownerId, 218, "Inventor's Goggles", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}");
|
||||||
this.expansionSetCode = "KLD";
|
this.expansionSetCode = "KLD";
|
||||||
this.subtype.add("Equipment");
|
this.subtype.add("Equipment");
|
||||||
|
|
||||||
// Equipped creature gets +1/+2.
|
// Equipped creature gets +1/+2.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 2, Duration.WhileOnBattlefield)));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 2, Duration.WhileOnBattlefield)));
|
||||||
|
|
||||||
// Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it.
|
// Whenever an Artificer enters the battlefield under your control, you may attach Inventor's Goggles to it.
|
||||||
this.addAbility(new EntersBattlefieldAllTriggeredAbility(
|
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
|
||||||
Zone.BATTLEFIELD,
|
Zone.BATTLEFIELD,
|
||||||
new AttachEffect(Outcome.BoostCreature, "attach {this} to it"),
|
new AttachEffect(Outcome.BoostCreature, "attach {this} to it"),
|
||||||
new FilterPermanent("Artificer", "Artificer"),
|
new FilterPermanent("Artificer", "Artificer"),
|
||||||
true,
|
true,
|
||||||
SetTargetPointer.PERMANENT,
|
SetTargetPointer.PERMANENT,
|
||||||
null,
|
null));
|
||||||
true));
|
|
||||||
|
// Equip {2}
|
||||||
// Equip {2}
|
this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2)));
|
||||||
this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2)));
|
}
|
||||||
}
|
|
||||||
|
public InventorsGoggles(final InventorsGoggles card) {
|
||||||
public InventorsGoggles(final InventorsGoggles card) {
|
super(card);
|
||||||
super(card);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
public InventorsGoggles copy() {
|
||||||
public InventorsGoggles copy() {
|
return new InventorsGoggles(this);
|
||||||
return new InventorsGoggles(this);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ class LostLegacyEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExi
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
|
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY);
|
||||||
Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
|
Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||||
if (targetPlayer != null) {
|
if (targetPlayer != null && cardName != null && !cardName.isEmpty()) {
|
||||||
FilterCard filter = new FilterCard();
|
FilterCard filter = new FilterCard();
|
||||||
filter.add(new NamePredicate(cardName));
|
filter.add(new NamePredicate(cardName));
|
||||||
int cardsInHandBefore = targetPlayer.getHand().count(filter, game);
|
int cardsInHandBefore = targetPlayer.getHand().count(filter, game);
|
||||||
|
|
|
||||||
|
|
@ -187,10 +187,10 @@ class MultiformWonder2Effect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent target = game.getPermanent(source.getFirstTarget());
|
Permanent sourceObject = game.getPermanent(source.getSourceId());
|
||||||
if (target != null) {
|
if (sourceObject != null) {
|
||||||
target.addPower(power);
|
sourceObject.addPower(power);
|
||||||
target.addToughness(toughness);
|
sourceObject.addToughness(toughness);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ import mage.game.Game;
|
||||||
import mage.game.events.EntersTheBattlefieldEvent;
|
import mage.game.events.EntersTheBattlefieldEvent;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.events.GameEvent.EventType;
|
import mage.game.events.GameEvent.EventType;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.events.NumberOfTriggersEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -85,15 +85,28 @@ class PanharmoniconEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checksEventType(GameEvent event, Game game) {
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
return event.getType() == EventType.ENTERS_THE_BATTLEFIELD;
|
return event.getType() == EventType.NUMBER_OF_TRIGGERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
if (event instanceof EntersTheBattlefieldEvent) {
|
if (event instanceof NumberOfTriggersEvent) {
|
||||||
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
|
NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event;
|
||||||
if (permanent != null) {
|
// Only triggers of the controller of Panharmonicon
|
||||||
return permanent.getCardType().contains(CardType.ARTIFACT) || permanent.getCardType().contains(CardType.CREATURE);
|
if (source.getControllerId().equals(event.getPlayerId())) {
|
||||||
|
GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent();
|
||||||
|
// Only EtB triggers
|
||||||
|
if (sourceEvent.getType() == EventType.ENTERS_THE_BATTLEFIELD && sourceEvent instanceof EntersTheBattlefieldEvent) {
|
||||||
|
EntersTheBattlefieldEvent entersTheBattlefieldEvent = (EntersTheBattlefieldEvent) sourceEvent;
|
||||||
|
// Only for entering artifacts or creatures
|
||||||
|
if (entersTheBattlefieldEvent.getTarget().getCardType().contains(CardType.ARTIFACT)
|
||||||
|
|| entersTheBattlefieldEvent.getTarget().getCardType().contains(CardType.CREATURE)) {
|
||||||
|
// Only for triggers of permanents
|
||||||
|
if (game.getPermanent(numberOfTriggersEvent.getSourceId()) != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -33,15 +33,18 @@ import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.PutOnLibraryTargetEffect;
|
|
||||||
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
|
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
|
||||||
import mage.abilities.mana.ColorlessManaAbility;
|
import mage.abilities.mana.ColorlessManaAbility;
|
||||||
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.common.FilterArtifactCard;
|
import mage.filter.common.FilterArtifactCard;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInYourGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -61,10 +64,7 @@ public class SequesteredStash extends CardImpl {
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveControllerEffect(5), new GenericManaCost(4));
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveControllerEffect(5), new GenericManaCost(4));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
ability.addCost(new SacrificeSourceCost());
|
ability.addCost(new SacrificeSourceCost());
|
||||||
Effect effect = new PutOnLibraryTargetEffect(true);
|
ability.addEffect(new SequesteredStashEffect());
|
||||||
effect.setText("Then you may put an artifact card from your graveyard on top of your library");
|
|
||||||
ability.addEffect(effect);
|
|
||||||
ability.addTarget(new TargetCardInYourGraveyard(new FilterArtifactCard("artifact card from your graveyard")));
|
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -78,3 +78,39 @@ public class SequesteredStash extends CardImpl {
|
||||||
return new SequesteredStash(this);
|
return new SequesteredStash(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SequesteredStashEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public SequesteredStashEffect() {
|
||||||
|
super(Outcome.Benefit);
|
||||||
|
this.staticText = "Then you may put an artifact card from your graveyard on top of your library";
|
||||||
|
}
|
||||||
|
|
||||||
|
public SequesteredStashEffect(final SequesteredStashEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SequesteredStashEffect copy() {
|
||||||
|
return new SequesteredStashEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(new FilterArtifactCard("artifact card from your graveyard"));
|
||||||
|
target.setNotTarget(true);
|
||||||
|
if (target.canChoose(source.getSourceId(), source.getControllerId(), game)
|
||||||
|
&& controller.chooseUse(outcome, "Put an artifact card from your graveyard to library?", source, game)
|
||||||
|
&& controller.choose(outcome, target, source.getSourceId(), game)) {
|
||||||
|
Card card = game.getCard(target.getFirstTarget());
|
||||||
|
if (card != null) {
|
||||||
|
controller.moveCards(card, Zone.LIBRARY, source, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -57,6 +58,7 @@ public class SparkOfCreativity extends CardImpl {
|
||||||
|
|
||||||
// Choose target creature. Exile the top card of your library. You may have Spark of Creativity deal damage to that creature equal to the converted mana cost of the exiled card. If you don't, you may play that card until end of turn.
|
// Choose target creature. Exile the top card of your library. You may have Spark of Creativity deal damage to that creature equal to the converted mana cost of the exiled card. If you don't, you may play that card until end of turn.
|
||||||
this.getSpellAbility().addEffect(new SparkOfCreativityEffect());
|
this.getSpellAbility().addEffect(new SparkOfCreativityEffect());
|
||||||
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SparkOfCreativity(final SparkOfCreativity card) {
|
public SparkOfCreativity(final SparkOfCreativity card) {
|
||||||
|
|
@ -142,9 +144,7 @@ class SparkOfCreativityPlayEffect extends AsThoughEffectImpl {
|
||||||
if (objectReference.refersTo(objectId, game) && affectedControllerId.equals(source.getControllerId())) {
|
if (objectReference.refersTo(objectId, game) && affectedControllerId.equals(source.getControllerId())) {
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
if (controller.chooseUse(outcome, "Play the exiled card?", source, game)) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
discard();
|
discard();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,11 +52,15 @@ public class SubtleStrike extends CardImpl {
|
||||||
this.getSpellAbility().getModes().setMinModes(1);
|
this.getSpellAbility().getModes().setMinModes(1);
|
||||||
this.getSpellAbility().getModes().setMaxModes(2);
|
this.getSpellAbility().getModes().setMaxModes(2);
|
||||||
// • Target creature gets -1/-1 until end of turn.
|
// • Target creature gets -1/-1 until end of turn.
|
||||||
this.getSpellAbility().addEffect(new BoostTargetEffect(-1, -1, Duration.EndOfTurn));
|
BoostTargetEffect minusOneMinusOne = new BoostTargetEffect(-1, -1, Duration.EndOfTurn);
|
||||||
|
minusOneMinusOne.setText("Target creature gets -1/-1 until end of turn");
|
||||||
|
this.getSpellAbility().addEffect(minusOneMinusOne);
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||||
// • Put a +1/+1 counter on target creature.
|
// • Put a +1/+1 counter on target creature.
|
||||||
Mode mode1 = new Mode();
|
Mode mode1 = new Mode();
|
||||||
mode1.getEffects().add(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
|
AddCountersTargetEffect plusOnePlusOneCounter = new AddCountersTargetEffect(CounterType.P1P1.createInstance());
|
||||||
|
plusOnePlusOneCounter.setText("Put a +1/+1 counter on target creature");
|
||||||
|
mode1.getEffects().add(plusOnePlusOneCounter);
|
||||||
mode1.getTargets().add(new TargetCreaturePermanent());
|
mode1.getTargets().add(new TargetCreaturePermanent());
|
||||||
this.getSpellAbility().addMode(mode1);
|
this.getSpellAbility().addMode(mode1);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ public class AltarOfTheBrood extends CardImpl {
|
||||||
|
|
||||||
// Whenever another permanent enters the battlefield under your control, each opponent puts the top card of his or her library into his or her graveyard.
|
// Whenever another permanent enters the battlefield under your control, each opponent puts the top card of his or her library into his or her graveyard.
|
||||||
this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD,
|
this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD,
|
||||||
new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.OPPONENT), filter, false));
|
new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.OPPONENT), filter, false, null, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AltarOfTheBrood(final AltarOfTheBrood card) {
|
public AltarOfTheBrood(final AltarOfTheBrood card) {
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,18 @@ package mage.sets.legions;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
|
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CreateTokenTargetEffect;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.SetTargetPointer;
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
|
import mage.game.Game;
|
||||||
import mage.game.permanent.token.SliverToken;
|
import mage.game.permanent.token.SliverToken;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -54,10 +57,8 @@ public class BroodSliver extends CardImpl {
|
||||||
this.toughness = new MageInt(3);
|
this.toughness = new MageInt(3);
|
||||||
|
|
||||||
// Whenever a Sliver deals combat damage to a player, its controller may put a 1/1 colorless Sliver creature token onto the battlefield.
|
// Whenever a Sliver deals combat damage to a player, its controller may put a 1/1 colorless Sliver creature token onto the battlefield.
|
||||||
Effect effect = new CreateTokenTargetEffect(new SliverToken());
|
this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(new BroodSliverEffect(),
|
||||||
effect.setText("its controller may put a 1/1 colorless Sliver creature token onto the battlefield");
|
new FilterCreaturePermanent("Sliver", "a Sliver"), false, SetTargetPointer.PLAYER, true));
|
||||||
this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(effect,
|
|
||||||
new FilterCreaturePermanent("Sliver", "a Sliver"), true, SetTargetPointer.PLAYER, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BroodSliver(final BroodSliver card) {
|
public BroodSliver(final BroodSliver card) {
|
||||||
|
|
@ -69,3 +70,32 @@ public class BroodSliver extends CardImpl {
|
||||||
return new BroodSliver(this);
|
return new BroodSliver(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BroodSliverEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
public BroodSliverEffect() {
|
||||||
|
super(Outcome.PutCardInPlay);
|
||||||
|
this.staticText = "its controller may put a 1/1 colorless Sliver creature token onto the battlefield";
|
||||||
|
}
|
||||||
|
|
||||||
|
public BroodSliverEffect(final BroodSliverEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BroodSliverEffect copy() {
|
||||||
|
return new BroodSliverEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player permanentController = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||||
|
if (permanentController != null) {
|
||||||
|
if (permanentController.chooseUse(outcome, "put a 1/1 colorless Sliver creature token onto the battlefield", source, game)) {
|
||||||
|
return new SliverToken().putOntoBattlefield(1, game, source.getSourceId(), permanentController.getId());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
84
Mage.Sets/src/mage/sets/lorwyn/SilvergillDouser.java
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* 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.lorwyn;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||||
|
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||||
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
|
import mage.filter.predicate.Predicates;
|
||||||
|
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Styxo
|
||||||
|
*/
|
||||||
|
public class SilvergillDouser extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Merfolk and/or Faeries you control");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(Predicates.or(new SubtypePredicate("Merfolk"), new SubtypePredicate("Faerie")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SilvergillDouser(UUID ownerId) {
|
||||||
|
super(ownerId, 87, "Silvergill Douser", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{U}");
|
||||||
|
this.expansionSetCode = "LRW";
|
||||||
|
this.subtype.add("Merfolk");
|
||||||
|
this.subtype.add("Wizard");
|
||||||
|
this.power = new MageInt(1);
|
||||||
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
|
// {tap}: Target creature gets -X/-0 until end of turn, where X is the number of Merfolk and/or Faeries you control.
|
||||||
|
DynamicValue number = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent(filter), -1);
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(number, new StaticValue(0), Duration.EndOfTurn, true), new TapSourceCost());
|
||||||
|
ability.addTarget(new TargetCreaturePermanent());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SilvergillDouser(final SilvergillDouser card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SilvergillDouser copy() {
|
||||||
|
return new SilvergillDouser(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,12 +27,9 @@
|
||||||
*/
|
*/
|
||||||
package mage.sets.magic2014;
|
package mage.sets.magic2014;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.abilities.TriggeredAbility;
|
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
|
@ -42,14 +39,11 @@ import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.Filter;
|
|
||||||
import mage.filter.FilterAbility;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.StackAbility;
|
import mage.game.stack.StackAbility;
|
||||||
import mage.game.stack.StackObject;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetObject;
|
import mage.target.common.TargetTriggeredAbility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -96,7 +90,7 @@ class StrionicResonatorEffect extends OneShotEffect {
|
||||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||||
if (controller != null && sourcePermanent != null) {
|
if (controller != null && sourcePermanent != null) {
|
||||||
stackAbility.createCopyOnStack(game, source, source.getControllerId(), true);
|
stackAbility.createCopyOnStack(game, source, source.getControllerId(), true);
|
||||||
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied activated ability").toString());
|
game.informPlayers(new StringBuilder(sourcePermanent.getName()).append(": ").append(controller.getLogName()).append(" copied triggered ability").toString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -116,76 +110,3 @@ class StrionicResonatorEffect extends OneShotEffect {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TargetTriggeredAbility extends TargetObject {
|
|
||||||
|
|
||||||
public TargetTriggeredAbility() {
|
|
||||||
this.minNumberOfTargets = 1;
|
|
||||||
this.maxNumberOfTargets = 1;
|
|
||||||
this.zone = Zone.STACK;
|
|
||||||
this.targetName = "target triggered ability you control";
|
|
||||||
}
|
|
||||||
|
|
||||||
public TargetTriggeredAbility(final TargetTriggeredAbility target) {
|
|
||||||
super(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canTarget(UUID id, Ability source, Game game) {
|
|
||||||
if (source != null && source.getSourceId().equals(id)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
StackObject stackObject = game.getStack().getStackObject(id);
|
|
||||||
return stackObject.getStackAbility() != null
|
|
||||||
&& (stackObject.getStackAbility() instanceof TriggeredAbility)
|
|
||||||
&& source != null
|
|
||||||
&& stackObject.getStackAbility().getControllerId().equals(source.getControllerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
|
|
||||||
return canChoose(sourceControllerId, game);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canChoose(UUID sourceControllerId, Game game) {
|
|
||||||
for (StackObject stackObject : game.getStack()) {
|
|
||||||
if (stackObject.getStackAbility() != null
|
|
||||||
&& stackObject.getStackAbility() instanceof TriggeredAbility
|
|
||||||
&& stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
|
|
||||||
return possibleTargets(sourceControllerId, game);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Game game) {
|
|
||||||
Set<UUID> possibleTargets = new HashSet<>();
|
|
||||||
for (StackObject stackObject : game.getStack()) {
|
|
||||||
if (stackObject.getStackAbility() != null
|
|
||||||
&& stackObject.getStackAbility() instanceof TriggeredAbility
|
|
||||||
&& stackObject.getStackAbility().getControllerId().equals(sourceControllerId)) {
|
|
||||||
possibleTargets.add(stackObject.getStackAbility().getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return possibleTargets;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TargetTriggeredAbility copy() {
|
|
||||||
return new TargetTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Filter getFilter() {
|
|
||||||
return new FilterAbility();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,8 @@ class PsychicRebuttalPredicate implements ObjectPlayerPredicate<ObjectPlayer<Sta
|
||||||
if (controllerId == null) {
|
if (controllerId == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Mode mode : input.getObject().getStackAbility().getModes().getSelectedModes()) {
|
for (UUID modeId : input.getObject().getStackAbility().getModes().getSelectedModes()) {
|
||||||
|
Mode mode = input.getObject().getStackAbility().getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetId : target.getTargets()) {
|
for (UUID targetId : target.getTargets()) {
|
||||||
if (controllerId.equals(targetId)) {
|
if (controllerId.equals(targetId)) {
|
||||||
|
|
|
||||||
|
|
@ -118,20 +118,19 @@ class FoodChainManaEffect extends ManaEffect {
|
||||||
ChoiceColor choice = new ChoiceColor();
|
ChoiceColor choice = new ChoiceColor();
|
||||||
controller.choose(Outcome.PutManaInPool, choice, game);
|
controller.choose(Outcome.PutManaInPool, choice, game);
|
||||||
ObjectColor chosenColor = choice.getColor();
|
ObjectColor chosenColor = choice.getColor();
|
||||||
|
if (chosenColor == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Mana mana = null;
|
Mana mana = null;
|
||||||
if (chosenColor.isBlack()) {
|
if (chosenColor.isBlack()) {
|
||||||
mana = new FoodChainManaBuilder().setMana(Mana.BlackMana(manaCostExiled + 1), source, game).build();
|
mana = new FoodChainManaBuilder().setMana(Mana.BlackMana(manaCostExiled + 1), source, game).build();
|
||||||
}
|
} else if (chosenColor.isBlue()) {
|
||||||
else if (chosenColor.isBlue()) {
|
|
||||||
mana = new FoodChainManaBuilder().setMana(Mana.BlueMana(manaCostExiled + 1), source, game).build();
|
mana = new FoodChainManaBuilder().setMana(Mana.BlueMana(manaCostExiled + 1), source, game).build();
|
||||||
}
|
} else if (chosenColor.isRed()) {
|
||||||
else if (chosenColor.isRed()) {
|
|
||||||
mana = new FoodChainManaBuilder().setMana(Mana.RedMana(manaCostExiled + 1), source, game).build();
|
mana = new FoodChainManaBuilder().setMana(Mana.RedMana(manaCostExiled + 1), source, game).build();
|
||||||
}
|
} else if (chosenColor.isGreen()) {
|
||||||
else if (chosenColor.isGreen()) {
|
|
||||||
mana = new FoodChainManaBuilder().setMana(Mana.GreenMana(manaCostExiled + 1), source, game).build();
|
mana = new FoodChainManaBuilder().setMana(Mana.GreenMana(manaCostExiled + 1), source, game).build();
|
||||||
}
|
} else if (chosenColor.isWhite()) {
|
||||||
else if (chosenColor.isWhite()) {
|
|
||||||
mana = new FoodChainManaBuilder().setMana(Mana.WhiteMana(manaCostExiled + 1), source, game).build();
|
mana = new FoodChainManaBuilder().setMana(Mana.WhiteMana(manaCostExiled + 1), source, game).build();
|
||||||
}
|
}
|
||||||
if (mana != null) {
|
if (mana != null) {
|
||||||
|
|
|
||||||
|
|
@ -29,18 +29,12 @@ package mage.sets.mirrodinbesieged;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
import mage.abilities.effects.common.ruleModifying.CantHaveCountersSourceEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.events.GameEvent.EventType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -58,7 +52,7 @@ public class MelirasKeepers extends CardImpl {
|
||||||
this.toughness = new MageInt(4);
|
this.toughness = new MageInt(4);
|
||||||
|
|
||||||
// Melira's Keepers can't have counters placed on it
|
// Melira's Keepers can't have counters placed on it
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MelirasKeepersEffect()));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantHaveCountersSourceEffect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MelirasKeepers(final MelirasKeepers card) {
|
public MelirasKeepers(final MelirasKeepers card) {
|
||||||
|
|
@ -71,31 +65,3 @@ public class MelirasKeepers extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MelirasKeepersEffect extends ContinuousRuleModifyingEffectImpl {
|
|
||||||
|
|
||||||
public MelirasKeepersEffect() {
|
|
||||||
super(Duration.WhileOnBattlefield, Outcome.PreventDamage);
|
|
||||||
staticText = "{this} can't have counters placed on it";
|
|
||||||
}
|
|
||||||
|
|
||||||
public MelirasKeepersEffect(final MelirasKeepersEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MelirasKeepersEffect copy() {
|
|
||||||
return new MelirasKeepersEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checksEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == EventType.ADD_COUNTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
|
||||||
return event.getTargetId().equals(source.getSourceId());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,8 @@ class ElderwoodScionCostReductionEffect extends CostModificationEffectImpl {
|
||||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||||
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) {
|
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) {
|
||||||
if (abilityToModify.getControllerId().equals(source.getControllerId())) {
|
if (abilityToModify.getControllerId().equals(source.getControllerId())) {
|
||||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = abilityToModify.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetUUID : target.getTargets()) {
|
for (UUID targetUUID : target.getTargets()) {
|
||||||
if (targetUUID.equals(source.getSourceId())) {
|
if (targetUUID.equals(source.getSourceId())) {
|
||||||
|
|
|
||||||
60
Mage.Sets/src/mage/sets/prophecy/BlessedWind.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.prophecy;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.effects.common.SetPlayerLifeTargetEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.target.TargetPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Styxo
|
||||||
|
*/
|
||||||
|
public class BlessedWind extends CardImpl {
|
||||||
|
|
||||||
|
public BlessedWind(UUID ownerId) {
|
||||||
|
super(ownerId, 4, "Blessed Wind", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{7}{W}{W}");
|
||||||
|
this.expansionSetCode = "PCY";
|
||||||
|
|
||||||
|
// Target player's life total becomes 20.
|
||||||
|
this.getSpellAbility().addEffect(new SetPlayerLifeTargetEffect(20));
|
||||||
|
this.getSpellAbility().addTarget(new TargetPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlessedWind(final BlessedWind card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlessedWind copy() {
|
||||||
|
return new BlessedWind(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ package mage.sets.ravnica;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
|
@ -41,12 +41,8 @@ import mage.constants.CardType;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.game.events.GameEvent;
|
import mage.filter.predicate.permanent.TokenPredicate;
|
||||||
import mage.game.events.GameEvent.EventType;
|
|
||||||
import mage.game.events.ZoneChangeEvent;
|
|
||||||
import mage.game.permanent.Permanent;
|
|
||||||
import mage.game.permanent.PermanentToken;
|
|
||||||
import mage.game.permanent.token.SpiritWhiteToken;
|
import mage.game.permanent.token.SpiritWhiteToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -55,6 +51,12 @@ import mage.game.permanent.token.SpiritWhiteToken;
|
||||||
*/
|
*/
|
||||||
public class TwilightDrover extends CardImpl {
|
public class TwilightDrover extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature token");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new TokenPredicate());
|
||||||
|
}
|
||||||
|
|
||||||
public TwilightDrover(UUID ownerId) {
|
public TwilightDrover(UUID ownerId) {
|
||||||
super(ownerId, 33, "Twilight Drover", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}");
|
super(ownerId, 33, "Twilight Drover", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}");
|
||||||
this.expansionSetCode = "RAV";
|
this.expansionSetCode = "RAV";
|
||||||
|
|
@ -64,8 +66,8 @@ public class TwilightDrover extends CardImpl {
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
// Whenever a creature token leaves the battlefield, put a +1/+1 counter on Twilight Drover.
|
// Whenever a creature token leaves the battlefield, put a +1/+1 counter on Twilight Drover.
|
||||||
this.addAbility(new TwilightDroverTriggeredAbility());
|
this.addAbility(new LeavesBattlefieldAllTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter));
|
||||||
|
|
||||||
// {2}{W}, Remove a +1/+1 counter from Twilight Drover: Put two 1/1 white Spirit creature tokens with flying onto the battlefield.
|
// {2}{W}, Remove a +1/+1 counter from Twilight Drover: Put two 1/1 white Spirit creature tokens with flying onto the battlefield.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SpiritWhiteToken("RAV"), 2), new ManaCostsImpl<>("{2}{W}"));
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SpiritWhiteToken("RAV"), 2), new ManaCostsImpl<>("{2}{W}"));
|
||||||
ability.addCost(new RemoveCountersSourceCost(CounterType.P1P1.createInstance()));
|
ability.addCost(new RemoveCountersSourceCost(CounterType.P1P1.createInstance()));
|
||||||
|
|
@ -81,42 +83,3 @@ public class TwilightDrover extends CardImpl {
|
||||||
return new TwilightDrover(this);
|
return new TwilightDrover(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TwilightDroverTriggeredAbility extends TriggeredAbilityImpl {
|
|
||||||
|
|
||||||
TwilightDroverTriggeredAbility() {
|
|
||||||
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TwilightDroverTriggeredAbility(final TwilightDroverTriggeredAbility ability) {
|
|
||||||
super(ability);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TwilightDroverTriggeredAbility copy() {
|
|
||||||
return new TwilightDroverTriggeredAbility(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == EventType.ZONE_CHANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
|
||||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
|
||||||
if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
|
|
||||||
UUID targetId = event.getTargetId();
|
|
||||||
Permanent permanent = game.getPermanentOrLKIBattlefield(targetId);
|
|
||||||
if (permanent != null) {
|
|
||||||
return permanent.getCardType().contains(CardType.CREATURE) && permanent instanceof PermanentToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRule() {
|
|
||||||
return "Whenever a creature token leaves the battlefield, put a +1/+1 counter on {this}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ public class LightmineField extends CardImpl {
|
||||||
super(ownerId, 32, "Lightmine Field", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
|
super(ownerId, 32, "Lightmine Field", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}");
|
||||||
this.expansionSetCode = "ROE";
|
this.expansionSetCode = "ROE";
|
||||||
|
|
||||||
|
|
||||||
// Whenever one or more creatures attack, Lightmine Field deals damage to each of those creatures equal to the number of attacking creatures.
|
// Whenever one or more creatures attack, Lightmine Field deals damage to each of those creatures equal to the number of attacking creatures.
|
||||||
this.addAbility(new LightmineFieldTriggeredAbility());
|
this.addAbility(new LightmineFieldTriggeredAbility());
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +121,7 @@ class LightmineFieldEffect extends OneShotEffect {
|
||||||
for (UUID attacker : attackers) {
|
for (UUID attacker : attackers) {
|
||||||
Permanent creature = game.getPermanent(attacker);
|
Permanent creature = game.getPermanent(attacker);
|
||||||
if (creature != null) {
|
if (creature != null) {
|
||||||
creature.damage(damage, source.getSourceId(), game, false, false);
|
creature.damage(damage, source.getSourceId(), game, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@
|
||||||
package mage.sets.scourge;
|
package mage.sets.scourge;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
|
@ -108,7 +107,8 @@ class GripOfChaosTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
}
|
}
|
||||||
if (stackObject != null) {
|
if (stackObject != null) {
|
||||||
int numberOfTargets = 0;
|
int numberOfTargets = 0;
|
||||||
for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||||
|
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
numberOfTargets += target.getTargets().size();
|
numberOfTargets += target.getTargets().size();
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +149,8 @@ class GripOfChaosEffect extends OneShotEffect {
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
StackObject stackObject = game.getStack().getStackObject(this.getTargetPointer().getFirst(game, source));
|
StackObject stackObject = game.getStack().getStackObject(this.getTargetPointer().getFirst(game, source));
|
||||||
if (stackObject != null) {
|
if (stackObject != null) {
|
||||||
for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||||
|
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
UUID oldTargetId = target.getFirstTarget();
|
UUID oldTargetId = target.getFirstTarget();
|
||||||
Set<UUID> possibleTargets = target.possibleTargets(source.getSourceId(), source.getControllerId(), game);
|
Set<UUID> possibleTargets = target.possibleTargets(source.getSourceId(), source.getControllerId(), game);
|
||||||
|
|
|
||||||
75
Mage.Sets/src/mage/sets/scourge/KrosanDrover.java
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* 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.scourge;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.Filter.ComparisonType;
|
||||||
|
import mage.filter.FilterCard;
|
||||||
|
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||||
|
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Eirkei
|
||||||
|
*/
|
||||||
|
public class KrosanDrover extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterCard filter = new FilterCard("Creature spells with converted mana cost 6 or greater");
|
||||||
|
|
||||||
|
static {
|
||||||
|
filter.add(new CardTypePredicate(CardType.CREATURE));
|
||||||
|
filter.add(new ConvertedManaCostPredicate(ComparisonType.GreaterThan, 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
public KrosanDrover(UUID ownerId) {
|
||||||
|
super(ownerId, 122, "Krosan Drover", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{G}");
|
||||||
|
this.expansionSetCode = "SCG";
|
||||||
|
this.subtype.add("Elf");
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
// Creature spells you cast with converted mana cost 6 or greater cost {2} less to cast.
|
||||||
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public KrosanDrover(final KrosanDrover card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KrosanDrover copy() {
|
||||||
|
return new KrosanDrover(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,19 +29,14 @@ package mage.sets.shadowmoor;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
import mage.abilities.effects.common.ruleModifying.CantHaveCountersSourceEffect;
|
||||||
import mage.abilities.keyword.FlyingAbility;
|
import mage.abilities.keyword.FlyingAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.events.GameEvent.EventType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -60,7 +55,7 @@ public class Tatterkite extends CardImpl {
|
||||||
this.addAbility(FlyingAbility.getInstance());
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
// Tatterkite can't have counters placed on it.
|
// Tatterkite can't have counters placed on it.
|
||||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new CantHaveCountersSourceEffect(Duration.WhileOnBattlefield)));
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantHaveCountersSourceEffect()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,34 +68,3 @@ public class Tatterkite extends CardImpl {
|
||||||
return new Tatterkite(this);
|
return new Tatterkite(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CantHaveCountersSourceEffect extends ContinuousRuleModifyingEffectImpl {
|
|
||||||
|
|
||||||
public CantHaveCountersSourceEffect(Duration duration) {
|
|
||||||
super(duration, Outcome.Detriment);
|
|
||||||
staticText = "{this} can't have counters placed on it";
|
|
||||||
}
|
|
||||||
|
|
||||||
public CantHaveCountersSourceEffect(final CantHaveCountersSourceEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CantHaveCountersSourceEffect copy() {
|
|
||||||
return new CantHaveCountersSourceEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checksEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == EventType.ADD_COUNTERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
|
||||||
UUID sourceId = source.getSourceId();
|
|
||||||
if (sourceId != null) {
|
|
||||||
return sourceId.equals(event.getTargetId());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,8 @@ class AccursedWitchSpellsCostReductionEffect extends CostModificationEffectImpl
|
||||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||||
if (abilityToModify instanceof SpellAbility) {
|
if (abilityToModify instanceof SpellAbility) {
|
||||||
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
|
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
|
||||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = abilityToModify.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetUUID : target.getTargets()) {
|
for (UUID targetUUID : target.getTargets()) {
|
||||||
Permanent permanent = game.getPermanent(targetUUID);
|
Permanent permanent = game.getPermanent(targetUUID);
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,8 @@ class InfectiousCurseCostReductionEffect extends CostModificationEffectImpl {
|
||||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||||
if (abilityToModify instanceof SpellAbility) {
|
if (abilityToModify instanceof SpellAbility) {
|
||||||
if (source.getControllerId().equals(abilityToModify.getControllerId())) {
|
if (source.getControllerId().equals(abilityToModify.getControllerId())) {
|
||||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = abilityToModify.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetUUID : target.getTargets()) {
|
for (UUID targetUUID : target.getTargets()) {
|
||||||
Permanent enchantment = game.getPermanent(source.getSourceId());
|
Permanent enchantment = game.getPermanent(source.getSourceId());
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,8 @@ class HinderingLightPredicate implements ObjectPlayerPredicate<ObjectPlayer<Stac
|
||||||
if (controllerId == null) {
|
if (controllerId == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Mode mode : input.getObject().getStackAbility().getModes().getSelectedModes()) {
|
for (UUID modeId : input.getObject().getStackAbility().getModes().getSelectedModes()) {
|
||||||
|
Mode mode = input.getObject().getStackAbility().getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetId : target.getTargets()) {
|
for (UUID targetId : target.getTargets()) {
|
||||||
if (controllerId.equals(targetId)) {
|
if (controllerId.equals(targetId)) {
|
||||||
|
|
|
||||||
120
Mage.Sets/src/mage/sets/timespiral/PsychoticEpisode.java
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* 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.MageObject;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.keyword.MadnessAbility;
|
||||||
|
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.constants.Zone;
|
||||||
|
import mage.filter.FilterCard;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.TargetCard;
|
||||||
|
import mage.target.TargetPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author anonymous
|
||||||
|
*/
|
||||||
|
public class PsychoticEpisode extends CardImpl {
|
||||||
|
|
||||||
|
public PsychoticEpisode(UUID ownerId) {
|
||||||
|
super(ownerId, 126, "Psychotic Episode", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{B}{B}");
|
||||||
|
this.expansionSetCode = "TSP";
|
||||||
|
|
||||||
|
// Target player reveals his or her hand and the top card of his or her library. You choose a card revealed this way. That player puts the chosen card on the bottom of his or her library.
|
||||||
|
this.getSpellAbility().addEffect(new PsychoticEpisodeEffect());
|
||||||
|
this.getSpellAbility().addTarget(new TargetPlayer());
|
||||||
|
// Madness {1}{B}
|
||||||
|
this.addAbility(new MadnessAbility(this, new ManaCostsImpl("{1}{B}")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PsychoticEpisode(final PsychoticEpisode card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsychoticEpisode copy() {
|
||||||
|
return new PsychoticEpisode(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PsychoticEpisodeEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
PsychoticEpisodeEffect() {
|
||||||
|
super(Outcome.Discard);
|
||||||
|
staticText = "Target player reveals his or her hand and the top card of his or her library. You choose a card revealed this way. That player puts the chosen card on the bottom of his or her library.";
|
||||||
|
}
|
||||||
|
|
||||||
|
PsychoticEpisodeEffect(final PsychoticEpisodeEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player player = game.getPlayer(targetPointer.getFirst(game, source));
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
|
if (player != null && controller != null && sourceObject != null) {
|
||||||
|
TargetCard targetCard = new TargetCard(Zone.ALL, new FilterCard());
|
||||||
|
targetCard.setRequired(true);
|
||||||
|
Cards options = player.getHand().copy();
|
||||||
|
Card topdeck = player.getLibrary().getFromTop(game);
|
||||||
|
options.add(topdeck);
|
||||||
|
controller.lookAtCards("Top of Library (Psychotic Episode)", topdeck, game);
|
||||||
|
if (controller.choose(Outcome.Discard, options, targetCard, game)) {
|
||||||
|
Card card = game.getCard(targetCard.getFirstTarget());
|
||||||
|
if (card != null) {
|
||||||
|
CardsImpl cards = new CardsImpl();
|
||||||
|
cards.add(card);
|
||||||
|
player.revealCards(sourceObject.getIdName(), cards, game);
|
||||||
|
player.putCardsOnBottomOfLibrary(cards, game, source, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsychoticEpisodeEffect copy() {
|
||||||
|
return new PsychoticEpisodeEffect(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
82
Mage.Sets/src/mage/sets/timespiral/QuilledSliver.java
Normal file
|
|
@ -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.timespiral;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.target.common.TargetAttackingOrBlockingCreature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author HanClinto
|
||||||
|
*
|
||||||
|
* A relatively straightforward merge between GemhideSliver.java and
|
||||||
|
* CrossbowInfantry.java
|
||||||
|
*/
|
||||||
|
public class QuilledSliver extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterPermanent filter = new FilterPermanent("Sliver", "All Slivers");
|
||||||
|
|
||||||
|
public QuilledSliver(UUID ownerId) {
|
||||||
|
super(ownerId, 37, "Quilled Sliver", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W}");
|
||||||
|
this.expansionSetCode = "TSP";
|
||||||
|
this.subtype.add("Sliver");
|
||||||
|
|
||||||
|
this.power = new MageInt(1);
|
||||||
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
|
// All Slivers have "{tap}: This permanent deals 1 damage to target attacking or blocking creature."
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost());
|
||||||
|
ability.addTarget(new TargetAttackingOrBlockingCreature());
|
||||||
|
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||||
|
new GainAbilityAllEffect(ability,
|
||||||
|
Duration.WhileOnBattlefield, filter,
|
||||||
|
"All Slivers have \"{T}: This permanent deals 1 damage to target attacking or blocking creature.\"")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuilledSliver(final QuilledSliver card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QuilledSliver copy() {
|
||||||
|
return new QuilledSliver(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
109
Mage.Sets/src/mage/sets/urzassaga/Curfew.java
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* 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.urzassaga;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Rarity;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.common.TargetControlledCreaturePermanent;
|
||||||
|
import mage.target.common.TargetControlledPermanent;
|
||||||
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author maxlebedev
|
||||||
|
*/
|
||||||
|
public class Curfew extends CardImpl {
|
||||||
|
|
||||||
|
public Curfew(UUID ownerId) {
|
||||||
|
super(ownerId, 68, "Curfew", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{U}");
|
||||||
|
this.expansionSetCode = "USG";
|
||||||
|
|
||||||
|
// Each player returns a creature he or she controls to its owner's hand.
|
||||||
|
this.getSpellAbility().addEffect(new CurfewEffect());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Curfew(final Curfew card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Curfew copy() {
|
||||||
|
return new Curfew(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CurfewEffect extends OneShotEffect{
|
||||||
|
|
||||||
|
public CurfewEffect() {
|
||||||
|
super(Outcome.ReturnToHand);
|
||||||
|
staticText = "Each player returns a creature he or she controls to its owner's hand";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
game.informPlayers("Each player returns a creature he or she controls to its owner's hand");
|
||||||
|
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
|
||||||
|
Player player = game.getPlayer(playerId);
|
||||||
|
if (player != null) {
|
||||||
|
TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent();
|
||||||
|
List<Permanent> liste = game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), playerId, game);
|
||||||
|
if(!liste.isEmpty()){
|
||||||
|
player.choose(Outcome.ReturnToHand, target, source.getSourceId(), game);
|
||||||
|
|
||||||
|
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||||
|
if (permanent != null) {
|
||||||
|
permanent.moveToZone(Zone.HAND, source.getSourceId(), game, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Effect copy() {
|
||||||
|
return new CurfewEffect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ class SmokestackEffect extends OneShotEffect {
|
||||||
int count = sourcePermanent.getCounters(game).getCount("Soot");
|
int count = sourcePermanent.getCounters(game).getCount("Soot");
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
int amount = Math.min(count, game.getBattlefield().countAll(new FilterControlledPermanent(), activePlayer.getId(), game));
|
int amount = Math.min(count, game.getBattlefield().countAll(new FilterControlledPermanent(), activePlayer.getId(), game));
|
||||||
Target target = new TargetControlledPermanent(amount, amount, new FilterControlledPermanent(), false);
|
Target target = new TargetControlledPermanent(amount, amount, new FilterControlledPermanent(), true);
|
||||||
//A spell or ability could have removed the only legal target this player
|
//A spell or ability could have removed the only legal target this player
|
||||||
//had, if thats the case this ability should fizzle.
|
//had, if thats the case this ability should fizzle.
|
||||||
if (target.canChoose(activePlayer.getId(), game)) {
|
if (target.canChoose(activePlayer.getId(), game)) {
|
||||||
|
|
|
||||||
|
|
@ -113,13 +113,13 @@ class TorchlingTargetPredicate implements Predicate<MageObject> {
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
int numberOfTargets = 0;
|
int numberOfTargets = 0;
|
||||||
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
|
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
|
||||||
for (Mode mode : spellAbility.getModes().getSelectedModes()) {
|
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = spellAbility.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetId : target.getTargets()) {
|
for (UUID targetId : target.getTargets()) {
|
||||||
if (!targetId.equals(sourceId)) {
|
if (!targetId.equals(sourceId)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
numberOfTargets++;
|
numberOfTargets++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,8 @@ class KaerveksTorchCostIncreaseEffect extends CostModificationEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||||
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) {
|
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) {
|
||||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = abilityToModify.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
for (UUID targetId : target.getTargets()) {
|
for (UUID targetId : target.getTargets()) {
|
||||||
if (targetId.equals(source.getSourceObject(game).getId())) {
|
if (targetId.equals(source.getSourceObject(game).getId())) {
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ class TerastodonEffect extends OneShotEffect {
|
||||||
if (destroyedPermanents.containsKey(permanent.getControllerId())) {
|
if (destroyedPermanents.containsKey(permanent.getControllerId())) {
|
||||||
numberPermanents = destroyedPermanents.get(permanent.getControllerId());
|
numberPermanents = destroyedPermanents.get(permanent.getControllerId());
|
||||||
}
|
}
|
||||||
destroyedPermanents.put(permanent.getControllerId(), numberPermanents);
|
destroyedPermanents.put(permanent.getControllerId(), numberPermanents + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,6 @@ import org.mage.test.serverside.base.CardTestPlayerBaseAI;
|
||||||
*/
|
*/
|
||||||
public class CastDestroySpellsTest extends CardTestPlayerBaseAI {
|
public class CastDestroySpellsTest extends CardTestPlayerBaseAI {
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testOrzhovCharm() {
|
public void testOrzhovCharm() {
|
||||||
// Choose one -
|
// Choose one -
|
||||||
|
|
@ -58,6 +54,8 @@ public class CastDestroySpellsTest extends CardTestPlayerBaseAI {
|
||||||
// Cycling abilities you activate cost you up to {2} less to activate.
|
// Cycling abilities you activate cost you up to {2} less to activate.
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
|
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Orzhov Charm", "Silvercoat Lion");
|
||||||
|
setModeChoice(playerA, "2");
|
||||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ public class UndyingTest extends CardTestPlayerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tatterkite is getting counters on it, i have him in a edh deck with
|
* Tatterkite is getting counters on it, I have him in a edh deck with
|
||||||
* Mikaeus, the Lunarch and when Tatterkite dies it triggers the undying and
|
* Mikaeus, the Lunarch and when Tatterkite dies it triggers the undying and
|
||||||
* he gets the +1/+1 counters
|
* he gets the +1/+1 counters
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* 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 org.mage.test.cards.modal;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class OneOrBothTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubtleStrikeFirstMode() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
// Choose one or both —
|
||||||
|
// • Target creature gets -1/-1 until end of turn.
|
||||||
|
// • Put a +1/+1 counter on target creature.
|
||||||
|
addCard(Zone.HAND, playerA, "Subtle Strike"); // Instant {1}{B}
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox");
|
||||||
|
setModeChoice(playerA, "1");
|
||||||
|
setModeChoice(playerA, null);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Silvercoat Lion", 2, 2);
|
||||||
|
assertPowerToughness(playerB, "Pillarfield Ox", 1, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubtleStrikeSecondMode() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
// Choose one or both —
|
||||||
|
// • Target creature gets -1/-1 until end of turn.
|
||||||
|
// • Put a +1/+1 counter on target creature.
|
||||||
|
addCard(Zone.HAND, playerA, "Subtle Strike"); // Instant {1}{B}
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox");
|
||||||
|
setModeChoice(playerA, "2");
|
||||||
|
setModeChoice(playerA, null);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Silvercoat Lion", 2, 2);
|
||||||
|
assertPowerToughness(playerB, "Pillarfield Ox", 3, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubtleStrikeBothModes() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
// Choose one or both —
|
||||||
|
// • Target creature gets -1/-1 until end of turn.
|
||||||
|
// • Put a +1/+1 counter on target creature.
|
||||||
|
addCard(Zone.HAND, playerA, "Subtle Strike"); // Instant {1}{B}
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox");
|
||||||
|
addTarget(playerA, "Silvercoat Lion");
|
||||||
|
setModeChoice(playerA, "1");
|
||||||
|
setModeChoice(playerA, "2");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Silvercoat Lion", 3, 3);
|
||||||
|
assertPowerToughness(playerB, "Pillarfield Ox", 1, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* 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 org.mage.test.cards.replacement;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
public class PanharmoniconTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that Panharmonicon adds EtB triggers correctly.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAddsTrigger() {
|
||||||
|
// If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||||
|
// Whenever another creature enters the battlefield, you gain 1 life.
|
||||||
|
addCard(Zone.HAND, playerA, "Soul Warden");
|
||||||
|
// When Devout Monk enters the battlefield, you gain 1 life.
|
||||||
|
addCard(Zone.HAND, playerA, "Devout Monk");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Soul Warden");
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Devout Monk"); // Life: 20 + 2*1 + 2*1 = 24
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that Panharmonicon doesn't add to opponents' triggers.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDoesntAddOpponentsTriggers() {
|
||||||
|
// If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
|
||||||
|
// Whenever another creature enters the battlefield, you gain 1 life.
|
||||||
|
addCard(Zone.HAND, playerB, "Soul Warden");
|
||||||
|
// When Devout Monk enters the battlefield, you gain 1 life.
|
||||||
|
addCard(Zone.HAND, playerB, "Devout Monk");
|
||||||
|
|
||||||
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Soul Warden");
|
||||||
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Devout Monk"); // Life: 20 + 1 + 1 = 22
|
||||||
|
|
||||||
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerB, 22);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that Panharmonicon doesn't add to lands triggers.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDoesntAddLandsTriggers() {
|
||||||
|
// If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon");
|
||||||
|
// When Radiant Fountain enters the battlefield, you gain 2 life.
|
||||||
|
addCard(Zone.HAND, playerA, "Radiant Fountain");
|
||||||
|
|
||||||
|
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Radiant Fountain"); // Life: 20 + 2 = 22
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 22);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that Panharmonicon doesn't add to non-permanents triggers.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDoesntAddNonPermanentsTriggers() {
|
||||||
|
// If an artifact or creature entering the battlefield causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Panharmonicon");
|
||||||
|
// When a Dragon enters the battlefield, you may return Bladewing's Thrall from your graveyard to the battlefield.
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Bladewing's Thrall");
|
||||||
|
// A 4/4 vanilla dragon
|
||||||
|
addCard(Zone.HAND, playerA, "Scion of Ugin");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scion of Ugin");
|
||||||
|
setChoice(playerA, "No"); // Return Bladewing's Thrall from your graveyard to the battlefield?
|
||||||
|
setChoice(playerA, "Yes"); // Should not get run since there is only one trigger.
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Bladewing's Thrall", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,20 +39,22 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
public class BrutalExpulsionTest extends CardTestPlayerBase {
|
public class BrutalExpulsionTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Brutal Expulsion targeting Gideon, Ally of Zendikar. Gideon has 3 loyalty. Brutal Expulsion resolves,
|
* Brutal Expulsion targeting Gideon, Ally of Zendikar. Gideon has 3
|
||||||
* leaves 1 loyalty. I attack Gideon for 1 with a Scion token, Gideon dies. Instead of going to graveyard,
|
* loyalty. Brutal Expulsion resolves, leaves 1 loyalty. I attack Gideon for
|
||||||
* Expulsion sends Gideon to exile. However, in game Gideon went to graveyard.
|
* 1 with a Scion token, Gideon dies. Instead of going to graveyard,
|
||||||
|
* Expulsion sends Gideon to exile. However, in game Gideon went to
|
||||||
|
* graveyard.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPlaneswalkerExile() {
|
public void testPlaneswalkerExile() {
|
||||||
// Choose one or both
|
// Choose one or both
|
||||||
// - Return target spell or creature to its owner's hand;
|
// - Return target spell or creature to its owner's hand;
|
||||||
// or Brutal Expulsion deals 2 damage to target creature or planeswalker. If that permanent would be put into a graveyard this turn, exile it instead.
|
// or Brutal Expulsion deals 2 damage to target creature or planeswalker. If that permanent would be put into a graveyard this turn, exile it instead.
|
||||||
addCard(Zone.HAND, playerA, "Brutal Expulsion");
|
addCard(Zone.HAND, playerA, "Brutal Expulsion"); // {2}{U}{R}
|
||||||
// Shock deals 2 damage to target creature or player.
|
// Shock deals 2 damage to target creature or player.
|
||||||
addCard(Zone.HAND, playerA, "Shock");
|
addCard(Zone.HAND, playerA, "Shock"); // {R}
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||||
|
|
||||||
// Planeswalker with 4 loyalty.
|
// Planeswalker with 4 loyalty.
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Gideon, Ally of Zendikar");
|
addCard(Zone.BATTLEFIELD, playerB, "Gideon, Ally of Zendikar");
|
||||||
|
|
@ -60,12 +62,12 @@ public class BrutalExpulsionTest extends CardTestPlayerBase {
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brutal Expulsion", playerB);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brutal Expulsion", playerB);
|
||||||
setModeChoice(playerA, "2");
|
setModeChoice(playerA, "2");
|
||||||
setModeChoice(playerA, null);
|
setModeChoice(playerA, null);
|
||||||
setChoice(playerA, "Yes");
|
setChoice(playerA, "Yes"); // Redirect to planeswalker
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", playerB);
|
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Shock", playerB);
|
||||||
setChoice(playerA, "Yes");
|
setChoice(playerA, "Yes"); // Redirect to planeswalker
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(1, PhaseStep.END_COMBAT);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertPermanentCount(playerB, "Gideon, Ally of Zendikar", 0);
|
assertPermanentCount(playerB, "Gideon, Ally of Zendikar", 0);
|
||||||
|
|
|
||||||
|
|
@ -15,24 +15,23 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
||||||
*/
|
*/
|
||||||
public class BroodSliverTest extends CardTestPlayerBase {
|
public class BroodSliverTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Reported bug: It lets the controller of Brood Sliver choose whether or not the token is created, instead of the attacking Sliver's controller.
|
Reported bug: It lets the controller of Brood Sliver choose whether or not the token is created, instead of the attacking Sliver's controller.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testTokenCreatedBySliverController() {
|
public void testTokenCreatedBySliverController() {
|
||||||
|
|
||||||
// Brood Sliver {4}{G} 3/3 Sliver
|
// Brood Sliver {4}{G} 3/3 Sliver
|
||||||
// Whenever a Sliver deals combat damage to a player, its controller may put a 1/1 colorless Sliver creature token onto the battlefield.
|
// Whenever a Sliver deals combat damage to a player, its controller may put a 1/1 colorless Sliver creature token onto the battlefield.
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Brood Sliver");
|
addCard(Zone.BATTLEFIELD, playerB, "Brood Sliver");
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Venom Sliver"); // 1/1 deathtouch granting sliver
|
addCard(Zone.BATTLEFIELD, playerA, "Venom Sliver"); // 1/1 deathtouch granting sliver
|
||||||
|
|
||||||
attack(1, playerA, "Venom Sliver");
|
attack(1, playerA, "Venom Sliver");
|
||||||
setChoice(playerA, "Yes"); // controller of Venom Sliver dealing damage should get the choice to create token
|
setChoice(playerA, "Yes"); // controller of Venom Sliver dealing damage should get the choice to create token
|
||||||
setChoice(playerB, "No"); // Brood Sliver controller should not be given choice in the first place
|
|
||||||
setStopAt(1, PhaseStep.END_COMBAT);
|
setStopAt(1, PhaseStep.END_COMBAT);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertLife(playerB, 19);
|
assertLife(playerB, 19);
|
||||||
assertPermanentCount(playerA, "Sliver", 1);
|
assertPermanentCount(playerA, "Sliver", 1);
|
||||||
assertPermanentCount(playerB, "Sliver", 0);
|
assertPermanentCount(playerB, "Sliver", 0);
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,8 @@ public class TestPlayer implements Player {
|
||||||
}
|
}
|
||||||
UUID modeId = ability.getModes().getModeId(modeNr);
|
UUID modeId = ability.getModes().getModeId(modeNr);
|
||||||
|
|
||||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
for (UUID currentModeId : ability.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = ability.getModes().get(currentModeId);
|
||||||
if (mode.getId().equals(modeId)) {
|
if (mode.getId().equals(modeId)) {
|
||||||
selectedMode = mode;
|
selectedMode = mode;
|
||||||
ability.getModes().setActiveMode(mode);
|
ability.getModes().setActiveMode(mode);
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,8 @@ public abstract class AbilityImpl implements Ability {
|
||||||
&& game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()), this)) {
|
&& game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()), this)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Mode mode : this.getModes().getSelectedModes()) {
|
for (UUID modeId : this.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = this.getModes().get(modeId);
|
||||||
this.getModes().setActiveMode(mode);
|
this.getModes().setActiveMode(mode);
|
||||||
//20121001 - 601.2c
|
//20121001 - 601.2c
|
||||||
// 601.2c The player announces his or her choice of an appropriate player, object, or zone for
|
// 601.2c The player announces his or her choice of an appropriate player, object, or zone for
|
||||||
|
|
@ -1060,7 +1061,8 @@ public abstract class AbilityImpl implements Ability {
|
||||||
}
|
}
|
||||||
} else if (object instanceof Spell && ((Spell) object).getSpellAbility().getModes().size() > 1) {
|
} else if (object instanceof Spell && ((Spell) object).getSpellAbility().getModes().size() > 1) {
|
||||||
Modes spellModes = ((Spell) object).getSpellAbility().getModes();
|
Modes spellModes = ((Spell) object).getSpellAbility().getModes();
|
||||||
for (Mode selectedMode : spellModes.getSelectedModes()) {
|
for (UUID selectedModeId : spellModes.getSelectedModes()) {
|
||||||
|
Mode selectedMode = spellModes.get(selectedModeId);
|
||||||
int item = 0;
|
int item = 0;
|
||||||
for (Mode mode : spellModes.values()) {
|
for (Mode mode : spellModes.values()) {
|
||||||
item++;
|
item++;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ import mage.constants.TargetController;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetOpponent;
|
import mage.target.common.TargetOpponent;
|
||||||
import mage.util.CardUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -49,8 +48,8 @@ import mage.util.CardUtil;
|
||||||
*/
|
*/
|
||||||
public class Modes extends LinkedHashMap<UUID, Mode> {
|
public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
|
|
||||||
private Mode mode; // the current mode of the selected modes
|
private Mode currentMode; // the current mode of the selected modes
|
||||||
private final ArrayList<Mode> selectedModes = new ArrayList<>();
|
private final ArrayList<UUID> selectedModes = new ArrayList<>();
|
||||||
private int minModes;
|
private int minModes;
|
||||||
private int maxModes;
|
private int maxModes;
|
||||||
private TargetController modeChooser;
|
private TargetController modeChooser;
|
||||||
|
|
@ -58,11 +57,11 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
private boolean eachModeOnlyOnce; // state if each mode can be chosen only once as long as the source object exists
|
private boolean eachModeOnlyOnce; // state if each mode can be chosen only once as long as the source object exists
|
||||||
|
|
||||||
public Modes() {
|
public Modes() {
|
||||||
this.mode = new Mode();
|
this.currentMode = new Mode();
|
||||||
this.put(mode.getId(), mode);
|
this.put(currentMode.getId(), currentMode);
|
||||||
this.minModes = 1;
|
this.minModes = 1;
|
||||||
this.maxModes = 1;
|
this.maxModes = 1;
|
||||||
this.selectedModes.add(mode);
|
this.selectedModes.add(currentMode.getId());
|
||||||
this.modeChooser = TargetController.YOU;
|
this.modeChooser = TargetController.YOU;
|
||||||
this.eachModeOnlyOnce = false;
|
this.eachModeOnlyOnce = false;
|
||||||
this.eachModeMoreThanOnce = false;
|
this.eachModeMoreThanOnce = false;
|
||||||
|
|
@ -75,23 +74,8 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
this.minModes = modes.minModes;
|
this.minModes = modes.minModes;
|
||||||
this.maxModes = modes.maxModes;
|
this.maxModes = modes.maxModes;
|
||||||
|
|
||||||
if (modes.size() == 1) {
|
this.currentMode = values().iterator().next();
|
||||||
this.mode = values().iterator().next();
|
selectedModes.addAll(modes.getSelectedModes());
|
||||||
this.selectedModes.add(mode);
|
|
||||||
} else {
|
|
||||||
// probably there is still a problem with copying modes with the same mode selected multiple times.
|
|
||||||
for (Mode selectedMode : modes.getSelectedModes()) {
|
|
||||||
Mode copiedMode = selectedMode.copy();
|
|
||||||
this.selectedModes.add(copiedMode);
|
|
||||||
if (modes.getSelectedModes().size() == 1) {
|
|
||||||
this.mode = copiedMode;
|
|
||||||
} else {
|
|
||||||
if (selectedMode.equals(modes.getMode())) {
|
|
||||||
this.mode = copiedMode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.modeChooser = modes.modeChooser;
|
this.modeChooser = modes.modeChooser;
|
||||||
this.eachModeOnlyOnce = modes.eachModeOnlyOnce;
|
this.eachModeOnlyOnce = modes.eachModeOnlyOnce;
|
||||||
this.eachModeMoreThanOnce = modes.eachModeMoreThanOnce;
|
this.eachModeMoreThanOnce = modes.eachModeMoreThanOnce;
|
||||||
|
|
@ -102,21 +86,21 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mode getMode() {
|
public Mode getMode() {
|
||||||
return mode;
|
return currentMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getModeId(int index) {
|
public UUID getModeId(int index) {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (Mode currentMode : this.values()) {
|
for (Mode mode : this.values()) {
|
||||||
idx++;
|
idx++;
|
||||||
if (idx == index) {
|
if (idx == index) {
|
||||||
return currentMode.getId();
|
return mode.getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Mode> getSelectedModes() {
|
public ArrayList<UUID> getSelectedModes() {
|
||||||
return selectedModes;
|
return selectedModes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,8 +129,8 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setActiveMode(Mode mode) {
|
public void setActiveMode(Mode mode) {
|
||||||
if (selectedModes.contains(mode)) {
|
if (selectedModes.contains(mode.getId())) {
|
||||||
this.mode = mode;
|
this.currentMode = mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,7 +159,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
for (Mode mode : this.values()) {
|
for (Mode mode : this.values()) {
|
||||||
if ((!isEachModeOnlyOnce() || onceSelectedModes == null || !onceSelectedModes.contains(mode.getId()))
|
if ((!isEachModeOnlyOnce() || onceSelectedModes == null || !onceSelectedModes.contains(mode.getId()))
|
||||||
&& mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) {
|
&& mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) {
|
||||||
this.selectedModes.add(mode.copy());
|
this.selectedModes.add(mode.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isEachModeOnlyOnce()) {
|
if (isEachModeOnlyOnce()) {
|
||||||
|
|
@ -203,7 +187,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
Player player = game.getPlayer(playerId);
|
Player player = game.getPlayer(playerId);
|
||||||
|
|
||||||
// player chooses modes manually
|
// player chooses modes manually
|
||||||
this.mode = null;
|
this.currentMode = null;
|
||||||
while (this.selectedModes.size() < this.getMaxModes()) {
|
while (this.selectedModes.size() < this.getMaxModes()) {
|
||||||
Mode choice = player.chooseMode(this, source, game);
|
Mode choice = player.chooseMode(this, source, game);
|
||||||
if (choice == null) {
|
if (choice == null) {
|
||||||
|
|
@ -212,9 +196,9 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
}
|
}
|
||||||
return this.selectedModes.size() >= this.getMinModes();
|
return this.selectedModes.size() >= this.getMinModes();
|
||||||
}
|
}
|
||||||
this.selectedModes.add(choice.copy());
|
this.selectedModes.add(choice.getId());
|
||||||
if (mode == null) {
|
if (currentMode == null) {
|
||||||
mode = choice;
|
currentMode = choice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isEachModeOnlyOnce()) {
|
if (isEachModeOnlyOnce()) {
|
||||||
|
|
@ -222,10 +206,10 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (mode == null) {
|
if (currentMode == null) {
|
||||||
this.selectedModes.clear();
|
this.selectedModes.clear();
|
||||||
Mode copiedMode = this.values().iterator().next().copy();
|
Mode copiedMode = this.values().iterator().next().copy();
|
||||||
this.selectedModes.add(copiedMode);
|
this.selectedModes.add(copiedMode.getId());
|
||||||
this.setActiveMode(copiedMode);
|
this.setActiveMode(copiedMode);
|
||||||
}
|
}
|
||||||
if (isEachModeOnlyOnce()) {
|
if (isEachModeOnlyOnce()) {
|
||||||
|
|
@ -234,27 +218,46 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAlreadySelectedModes(ArrayList<Mode> selectedModes, Ability source, Game game) {
|
/**
|
||||||
String key = getKey(source, game);
|
* Saves the already selected modes to the state value
|
||||||
Set<UUID> onceSelectedModes = (Set<UUID>) game.getState().getValue(key);
|
*
|
||||||
if (onceSelectedModes == null) {
|
* @param selectedModes
|
||||||
onceSelectedModes = new HashSet<>();
|
* @param source
|
||||||
|
* @param game
|
||||||
|
*/
|
||||||
|
private void setAlreadySelectedModes(ArrayList<UUID> selectedModes, Ability source, Game game) {
|
||||||
|
for (UUID modeId : selectedModes) {
|
||||||
|
String key = getKey(source, game, modeId);
|
||||||
|
game.getState().setValue(key, true);
|
||||||
}
|
}
|
||||||
for (Mode mode : selectedModes) {
|
|
||||||
onceSelectedModes.add(mode.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
game.getState().setValue(key, onceSelectedModes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The already once selected modes for a modal card are stored as a state value
|
||||||
|
// That's important for modal abilities with modes that can only selected once while the object stays in its zone
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private Set<UUID> getAlreadySelectedModes(Ability source, Game game) {
|
private Set<UUID> getAlreadySelectedModes(Ability source, Game game) {
|
||||||
return (Set<UUID>) game.getState().getValue(getKey(source, game));
|
Set<UUID> onceSelectedModes = new HashSet<>();
|
||||||
|
for (UUID modeId : this.keySet()) {
|
||||||
|
Object exist = game.getState().getValue(getKey(source, game, modeId));
|
||||||
|
if (exist != null) {
|
||||||
|
onceSelectedModes.add(modeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return onceSelectedModes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getKey(Ability source, Game game) {
|
// creates the key the selected modes are saved with to the state values
|
||||||
return CardUtil.getObjectZoneString("selectedModes", source.getSourceId(), game, game.getState().getZoneChangeCounter(source.getSourceId()), false);
|
private String getKey(Ability source, Game game, UUID modeId) {
|
||||||
|
return source.getSourceId().toString() + game.getState().getZoneChangeCounter(source.getSourceId()) + modeId.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all (still) available modes of the ability
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* @param game
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public List<Mode> getAvailableModes(Ability source, Game game) {
|
public List<Mode> getAvailableModes(Ability source, Game game) {
|
||||||
List<Mode> availableModes = new ArrayList<>();
|
List<Mode> availableModes = new ArrayList<>();
|
||||||
Set<UUID> nonAvailableModes;
|
Set<UUID> nonAvailableModes;
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,9 @@ public abstract class StaticAbility extends AbilityImpl {
|
||||||
if (game.getShortLivingLKI(getSourceId(), zone)) {
|
if (game.getShortLivingLKI(getSourceId(), zone)) {
|
||||||
return true; // maybe this can be a problem if effects removed the ability from the object
|
return true; // maybe this can be a problem if effects removed the ability from the object
|
||||||
}
|
}
|
||||||
|
if (game.getPermanentEntering(getSourceId()) != null && zone.equals(Zone.BATTLEFIELD)) {
|
||||||
|
return true; // abilities of permanents entering battlefield are countes as on battlefield
|
||||||
|
}
|
||||||
return super.isInUseableZone(game, source, event);
|
return super.isInUseableZone(game, source, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import mage.cards.Card;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.events.NumberOfTriggersEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
|
|
||||||
|
|
@ -124,7 +125,12 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ability.checkTrigger(event, game)) {
|
if (ability.checkTrigger(event, game)) {
|
||||||
ability.trigger(game, ability.getControllerId());
|
NumberOfTriggersEvent numberOfTriggersEvent = new NumberOfTriggersEvent(ability.getControllerId(), ability.getSourceId(), event);
|
||||||
|
if (!game.replaceEvent(numberOfTriggersEvent)) {
|
||||||
|
for (int i = 0; i < numberOfTriggersEvent.getAmount(); i++) {
|
||||||
|
ability.trigger(game, ability.getControllerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ package mage.abilities.common;
|
||||||
|
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.constants.SetTargetPointer;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.DamagedPlayerEvent;
|
import mage.game.events.DamagedPlayerEvent;
|
||||||
|
|
@ -41,7 +42,8 @@ import mage.target.targetpointer.FixedTarget;
|
||||||
*/
|
*/
|
||||||
public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbilityImpl {
|
public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
private boolean setTargetPointer;
|
protected boolean setTargetPointer;
|
||||||
|
protected String text;
|
||||||
|
|
||||||
public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional) {
|
public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional) {
|
||||||
this(effect, optional, false);
|
this(effect, optional, false);
|
||||||
|
|
@ -52,8 +54,15 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility
|
||||||
this.setTargetPointer = setTargetPointer;
|
this.setTargetPointer = setTargetPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DealsCombatDamageToAPlayerTriggeredAbility(Effect effect, boolean optional, String text, boolean setTargetPointer) {
|
||||||
|
super(Zone.BATTLEFIELD, effect, optional);
|
||||||
|
this.text = text;
|
||||||
|
this.setTargetPointer = setTargetPointer;
|
||||||
|
}
|
||||||
|
|
||||||
public DealsCombatDamageToAPlayerTriggeredAbility(final DealsCombatDamageToAPlayerTriggeredAbility ability) {
|
public DealsCombatDamageToAPlayerTriggeredAbility(final DealsCombatDamageToAPlayerTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
|
this.text = ability.text;
|
||||||
this.setTargetPointer = ability.setTargetPointer;
|
this.setTargetPointer = ability.setTargetPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,7 +93,10 @@ public class DealsCombatDamageToAPlayerTriggeredAbility extends TriggeredAbility
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "Whenever {this} deals combat damage to a player, " + super.getRule();
|
if (text == null || text.isEmpty()) {
|
||||||
|
return "Whenever {this} deals combat damage to a player, " + super.getRule();
|
||||||
|
}
|
||||||
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,12 +73,11 @@ public class DealsDamageToAPlayerAllTriggeredAbility extends TriggeredAbilityImp
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
if (!onlyCombat || ((DamagedPlayerEvent) event).isCombatDamage()) {
|
if (!onlyCombat || ((DamagedPlayerEvent) event).isCombatDamage()) {
|
||||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
controllerId = permanent.getControllerId();
|
if (filter.match(permanent, getSourceId(), getControllerId(), game)) {
|
||||||
if (filter.match(permanent, sourceId, controllerId, game)) {
|
|
||||||
if (!setTargetPointer.equals(SetTargetPointer.NONE)) {
|
if (!setTargetPointer.equals(SetTargetPointer.NONE)) {
|
||||||
for (Effect effect : this.getEffects()) {
|
for (Effect effect : this.getEffects()) {
|
||||||
effect.setValue("damage", event.getAmount());
|
effect.setValue("damage", event.getAmount());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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.abilities.common;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.events.ZoneChangeEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Styxo
|
||||||
|
*/
|
||||||
|
public class LeavesBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
|
protected FilterPermanent filter;
|
||||||
|
|
||||||
|
public LeavesBattlefieldAllTriggeredAbility(Effect effect, FilterPermanent filter) {
|
||||||
|
this(effect, filter, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LeavesBattlefieldAllTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional) {
|
||||||
|
this(Zone.BATTLEFIELD, effect, filter, optional);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LeavesBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional) {
|
||||||
|
super(zone, effect, optional);
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LeavesBattlefieldAllTriggeredAbility(final LeavesBattlefieldAllTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
filter = ability.filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LeavesBattlefieldAllTriggeredAbility copy() {
|
||||||
|
return new LeavesBattlefieldAllTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||||
|
if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
|
||||||
|
UUID targetId = event.getTargetId();
|
||||||
|
Permanent permanent = game.getPermanentOrLKIBattlefield(targetId);
|
||||||
|
if (permanent != null) {
|
||||||
|
return filter.match(permanent, getSourceId(), getControllerId(), game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return "Whenever " + filter.getMessage() + " leaves the battlefield, " + super.getRule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -51,7 +51,8 @@ public class ChangeATargetOfTargetSpellAbilityToSourceEffect extends OneShotEffe
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Mode mode : sourceAbility.getModes().getSelectedModes()) {
|
for (UUID modeId : sourceAbility.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = sourceAbility.getModes().get(modeId);
|
||||||
targets.addAll(mode.getTargets());
|
targets.addAll(mode.getTargets());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,12 +103,10 @@ public class ChangeATargetOfTargetSpellAbilityToSourceEffect extends OneShotEffe
|
||||||
}
|
}
|
||||||
if (oldTargetName != null) {
|
if (oldTargetName != null) {
|
||||||
game.informPlayers(sourceObject.getLogName() + ": Changed target of " + stackObject.getLogName() + " from " + oldTargetName + " to " + sourceObject.getLogName());
|
game.informPlayers(sourceObject.getLogName() + ": Changed target of " + stackObject.getLogName() + " from " + oldTargetName + " to " + sourceObject.getLogName());
|
||||||
|
} else if (twoTimesTarget) {
|
||||||
|
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its not valid to target it twice for " + stackObject.getLogName());
|
||||||
} else {
|
} else {
|
||||||
if (twoTimesTarget) {
|
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its no valid target for " + stackObject.getLogName());
|
||||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its not valid to target it twice for " + stackObject.getLogName());
|
|
||||||
} else {
|
|
||||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its no valid target for " + stackObject.getLogName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,10 @@ public class CopyEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
|
if (affectedObjectList.isEmpty()) {
|
||||||
|
this.discard();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Permanent permanent = affectedObjectList.get(0).getPermanent(game);
|
Permanent permanent = affectedObjectList.get(0).getPermanent(game);
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
permanent = (Permanent) game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD, source.getSourceObjectZoneChangeCounter());
|
permanent = (Permanent) game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD, source.getSourceObjectZoneChangeCounter());
|
||||||
|
|
|
||||||
|
|
@ -111,13 +111,13 @@ public class PutTopCardOfLibraryIntoGraveEachPlayerEffect extends OneShotEffect
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
switch (targetController) {
|
switch (targetController) {
|
||||||
case OPPONENT:
|
case OPPONENT:
|
||||||
sb.append("Each opponent ");
|
sb.append("each opponent ");
|
||||||
break;
|
break;
|
||||||
case ANY:
|
case ANY:
|
||||||
sb.append("Each player ");
|
sb.append("each player ");
|
||||||
break;
|
break;
|
||||||
case NOT_YOU:
|
case NOT_YOU:
|
||||||
sb.append("Each other player ");
|
sb.append("each other player ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("TargetController type not supported.");
|
throw new UnsupportedOperationException("TargetController type not supported.");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* 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.abilities.effects.common;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Styxo
|
||||||
|
*/
|
||||||
|
public class SetPlayerLifeTargetEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
protected DynamicValue amount;
|
||||||
|
|
||||||
|
public SetPlayerLifeTargetEffect(int amount) {
|
||||||
|
this(new StaticValue(amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetPlayerLifeTargetEffect(DynamicValue amount) {
|
||||||
|
super(Outcome.Neutral);
|
||||||
|
this.amount = amount;
|
||||||
|
this.staticText = setText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetPlayerLifeTargetEffect(final SetPlayerLifeTargetEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
this.amount = effect.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SetPlayerLifeTargetEffect copy() {
|
||||||
|
return new SetPlayerLifeTargetEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player player = game.getPlayer(targetPointer.getFirst(game, source));
|
||||||
|
if (player != null) {
|
||||||
|
player.setLife(amount.calculate(game, source, this), game);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String setText() {
|
||||||
|
StringBuilder sb = new StringBuilder("Target player's life total becomes ");
|
||||||
|
sb.append(amount.toString());
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.abilities.effects.common.ruleModifying;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Styxo
|
||||||
|
*/
|
||||||
|
public class CantHaveCountersSourceEffect extends ContinuousRuleModifyingEffectImpl {
|
||||||
|
|
||||||
|
public CantHaveCountersSourceEffect() {
|
||||||
|
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||||
|
staticText = "{this} can't have counters placed on it";
|
||||||
|
}
|
||||||
|
|
||||||
|
public CantHaveCountersSourceEffect(final CantHaveCountersSourceEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CantHaveCountersSourceEffect copy() {
|
||||||
|
return new CantHaveCountersSourceEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.ADD_COUNTERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
|
UUID sourceId = source.getSourceId();
|
||||||
|
if (sourceId != null) {
|
||||||
|
return sourceId.equals(event.getTargetId());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -122,7 +122,10 @@ class CrewCost extends CostImpl {
|
||||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||||
int sumPower = 0;
|
int sumPower = 0;
|
||||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) {
|
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) {
|
||||||
sumPower += permanent.getPower().getValue();
|
int powerToAdd = permanent.getPower().getValue();
|
||||||
|
if (powerToAdd > 0) {
|
||||||
|
sumPower += powerToAdd;
|
||||||
|
}
|
||||||
if (sumPower >= value) {
|
if (sumPower >= value) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
|
@ -82,7 +82,8 @@ public class HeroicAbility extends TriggeredAbilityImpl {
|
||||||
private boolean checkSpell(Spell spell, Game game) {
|
private boolean checkSpell(Spell spell, Game game) {
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
SpellAbility sa = spell.getSpellAbility();
|
SpellAbility sa = spell.getSpellAbility();
|
||||||
for (Mode mode : sa.getModes().getSelectedModes()) {
|
for (UUID modeId : sa.getModes().getSelectedModes()) {
|
||||||
|
Mode mode = sa.getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
if (!target.isNotTarget() && target.getTargets().contains(this.getSourceId())) {
|
if (!target.isNotTarget() && target.getTargets().contains(this.getSourceId())) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ package mage.cards;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.MageObjectImpl;
|
import mage.MageObjectImpl;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
|
@ -53,10 +52,8 @@ import mage.game.command.Commander;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.PermanentCard;
|
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.players.Player;
|
|
||||||
import mage.util.GameLog;
|
import mage.util.GameLog;
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.Watcher;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
@ -315,11 +312,11 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
public String getTokenSetCode() {
|
public String getTokenSetCode() {
|
||||||
return tokenSetCode;
|
return tokenSetCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTokenDescriptor() {
|
public String getTokenDescriptor() {
|
||||||
return tokenDescriptor;
|
return tokenDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Mana> getMana() {
|
public List<Mana> getMana() {
|
||||||
|
|
@ -342,22 +339,29 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
Zone fromZone = game.getState().getZone(objectId);
|
Zone fromZone = game.getState().getZone(objectId);
|
||||||
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone, appliedEffects);
|
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone, appliedEffects);
|
||||||
ZoneChangeInfo zoneChangeInfo;
|
ZoneChangeInfo zoneChangeInfo;
|
||||||
if (toZone == Zone.LIBRARY) {
|
if (null != toZone) {
|
||||||
zoneChangeInfo = new ZoneChangeInfo.Library(event, flag /* put on top */);
|
switch (toZone) {
|
||||||
} else if (toZone == Zone.BATTLEFIELD) {
|
case LIBRARY:
|
||||||
zoneChangeInfo = new ZoneChangeInfo.Battlefield(event, flag /* comes into play tapped */);
|
zoneChangeInfo = new ZoneChangeInfo.Library(event, flag /* put on top */);
|
||||||
} else {
|
break;
|
||||||
zoneChangeInfo = new ZoneChangeInfo(event);
|
case BATTLEFIELD:
|
||||||
|
zoneChangeInfo = new ZoneChangeInfo.Battlefield(event, flag /* comes into play tapped */);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
zoneChangeInfo = new ZoneChangeInfo(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ZonesHandler.moveCard(zoneChangeInfo, game);
|
||||||
}
|
}
|
||||||
return ZonesHandler.moveCard(zoneChangeInfo, game);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
|
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
|
||||||
Card mainCard = getMainCard();
|
Card mainCard = getMainCard();
|
||||||
ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK);
|
ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK);
|
||||||
ZoneChangeInfo.Stack info =
|
ZoneChangeInfo.Stack info
|
||||||
new ZoneChangeInfo.Stack(event, new Spell(this, ability.copy(), controllerId, event.getFromZone()));
|
= new ZoneChangeInfo.Stack(event, new Spell(this, ability.copy(), controllerId, event.getFromZone()));
|
||||||
return ZonesHandler.cast(info, game);
|
return ZonesHandler.cast(info, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -449,6 +453,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
} else if (game.getPlayer(ownerId).getSideboard().contains(this.getId())) {
|
} else if (game.getPlayer(ownerId).getSideboard().contains(this.getId())) {
|
||||||
game.getPlayer(ownerId).getSideboard().remove(this.getId());
|
game.getPlayer(ownerId).getSideboard().remove(this.getId());
|
||||||
removed = true;
|
removed = true;
|
||||||
|
} else if (game.getPhase() == null) {
|
||||||
|
// E.g. Commander of commander game
|
||||||
|
removed = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BATTLEFIELD: // for sacrificing permanents or putting to library
|
case BATTLEFIELD: // for sacrificing permanents or putting to library
|
||||||
|
|
@ -461,7 +468,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (removed) {
|
if (removed) {
|
||||||
game.rememberLKI(lkiObject != null ? lkiObject.getId() : objectId, fromZone, lkiObject != null ? lkiObject : this);
|
if (!fromZone.equals(Zone.OUTSIDE)) {
|
||||||
|
game.rememberLKI(lkiObject != null ? lkiObject.getId() : objectId, fromZone, lkiObject != null ? lkiObject : this);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Couldn't find card in fromZone, card=" + getIdName() + ", fromZone=" + fromZone);
|
logger.warn("Couldn't find card in fromZone, card=" + getIdName() + ", fromZone=" + fromZone);
|
||||||
}
|
}
|
||||||
|
|
@ -598,7 +607,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
returnCode = false;
|
returnCode = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(finalAmount > 0) {
|
if (finalAmount > 0) {
|
||||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERS_ADDED, objectId, getControllerOrOwner(), counter.getName(), amount));
|
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERS_ADDED, objectId, getControllerOrOwner(), counter.getName(), amount));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -656,7 +665,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
}
|
}
|
||||||
return super.getColor(game);
|
return super.getColor(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getSubtype(Game game) {
|
public List<String> getSubtype(Game game) {
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
*/
|
*/
|
||||||
package mage.filter.predicate.mageobject;
|
package mage.filter.predicate.mageobject;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.filter.predicate.Predicate;
|
import mage.filter.predicate.Predicate;
|
||||||
|
|
@ -51,7 +52,8 @@ public class NumberOfTargetsPredicate implements Predicate<MageObject> {
|
||||||
StackObject stackObject = game.getState().getStack().getStackObject(input.getId());
|
StackObject stackObject = game.getState().getStack().getStackObject(input.getId());
|
||||||
if (stackObject != null) {
|
if (stackObject != null) {
|
||||||
int numberOfTargets = 0;
|
int numberOfTargets = 0;
|
||||||
for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||||
|
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
|
||||||
for (Target target : mode.getTargets()) {
|
for (Target target : mode.getTargets()) {
|
||||||
numberOfTargets += target.getTargets().size();
|
numberOfTargets += target.getTargets().size();
|
||||||
}
|
}
|
||||||
|
|
|
||||||