diff --git a/Mage.Client/sounds/OnAddArtifact.wav b/Mage.Client/sounds/OnAddArtifact.wav index e9488ecad8..2d6295ca75 100644 Binary files a/Mage.Client/sounds/OnAddArtifact.wav and b/Mage.Client/sounds/OnAddArtifact.wav differ diff --git a/Mage.Client/sounds/OnAddPermanent.wav b/Mage.Client/sounds/OnAddPermanent.wav index ac338bf4c8..7ca048e514 100644 Binary files a/Mage.Client/sounds/OnAddPermanent.wav and b/Mage.Client/sounds/OnAddPermanent.wav differ diff --git a/Mage.Client/sounds/OnAttack.wav b/Mage.Client/sounds/OnAttack.wav index 48f3b7ac28..815db42ae6 100644 Binary files a/Mage.Client/sounds/OnAttack.wav and b/Mage.Client/sounds/OnAttack.wav differ diff --git a/Mage.Client/sounds/OnBlock.wav b/Mage.Client/sounds/OnBlock.wav index 984ab5f914..28bf3ddde5 100644 Binary files a/Mage.Client/sounds/OnBlock.wav and b/Mage.Client/sounds/OnBlock.wav differ diff --git a/Mage.Client/sounds/OnButtonCancel.wav b/Mage.Client/sounds/OnButtonCancel.wav index cb0b80dbf8..9b0c04ca6f 100644 Binary files a/Mage.Client/sounds/OnButtonCancel.wav and b/Mage.Client/sounds/OnButtonCancel.wav differ diff --git a/Mage.Client/sounds/OnButtonOk.wav b/Mage.Client/sounds/OnButtonOk.wav index 7c33054ce4..f0e09ff85b 100644 Binary files a/Mage.Client/sounds/OnButtonOk.wav and b/Mage.Client/sounds/OnButtonOk.wav differ diff --git a/Mage.Client/sounds/OnCountdown1.wav b/Mage.Client/sounds/OnCountdown1.wav index 5ab29bf462..08fbe61614 100644 Binary files a/Mage.Client/sounds/OnCountdown1.wav and b/Mage.Client/sounds/OnCountdown1.wav differ diff --git a/Mage.Client/sounds/OnDraftSelect.wav b/Mage.Client/sounds/OnDraftSelect.wav index cd8a5c09db..a7aa354a74 100644 Binary files a/Mage.Client/sounds/OnDraftSelect.wav and b/Mage.Client/sounds/OnDraftSelect.wav differ diff --git a/Mage.Client/sounds/OnDraw.wav b/Mage.Client/sounds/OnDraw.wav index 144d2009d1..a91c5ec6f4 100644 Binary files a/Mage.Client/sounds/OnDraw.wav and b/Mage.Client/sounds/OnDraw.wav differ diff --git a/Mage.Client/sounds/OnEndTurn.wav b/Mage.Client/sounds/OnEndTurn.wav index 56a6c525e2..261e7482e3 100644 Binary files a/Mage.Client/sounds/OnEndTurn.wav and b/Mage.Client/sounds/OnEndTurn.wav differ diff --git a/Mage.Client/sounds/OnGameStart.wav b/Mage.Client/sounds/OnGameStart.wav index 791a85b591..08d76fefdb 100644 Binary files a/Mage.Client/sounds/OnGameStart.wav and b/Mage.Client/sounds/OnGameStart.wav differ diff --git a/Mage.Client/sounds/OnHover.wav b/Mage.Client/sounds/OnHover.wav index fae205369b..459fd07055 100644 Binary files a/Mage.Client/sounds/OnHover.wav and b/Mage.Client/sounds/OnHover.wav differ diff --git a/Mage.Client/sounds/OnNextPage.wav b/Mage.Client/sounds/OnNextPage.wav index e109a11679..c8aae197d5 100644 Binary files a/Mage.Client/sounds/OnNextPage.wav and b/Mage.Client/sounds/OnNextPage.wav differ diff --git a/Mage.Client/sounds/OnNextPhase.wav b/Mage.Client/sounds/OnNextPhase.wav index 7d321fc19f..09cfb019ca 100644 Binary files a/Mage.Client/sounds/OnNextPhase.wav and b/Mage.Client/sounds/OnNextPhase.wav differ diff --git a/Mage.Client/sounds/OnPlayerJoined.wav b/Mage.Client/sounds/OnPlayerJoined.wav index 0182728328..98a94af751 100644 Binary files a/Mage.Client/sounds/OnPlayerJoined.wav and b/Mage.Client/sounds/OnPlayerJoined.wav differ diff --git a/Mage.Client/sounds/OnPlayerLeft.wav b/Mage.Client/sounds/OnPlayerLeft.wav index c0590e8489..13c6a54aa3 100644 Binary files a/Mage.Client/sounds/OnPlayerLeft.wav and b/Mage.Client/sounds/OnPlayerLeft.wav differ diff --git a/Mage.Client/sounds/OnPlayerLost.wav b/Mage.Client/sounds/OnPlayerLost.wav index 4fd3e50fb1..4960cf90d4 100644 Binary files a/Mage.Client/sounds/OnPlayerLost.wav and b/Mage.Client/sounds/OnPlayerLost.wav differ diff --git a/Mage.Client/sounds/OnPlayerQuit.wav b/Mage.Client/sounds/OnPlayerQuit.wav index d9b2826d1e..4d97f17e4f 100644 Binary files a/Mage.Client/sounds/OnPlayerQuit.wav and b/Mage.Client/sounds/OnPlayerQuit.wav differ diff --git a/Mage.Client/sounds/OnPlayerQuitTournament.wav b/Mage.Client/sounds/OnPlayerQuitTournament.wav index c92220b59c..8857e7980f 100644 Binary files a/Mage.Client/sounds/OnPlayerQuitTournament.wav and b/Mage.Client/sounds/OnPlayerQuitTournament.wav differ diff --git a/Mage.Client/sounds/OnPlayerSubmittedDeck.wav b/Mage.Client/sounds/OnPlayerSubmittedDeck.wav index cfa7603c0f..1e89502f8f 100644 Binary files a/Mage.Client/sounds/OnPlayerSubmittedDeck.wav and b/Mage.Client/sounds/OnPlayerSubmittedDeck.wav differ diff --git a/Mage.Client/sounds/OnPlayerWhispered.wav b/Mage.Client/sounds/OnPlayerWhispered.wav index ad26c3a9d4..7e58c8a5a1 100644 Binary files a/Mage.Client/sounds/OnPlayerWhispered.wav and b/Mage.Client/sounds/OnPlayerWhispered.wav differ diff --git a/Mage.Client/sounds/OnPlayerWon.wav b/Mage.Client/sounds/OnPlayerWon.wav index 3c9eda4625..91f00881dd 100644 Binary files a/Mage.Client/sounds/OnPlayerWon.wav and b/Mage.Client/sounds/OnPlayerWon.wav differ diff --git a/Mage.Client/sounds/OnPrevPage.wav b/Mage.Client/sounds/OnPrevPage.wav index 9cafab28a6..85b7179063 100644 Binary files a/Mage.Client/sounds/OnPrevPage.wav and b/Mage.Client/sounds/OnPrevPage.wav differ diff --git a/Mage.Client/sounds/OnSkipButton.wav b/Mage.Client/sounds/OnSkipButton.wav index 7d321fc19f..db8a44c52f 100644 Binary files a/Mage.Client/sounds/OnSkipButton.wav and b/Mage.Client/sounds/OnSkipButton.wav differ diff --git a/Mage.Client/sounds/OnSkipButtonCancel.wav b/Mage.Client/sounds/OnSkipButtonCancel.wav index cb0b80dbf8..d58aa0144a 100644 Binary files a/Mage.Client/sounds/OnSkipButtonCancel.wav and b/Mage.Client/sounds/OnSkipButtonCancel.wav differ diff --git a/Mage.Client/sounds/OnStackNew.wav b/Mage.Client/sounds/OnStackNew.wav index 4fd917b8e8..4610b5fe33 100644 Binary files a/Mage.Client/sounds/OnStackNew.wav and b/Mage.Client/sounds/OnStackNew.wav differ diff --git a/Mage.Client/sounds/OnSummon-.wav b/Mage.Client/sounds/OnSummon-.wav index 1facee015c..63e57d3df3 100644 Binary files a/Mage.Client/sounds/OnSummon-.wav and b/Mage.Client/sounds/OnSummon-.wav differ diff --git a/Mage.Client/sounds/OnSummon.wav b/Mage.Client/sounds/OnSummon.wav index f41a49e9a6..bf5bed88cc 100644 Binary files a/Mage.Client/sounds/OnSummon.wav and b/Mage.Client/sounds/OnSummon.wav differ diff --git a/Mage.Client/sounds/OnTapPermanent.wav b/Mage.Client/sounds/OnTapPermanent.wav index 7c33054ce4..8760020598 100644 Binary files a/Mage.Client/sounds/OnTapPermanent.wav and b/Mage.Client/sounds/OnTapPermanent.wav differ diff --git a/Mage.Client/sounds/OnTournamentStart.wav b/Mage.Client/sounds/OnTournamentStart.wav index a6aa47f24f..94df53fcd9 100644 Binary files a/Mage.Client/sounds/OnTournamentStart.wav and b/Mage.Client/sounds/OnTournamentStart.wav differ diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form index e35b22b89b..afaf19627e 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form @@ -82,7 +82,7 @@ - + @@ -159,7 +159,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -333,16 +333,23 @@ - + - + + + + - + + + + + @@ -357,6 +364,16 @@ + + + + + + + + + + @@ -512,7 +529,7 @@ - + @@ -1155,7 +1172,7 @@ - + @@ -1606,7 +1623,7 @@ - + @@ -1819,7 +1836,7 @@ - + diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index bd764f48ce..ec880ce8f4 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -91,6 +91,7 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER = "gameAskMoveToGraveORder"; public static final String KEY_GAME_LOG_AUTO_SAVE = "gameLogAutoSave"; + public static final String KEY_DRAFT_LOG_AUTO_SAVE = "draftLogAutoSave"; public static final String KEY_CARD_IMAGES_USE_DEFAULT = "cardImagesUseDefault"; public static final String KEY_CARD_IMAGES_PATH = "cardImagesPath"; @@ -362,6 +363,7 @@ public class PreferencesDialog extends javax.swing.JDialog { cbAskMoveToGraveOrder = new javax.swing.JCheckBox(); main_gamelog = new javax.swing.JPanel(); cbGameLogAutoSave = new javax.swing.JCheckBox(); + cbDraftLogAutoSave = new javax.swing.JCheckBox(); tabPhases = new javax.swing.JPanel(); jLabelHeadLine = new javax.swing.JLabel(); jLabelYourTurn = new javax.swing.JLabel(); @@ -643,18 +645,32 @@ public class PreferencesDialog extends javax.swing.JDialog { } }); + cbDraftLogAutoSave.setSelected(true); + cbDraftLogAutoSave.setText("Auto save draft logs (to \"../Mage.Client/gamelogs/\" directory)"); + cbDraftLogAutoSave.setToolTipText("The logs of all your games will be saved to the mentioned folder if this option is switched on."); + cbDraftLogAutoSave.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbDraftLogAutoSaveActionPerformed(evt); + } + }); + javax.swing.GroupLayout main_gamelogLayout = new javax.swing.GroupLayout(main_gamelog); main_gamelog.setLayout(main_gamelogLayout); main_gamelogLayout.setHorizontalGroup( main_gamelogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(main_gamelogLayout.createSequentialGroup() .addContainerGap() - .addComponent(cbGameLogAutoSave, javax.swing.GroupLayout.PREFERRED_SIZE, 528, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(main_gamelogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(cbGameLogAutoSave, javax.swing.GroupLayout.PREFERRED_SIZE, 528, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(cbDraftLogAutoSave, javax.swing.GroupLayout.PREFERRED_SIZE, 528, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); main_gamelogLayout.setVerticalGroup( main_gamelogLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(cbGameLogAutoSave, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(main_gamelogLayout.createSequentialGroup() + .addComponent(cbGameLogAutoSave) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbDraftLogAutoSave)) ); javax.swing.GroupLayout tabMainLayout = new javax.swing.GroupLayout(tabMain); @@ -675,7 +691,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addContainerGap() .addComponent(main_card, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(main_game, javax.swing.GroupLayout.PREFERRED_SIZE, 189, Short.MAX_VALUE) + .addComponent(main_game, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(main_gamelog, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) @@ -861,7 +877,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addComponent(checkBoxEndTurnOthers)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(phases_stopSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(13, Short.MAX_VALUE)) + .addContainerGap(45, Short.MAX_VALUE)) ); tabsPanel.addTab("Phases", tabPhases); @@ -1435,7 +1451,7 @@ public class PreferencesDialog extends javax.swing.JDialog { ); tabAvatarsLayout.setVerticalGroup( tabAvatarsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(avatarPane, javax.swing.GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE) + .addComponent(avatarPane, javax.swing.GroupLayout.DEFAULT_SIZE, 432, Short.MAX_VALUE) ); tabsPanel.addTab("Avatars", tabAvatars); @@ -1585,7 +1601,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addGroup(connection_serversLayout.createSequentialGroup() .addGroup(connection_serversLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(lblURLServerList, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(txtURLServerList, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(txtURLServerList, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel17)) ); @@ -1617,7 +1633,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addComponent(cbProxyType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(18, 18, 18) .addComponent(pnlProxySettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(54, Short.MAX_VALUE)) + .addContainerGap(90, Short.MAX_VALUE)) ); pnlProxySettings.getAccessibleContext().setAccessibleDescription(""); @@ -1681,6 +1697,7 @@ public class PreferencesDialog extends javax.swing.JDialog { save(prefs, dialog.cbConfirmEmptyManaPool, KEY_GAME_CONFIRM_EMPTY_MANA_POOL, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.cbAskMoveToGraveOrder, KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.cbGameLogAutoSave, KEY_GAME_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbDraftLogAutoSave, KEY_DRAFT_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); // Phases save(prefs, dialog.checkBoxUpkeepYou, UPKEEP_YOU); @@ -2001,6 +2018,10 @@ public class PreferencesDialog extends javax.swing.JDialog { // TODO add your handling code here: }//GEN-LAST:event_cbAskMoveToGraveOrderActionPerformed + private void cbDraftLogAutoSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbDraftLogAutoSaveActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_cbDraftLogAutoSaveActionPerformed + private void showProxySettings() { if (cbProxyType.getSelectedItem() == Connection.ProxyType.SOCKS) { this.pnlProxy.setVisible(true); @@ -2079,6 +2100,7 @@ public class PreferencesDialog extends javax.swing.JDialog { load(prefs, dialog.cbAskMoveToGraveOrder, KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true"); load(prefs, dialog.cbGameLogAutoSave, KEY_GAME_LOG_AUTO_SAVE, "true"); + load(prefs, dialog.cbDraftLogAutoSave, KEY_DRAFT_LOG_AUTO_SAVE, "true"); load(prefs, dialog.checkBoxUpkeepYou, UPKEEP_YOU, "on", "on"); load(prefs, dialog.checkBoxDrawYou, DRAW_YOU, "on", "on"); @@ -2449,6 +2471,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JCheckBox cbAskMoveToGraveOrder; private javax.swing.JCheckBox cbCheckForNewImages; private javax.swing.JCheckBox cbConfirmEmptyManaPool; + private javax.swing.JCheckBox cbDraftLogAutoSave; private javax.swing.JCheckBox cbEnableBattlefieldBGM; private javax.swing.JCheckBox cbEnableDraftSounds; private javax.swing.JCheckBox cbEnableGameSounds; diff --git a/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java b/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java index da4ea2b425..99645ecaed 100644 --- a/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java +++ b/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java @@ -41,10 +41,21 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; import java.util.HashSet; +import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.ImageIcon; import javax.swing.JComponent; @@ -53,9 +64,12 @@ import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.KeyStroke; import javax.swing.Timer; +import mage.cards.repository.CardInfo; +import mage.cards.repository.CardRepository; import mage.client.MageFrame; import mage.client.components.tray.MageTray; import mage.client.deckeditor.SortSettingDraft; +import mage.client.dialog.PreferencesDialog; import mage.client.plugins.impl.Plugins; import mage.client.util.CardsViewUtil; import mage.client.util.Event; @@ -94,6 +108,19 @@ public class DraftPanel extends javax.swing.JPanel { // id of card with popup menu protected UUID cardIdPopupMenu; + // Filename for the draft log (only updated if writing the log). + private String logFilename; + + // Number of the current booster (for draft log writing). + private int packNo; + + // Number of the current card pick (for draft log writing). + private int pickNo; + + // Cached booster data to be written into the log (see logLastPick). + private String currentBoosterHeader; + private String[] currentBooster; + private static final CardsView emptyView = new CardsView(); /** Creates new form DraftPanel */ @@ -149,6 +176,20 @@ public class DraftPanel extends javax.swing.JPanel { if (!session.joinDraft(draftId)) { hideDraft(); } + + if (isLogging()) { + // If we are logging the draft create a file that will contain + // the log. + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); + logFilename = "Draft_" + sdf.format(new Date()) + "_" + draftId + ".txt"; + try { + Files.write(pathToDraftLog(), "".getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + } catch (IOException ex) { + Logger.getLogger(DraftPanel.class.getName()).log(Level.SEVERE, null, ex); + } + } else { + logFilename = null; + } } public void updateDraft(DraftView draftView) { @@ -167,6 +208,9 @@ public class DraftPanel extends javax.swing.JPanel { this.chkPack3.setSelected(draftView.getBoosterNum() > 2); this.txtCardNo.setText(Integer.toString(draftView.getCardNum())); + packNo = draftView.getBoosterNum(); + pickNo = draftView.getCardNum(); + int right = draftView.getPlayers().size() / 2; int left = draftView.getPlayers().size() - right; int height = left * 18; @@ -247,6 +291,7 @@ public class DraftPanel extends javax.swing.JPanel { } public void loadBooster(DraftPickView draftPickView) { + logLastPick(draftPickView); // upper area that shows the picks loadCardsToPickedCardsArea(draftPickView.getPicks()); @@ -413,6 +458,94 @@ public class DraftPanel extends javax.swing.JPanel { draftPicks.loadCards(CardsViewUtil.convertSimple(pickedCardsShown), bigCard, null); } + // Log the last card picked into the draft log together with booster + // contents. + // We don't get any event when the card is selected due to timeout + // that's why instead of proactively logging our pick we instead + // log *last* pick from the list of picks. + // To make this possible we cache the list of cards from the + // previous booster and it's sequence number (pack number / pick number) + // in fields currentBooster and currentBoosterHeader. + private void logLastPick(DraftPickView pickView) { + if (!isLogging()) { + return; + } + if (currentBooster != null) { + String lastPick = getCardName(getLastPick(pickView.getPicks().values())); + if (lastPick != null) { + logPick(lastPick); + } + currentBooster = null; + } + setCurrentBoosterForLog(pickView.getBooster()); + if (currentBooster.length == 1) { + logPick(currentBooster[0]); + } + } + + private static boolean isLogging() { + String autoSave = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_DRAFT_LOG_AUTO_SAVE, "true"); + return autoSave.equals("true"); + } + + private void setCurrentBoosterForLog(SimpleCardsView booster) { + LinkedList cards = new LinkedList<>(); + for (SimpleCardView simple: booster.values()) { + String cardName = getCardName(simple); + if (cardName != null) { + cards.add(cardName); + } + } + + currentBoosterHeader = "Pack " + packNo + " pick " + pickNo + ":\n"; + currentBooster = cards.toArray(new String[cards.size()]); + } + + private void logPick(String pick) { + StringBuilder b = new StringBuilder(); + b.append(currentBoosterHeader); + for (String name : currentBooster) { + b.append(pick.equals(name) ? "--> " : " "); + b.append(name); + b.append('\n'); + } + b.append('\n'); + appendToDraftLog(b.toString()); + } + + private Path pathToDraftLog() { + File saveDir = new File("gamelogs"); + if(!saveDir.exists()) { + saveDir.mkdirs(); + } + return new File(saveDir, logFilename).toPath(); + } + + private void appendToDraftLog(String data) { + try { + Files.write(pathToDraftLog(), data.getBytes(), StandardOpenOption.APPEND); + } catch (IOException ex) { + Logger.getLogger(DraftPanel.class.getName()).log(Level.SEVERE, null, ex); + } + } + + private static SimpleCardView getLastPick(Collection picks) { + SimpleCardView last = null; + for (SimpleCardView pick : picks) { + last = pick; + } + return last; + } + + private static String getCardName(SimpleCardView card) { + if (card == null) { + return null; + } + CardInfo cardInfo = CardRepository.instance.findCard(card.getExpansionSetCode(), card.getCardNumber()); + return cardInfo != null ? cardInfo.getName() : null; + } + + /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is diff --git a/Mage.Sets/src/mage/sets/dissension/ShieldingPlax.java b/Mage.Sets/src/mage/sets/dissension/ShieldingPlax.java index 3d42a62d49..f2367a6c85 100644 --- a/Mage.Sets/src/mage/sets/dissension/ShieldingPlax.java +++ b/Mage.Sets/src/mage/sets/dissension/ShieldingPlax.java @@ -43,8 +43,8 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; +import mage.filter.FilterObject; import mage.filter.FilterStackObject; -import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -54,12 +54,8 @@ import mage.target.common.TargetCreaturePermanent; */ public class ShieldingPlax extends CardImpl { - private static final FilterStackObject filter = new FilterStackObject("spells or abilities your opponents control"); + private static final FilterObject filter = new FilterStackObject("spells or abilities your opponents control"); - static { - filter.add(new ControllerPredicate(TargetController.OPPONENT)); - } - public ShieldingPlax(UUID ownerId) { super(ownerId, 147, "Shielding Plax", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{G/U}"); this.expansionSetCode = "DIS"; @@ -71,12 +67,13 @@ public class ShieldingPlax extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - + // When Shielding Plax enters the battlefield, draw a card. this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1))); - + // Enchanted creature can't be the target of spells or abilities your opponents control. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeTargetedAttachedEffect(filter, Duration.WhileOnBattlefield, AttachmentType.AURA))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new CantBeTargetedAttachedEffect(filter, Duration.WhileOnBattlefield, AttachmentType.AURA, TargetController.OPPONENT))); } public ShieldingPlax(final ShieldingPlax card) { diff --git a/Mage.Sets/src/mage/sets/exodus/SonicBurst.java b/Mage.Sets/src/mage/sets/exodus/SonicBurst.java new file mode 100644 index 0000000000..83af8608c9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/exodus/SonicBurst.java @@ -0,0 +1,63 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.exodus; + +import java.util.UUID; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author markedagain + */ +public class SonicBurst extends CardImpl { + + public SonicBurst(UUID ownerId) { + super(ownerId, 103, "Sonic Burst", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{R}"); + this.expansionSetCode = "EXO"; + + // As an additional cost to cast Sonic Burst, discard a card at random. + this.getSpellAbility().addCost(new DiscardCardCost(true)); + // Sonic Burst deals 4 damage to target creature or player. + this.getSpellAbility().addEffect(new DamageTargetEffect(4)); + this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); + } + + public SonicBurst(final SonicBurst card) { + super(card); + } + + @Override + public SonicBurst copy() { + return new SonicBurst(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/Deathgrip.java b/Mage.Sets/src/mage/sets/fifthedition/Deathgrip.java new file mode 100644 index 0000000000..1987935456 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/Deathgrip.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fifthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Deathgrip extends mage.sets.limitedbeta.Deathgrip { + + public Deathgrip(UUID ownerId) { + super(ownerId); + this.cardNumber = 16; + this.expansionSetCode = "5ED"; + } + + public Deathgrip(final Deathgrip card) { + super(card); + } + + @Override + public Deathgrip copy() { + return new Deathgrip(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fourthedition/Deathgrip.java b/Mage.Sets/src/mage/sets/fourthedition/Deathgrip.java new file mode 100644 index 0000000000..a99ff56436 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/Deathgrip.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fourthedition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Deathgrip extends mage.sets.limitedbeta.Deathgrip { + + public Deathgrip(UUID ownerId) { + super(ownerId); + this.cardNumber = 14; + this.expansionSetCode = "4ED"; + } + + public Deathgrip(final Deathgrip card) { + super(card); + } + + @Override + public Deathgrip copy() { + return new Deathgrip(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/SoultetherGolem.java b/Mage.Sets/src/mage/sets/futuresight/SoultetherGolem.java index ca9d9e48c6..5fb3ab962c 100644 --- a/Mage.Sets/src/mage/sets/futuresight/SoultetherGolem.java +++ b/Mage.Sets/src/mage/sets/futuresight/SoultetherGolem.java @@ -29,6 +29,7 @@ package mage.sets.futuresight; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -49,7 +50,7 @@ import mage.filter.predicate.permanent.ControllerPredicate; * @author fireshoes */ public class SoultetherGolem extends CardImpl { - + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); static { @@ -65,10 +66,12 @@ public class SoultetherGolem extends CardImpl { this.toughness = new MageInt(3); // Vanishing 1 - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(1)))); + Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(1))); + ability.setRuleVisible(false); + this.addAbility(ability); this.addAbility(new VanishingUpkeepAbility(1)); this.addAbility(new VanishingSacrificeAbility()); - + // Whenever another creature enters the battlefield under your control, put a time counter on Soultether Golem. this.addAbility(new EntersBattlefieldAllTriggeredAbility( Zone.BATTLEFIELD, diff --git a/Mage.Sets/src/mage/sets/iceage/ForgottenLore.java b/Mage.Sets/src/mage/sets/iceage/ForgottenLore.java new file mode 100644 index 0000000000..48aeebbb97 --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/ForgottenLore.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.iceage; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class ForgottenLore extends mage.sets.masterseditionii.ForgottenLore { + + public ForgottenLore(UUID ownerId) { + super(ownerId); + this.cardNumber = 125; + this.expansionSetCode = "ICE"; + } + + public ForgottenLore(final ForgottenLore card) { + super(card); + } + + @Override + public ForgottenLore copy() { + return new ForgottenLore(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Deathgrip.java b/Mage.Sets/src/mage/sets/limitedalpha/Deathgrip.java new file mode 100644 index 0000000000..021a7712be --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedalpha/Deathgrip.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.limitedalpha; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Deathgrip extends mage.sets.limitedbeta.Deathgrip { + + public Deathgrip(UUID ownerId) { + super(ownerId); + this.cardNumber = 9; + this.expansionSetCode = "LEA"; + } + + public Deathgrip(final Deathgrip card) { + super(card); + } + + @Override + public Deathgrip copy() { + return new Deathgrip(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedbeta/Deathgrip.java b/Mage.Sets/src/mage/sets/limitedbeta/Deathgrip.java new file mode 100644 index 0000000000..7d7bb2a9ce --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedbeta/Deathgrip.java @@ -0,0 +1,67 @@ +/* + * 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.limitedbeta; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetSpell; + +/** + * + * @author markedagain + */ +public class Deathgrip extends CardImpl { + private static final FilterSpell filter = new FilterSpell("green spell"); + static{ + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + + public Deathgrip(UUID ownerId) { + super(ownerId, 9, "Deathgrip", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{B}{B}"); + this.expansionSetCode = "LEB"; + + // {B}{B}: Counter target green spell. + this.getSpellAbility().addEffect(new CounterTargetEffect()); + this.getSpellAbility().addTarget(new TargetSpell(filter)); + } + + public Deathgrip(final Deathgrip card) { + super(card); + } + + @Override + public Deathgrip copy() { + return new Deathgrip(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magic2011/GaeasRevenge.java b/Mage.Sets/src/mage/sets/magic2011/GaeasRevenge.java index d09fae3189..1c174e38e8 100644 --- a/Mage.Sets/src/mage/sets/magic2011/GaeasRevenge.java +++ b/Mage.Sets/src/mage/sets/magic2011/GaeasRevenge.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,19 +20,14 @@ * 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.magic2011; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.SimpleStaticAbility; @@ -40,6 +35,11 @@ import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.CantBeTargetedSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterObject; import mage.filter.FilterStackObject; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; @@ -50,7 +50,7 @@ import mage.filter.predicate.mageobject.ColorPredicate; */ public class GaeasRevenge extends CardImpl { - private static final FilterStackObject filter = new FilterStackObject("nongreen spells or abilities from nongreen sources"); + private static final FilterObject filter = new FilterStackObject("nongreen spells or abilities from nongreen sources"); static { filter.add(Predicates.not(new ColorPredicate(ObjectColor.GREEN))); diff --git a/Mage.Sets/src/mage/sets/masterseditionii/ForgottenLore.java b/Mage.Sets/src/mage/sets/masterseditionii/ForgottenLore.java new file mode 100644 index 0000000000..3fc2f88f87 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/ForgottenLore.java @@ -0,0 +1,140 @@ +/* + * 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.masterseditionii; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +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.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.predicate.other.OwnerIdPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetOpponent; +/** + * + * @author LoneFox + */ +public class ForgottenLore extends CardImpl { + + public ForgottenLore(UUID ownerId) { + super(ownerId, 164, "Forgotten Lore", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{G}"); + this.expansionSetCode = "ME2"; + + // Target opponent chooses a card in your graveyard. You may pay {G}. If you do, repeat this process except that opponent can't choose a card already chosen for Forgotten Lore. Then put the last chosen card into your hand. + this.getSpellAbility().addEffect(new ForgottenLoreEffect()); + this.getSpellAbility().addTarget(new TargetOpponent()); + } + + public ForgottenLore(final ForgottenLore card) { + super(card); + } + + @Override + public ForgottenLore copy() { + return new ForgottenLore(this); + } +} + +class ForgottenLoreEffect extends OneShotEffect { + + public ForgottenLoreEffect() { + super(Outcome.Benefit); + staticText = "Target opponent chooses a card in your graveyard. You may pay {G}. If you do, repeat this process except that opponent can't choose a card already chosen for {this}. Then put the last chosen card into your hand."; + } + + public ForgottenLoreEffect(final ForgottenLoreEffect effect) { + super(effect); + } + + @Override + public ForgottenLoreEffect copy() { + return new ForgottenLoreEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player you = game.getPlayer(source.getControllerId()); + Player opponent = game.getPlayer(targetPointer.getFirst(game, source)); + if(you != null && opponent != null) + { + FilterCard filter = new FilterCard(); + filter.add(new OwnerIdPredicate(you.getId())); + Cost cost = new ManaCostsImpl("{G}"); + TargetCardInGraveyard chosenCard; + Card card = null; + boolean done = false; + do { + chosenCard = new TargetCardInGraveyard(filter); + chosenCard.setNotTarget(true); + if(chosenCard.canChoose(opponent.getId(), game)) { + opponent.chooseTarget(Outcome.ReturnToHand, chosenCard, source, game); + card = game.getCard(chosenCard.getFirstTarget()); + filter.add(Predicates.not(new CardIdPredicate(card.getId()))); + game.informPlayers("Forgotten Lore: " + opponent.getLogName() + " has chosen " + card.getLogName()); + } + else { + done = true; + } + + if(!done) { + if(cost.canPay(source, source.getSourceId(), you.getId(), game) && you.chooseUse(Outcome.Benefit, "Pay {G} to choose a different card ?", source, game)) { + cost.clearPaid(); + if(!cost.pay(source, game, source.getSourceId(), you.getId(), false)) { + done = true; + } + } + else { + done = true; + } + } + + } while(!done); + + if(card != null) { + Cards cardsToHand = new CardsImpl(); + cardsToHand.add(card); + you.moveCards(cardsToHand, Zone.GRAVEYARD, Zone.HAND, source, game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniv/Deathgrip.java b/Mage.Sets/src/mage/sets/masterseditioniv/Deathgrip.java new file mode 100644 index 0000000000..e5d9b196a8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniv/Deathgrip.java @@ -0,0 +1,54 @@ +/* + * 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.masterseditioniv; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author anonymous + */ +public class Deathgrip extends mage.sets.limitedbeta.Deathgrip { + + public Deathgrip(UUID ownerId) { + super(ownerId); + this.cardNumber = 75; + this.expansionSetCode = "ME4"; + this.rarity = Rarity.RARE; + } + + public Deathgrip(final Deathgrip card) { + super(card); + } + + @Override + public Deathgrip copy() { + return new Deathgrip(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/HammerOfBogardan.java b/Mage.Sets/src/mage/sets/mirage/HammerOfBogardan.java index 43bce3d67f..fc95438330 100644 --- a/Mage.Sets/src/mage/sets/mirage/HammerOfBogardan.java +++ b/Mage.Sets/src/mage/sets/mirage/HammerOfBogardan.java @@ -29,15 +29,15 @@ package mage.sets.mirage; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.PhaseStep; +import mage.constants.Rarity; import mage.constants.Zone; import mage.target.common.TargetCreatureOrPlayer; @@ -58,8 +58,8 @@ public class HammerOfBogardan extends CardImpl { this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); // {2}{R}{R}{R}: Return Hammer of Bogardan from your graveyard to your hand. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToHandEffect(), new ManaCostsImpl("{2}{R}{R}{R}"), new IsStepCondition(PhaseStep.END_COMBAT), null)); + this.addAbility(new ConditionalActivatedAbility(Zone.GRAVEYARD, + new ReturnSourceFromGraveyardToHandEffect(), new ManaCostsImpl("{2}{R}{R}{R}"), new IsStepCondition(PhaseStep.UPKEEP), null)); } public HammerOfBogardan(final HammerOfBogardan card) { diff --git a/Mage.Sets/src/mage/sets/mirage/SkulkingGhost.java b/Mage.Sets/src/mage/sets/mirage/SkulkingGhost.java new file mode 100644 index 0000000000..e6c6792251 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirage/SkulkingGhost.java @@ -0,0 +1,66 @@ +/* + * 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.mirage; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesTargetTriggeredAbility; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class SkulkingGhost extends CardImpl { + + public SkulkingGhost(UUID ownerId) { + super(ownerId, 41, "Skulking Ghost", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.expansionSetCode = "MIR"; + this.subtype.add("Spirit"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // When Skulking Ghost becomes the target of a spell or ability, sacrifice it. + this.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); + } + + public SkulkingGhost(final SkulkingGhost card) { + super(card); + } + + @Override + public SkulkingGhost copy() { + return new SkulkingGhost(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/Thirst.java b/Mage.Sets/src/mage/sets/mirage/Thirst.java new file mode 100644 index 0000000000..db2df103b7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirage/Thirst.java @@ -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.mirage; + +import java.util.UUID; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect; +import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; +import mage.abilities.effects.common.TapEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class Thirst extends CardImpl { + + public Thirst(UUID ownerId) { + super(ownerId, 104, "Thirst", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + this.expansionSetCode = "MIR"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + // When Thirst enters the battlefield, tap enchanted creature. + this.addAbility(new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect())); + // Enchanted creature doesn't untap during its controller's untap step. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepEnchantedEffect())); + // At the beginning of your upkeep, sacrifice Thirst unless you pay {U}. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{U}")), + TargetController.YOU, false)); + } + + public Thirst(final Thirst card) { + super(card); + } + + @Override + public Thirst copy() { + return new Thirst(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/WitheringBoon.java b/Mage.Sets/src/mage/sets/mirage/WitheringBoon.java new file mode 100644 index 0000000000..60bf5a1f63 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirage/WitheringBoon.java @@ -0,0 +1,69 @@ +/* + * 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.mirage; + +import java.util.UUID; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetSpell; + +/** + * + * @author markedagain + */ +public class WitheringBoon extends CardImpl { + private static final FilterSpell filter = new FilterSpell("creature spell"); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + } + public WitheringBoon(UUID ownerId) { + super(ownerId, 50, "Withering Boon", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{B}"); + this.expansionSetCode = "MIR"; + + // As an additional cost to cast Withering Boon, pay 3 life. + this.getSpellAbility().addCost(new PayLifeCost(3)); + // Counter target creature spell. + this.getSpellAbility().addEffect(new CounterTargetEffect()); + this.getSpellAbility().addTarget(new TargetSpell(filter)); + } + + public WitheringBoon(final WitheringBoon card) { + super(card); + } + + @Override + public WitheringBoon copy() { + return new WitheringBoon(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodin/JinxedChoker.java b/Mage.Sets/src/mage/sets/mirrodin/JinxedChoker.java new file mode 100644 index 0000000000..9ce1f78d59 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirrodin/JinxedChoker.java @@ -0,0 +1,180 @@ +/* + * 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.mirrodin; + +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; +import mage.abilities.common.OnEventTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.cards.CardImpl; +import mage.constants.*; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +import java.lang.Override; +import java.util.UUID; + +/** + * + * @author andyfries + */ + +public class JinxedChoker extends CardImpl { + + public JinxedChoker(UUID ownerId) { + super(ownerId, 189, "Jinxed Choker", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{3}"); + this.expansionSetCode = "MRD"; + + // At the beginning of your end step, target opponent gains control of Jinxed Choker and puts a charge counter on it. + Ability endStepAbility = new BeginningOfYourEndStepTriggeredAbility(new JinxedChokerChangeControllerEffect(), false); + endStepAbility.addTarget(new TargetOpponent()); + + AddCountersSourceEffect addCountersSourceEffect = new AddCountersSourceEffect(CounterType.CHARGE.createInstance()); + addCountersSourceEffect.setText(""); + endStepAbility.addEffect(addCountersSourceEffect); + this.addAbility(endStepAbility); + + // At the beginning of your upkeep, Jinxed Choker deals damage to you equal to the number of charge counters on it. + Ability upkeepAbility = new OnEventTriggeredAbility(GameEvent.EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new DamageControllerEffect(new JinxedChokerDynamicValue()), false); + this.addAbility(upkeepAbility); + + // {3}: Put a charge counter on Jinxed Choker or remove one from it. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new JinxedChokerCounterEffect(), new ManaCostsImpl("{3}")); + this.addAbility(ability); + } + + public JinxedChoker(final JinxedChoker card) { + super(card); + } + + @Override + public JinxedChoker copy() { + return new JinxedChoker(this); + } +} + +class JinxedChokerChangeControllerEffect extends ContinuousEffectImpl { + + public JinxedChokerChangeControllerEffect() { + super(Duration.Custom, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); + staticText = "target opponent gains control of {this} and puts a charge counter on it"; + } + + public JinxedChokerChangeControllerEffect(final JinxedChokerChangeControllerEffect effect) { + super(effect); + } + + @Override + public JinxedChokerChangeControllerEffect copy() { + return new JinxedChokerChangeControllerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = (Permanent) source.getSourceObjectIfItStillExists(game); + if (permanent != null) { + return permanent.changeControllerId(source.getFirstTarget(), game); + } else { + discard(); + } + return false; + } + +} + +class JinxedChokerDynamicValue implements DynamicValue { + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + Permanent permanent = game.getPermanent(sourceAbility.getSourceId()); + + int count = 0; + if (permanent != null){ + count = permanent.getCounters().getCount(CounterType.CHARGE); + } + return count; + } + + @Override + public JinxedChokerDynamicValue copy() { + return new JinxedChokerDynamicValue(); + } + + @Override + public String getMessage() { + return "charge counter on it"; + } + + @Override + public String toString() { + return "1"; + } +} + +class JinxedChokerCounterEffect extends OneShotEffect { + + public JinxedChokerCounterEffect() { + super(Outcome.Detriment); + this.staticText = "Put a charge counter on {this} or remove one from it"; + } + + public JinxedChokerCounterEffect(final JinxedChokerCounterEffect effect) { + super(effect); + } + + @Override + public JinxedChokerCounterEffect copy() { + return new JinxedChokerCounterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (controller != null && sourcePermanent != null) { + if (!sourcePermanent.getCounters().containsKey(CounterType.CHARGE) || controller.chooseUse(outcome, "Put a charge counter on? (No removes one)", source, game)) { + return new AddCountersSourceEffect(CounterType.CHARGE.createInstance(), true).apply(game, source); + } else { + return new RemoveCounterSourceEffect(CounterType.CHARGE.createInstance()).apply(game, source); + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/nemesis/MoggAlarm.java b/Mage.Sets/src/mage/sets/nemesis/MoggAlarm.java new file mode 100644 index 0000000000..3a7e4d58fb --- /dev/null +++ b/Mage.Sets/src/mage/sets/nemesis/MoggAlarm.java @@ -0,0 +1,72 @@ +/* + * 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.nemesis; + +import java.util.UUID; +import mage.abilities.costs.AlternativeCostSourceAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.permanent.token.GoblinToken; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author markedagain + */ +public class MoggAlarm extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("two Mountains"); + static { + filter.add(new SubtypePredicate("Mountain")); + } + + public MoggAlarm(UUID ownerId) { + super(ownerId, 93, "Mogg Alarm", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{R}{R}"); + this.expansionSetCode = "NMS"; + + // You may sacrifice two Mountains rather than pay Mogg Alarm's mana cost. + this.addAbility(new AlternativeCostSourceAbility(new SacrificeTargetCost(new TargetControlledPermanent(2, 2, filter, true)))); + // Put two 1/1 red Goblin creature tokens onto the battlefield. + this.getSpellAbility().addEffect(new CreateTokenEffect(new GoblinToken(),2)); + + } + + public MoggAlarm(final MoggAlarm card) { + super(card); + } + + @Override + public MoggAlarm copy() { + return new MoggAlarm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ninthedition/Thundermare.java b/Mage.Sets/src/mage/sets/ninthedition/Thundermare.java new file mode 100644 index 0000000000..a9e7495472 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ninthedition/Thundermare.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.ninthedition; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class Thundermare extends mage.sets.portal.Thundermare { + + public Thundermare(UUID ownerId) { + super(ownerId); + this.cardNumber = 224; + this.expansionSetCode = "9ED"; + } + + public Thundermare(final Thundermare card) { + super(card); + } + + @Override + public Thundermare copy() { + return new Thundermare(this); + } +} diff --git a/Mage.Sets/src/mage/sets/onslaught/Aurification.java b/Mage.Sets/src/mage/sets/onslaught/Aurification.java new file mode 100644 index 0000000000..92479ceca5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/onslaught/Aurification.java @@ -0,0 +1,164 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.onslaught; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BecomesSubtypeAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.ArrayList; +import java.util.UUID; + +/** + * + * @author andyfries + */ + +public class Aurification extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Each creature with a gold counter on it"); + + static { + filter.add(new CounterPredicate(CounterType.GOLD)); + } + + final String rule = "Each creature with a gold counter on it is a Wall in addition to its other creature types and has defender."; + + public Aurification(UUID ownerId) { + super(ownerId, 6, "Aurification", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); + this.expansionSetCode = "ONS"; + + // Whenever a creature deals damage to you, put a gold counter on it. + this.addAbility(new AddGoldCountersAbility()); + + // Each creature with a gold counter on it is a Wall in addition to its other creature types and has defender. + ArrayList subtypes = new ArrayList<>(1); + subtypes.add("Wall"); + + BecomesSubtypeAllEffect becomesSubtypeAllEffect = new BecomesSubtypeAllEffect(Duration.WhileOnBattlefield, subtypes, filter, false); + becomesSubtypeAllEffect.setText(""); + + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, becomesSubtypeAllEffect)); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(DefenderAbility.getInstance(), Duration.WhileOnBattlefield, filter, rule))); + + // When Aurification leaves the battlefield, remove all gold counters from all creatures. + this.addAbility(new LeavesBattlefieldTriggeredAbility(new RemoveAllGoldCountersEffect(), false)); + } + + public Aurification(final Aurification card) { + super(card); + } + + @Override + public Aurification copy() { + return new Aurification(this); + } + + public class AddGoldCountersAbility extends TriggeredAbilityImpl { + + public AddGoldCountersAbility() { + super(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.GOLD.createInstance())); + } + + public AddGoldCountersAbility(final AddGoldCountersAbility ability) { + super(ability); + } + + @Override + public AddGoldCountersAbility copy() { + return new AddGoldCountersAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getPlayerId().equals(this.getControllerId())) { + Permanent permanent = game.getPermanent(event.getSourceId()); + if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getSourceId())); + } + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever a creature deals damage to you, put a gold counter on it."; + } + + } + + public class RemoveAllGoldCountersEffect extends OneShotEffect { + public RemoveAllGoldCountersEffect() { + super(Outcome.Neutral); + this.staticText = "remove all gold counters from all creatures"; + } + + public RemoveAllGoldCountersEffect(final RemoveAllGoldCountersEffect effect) { + super(effect); + } + + @Override + public RemoveAllGoldCountersEffect copy() { + return new RemoveAllGoldCountersEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(CardType.CREATURE)) { + if (permanent != null){ + permanent.getCounters().removeAllCounters(CounterType.GOLD); + } + } + return true; + } + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/planarchaos/AvenRiftwatcher.java b/Mage.Sets/src/mage/sets/planarchaos/AvenRiftwatcher.java index 8cf27f15ec..4da27ce574 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/AvenRiftwatcher.java +++ b/Mage.Sets/src/mage/sets/planarchaos/AvenRiftwatcher.java @@ -29,6 +29,7 @@ package mage.sets.planarchaos; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersOrLeavesTheBattlefieldSourceTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; @@ -60,7 +61,9 @@ public class AvenRiftwatcher extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Vanishing 3 - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(3)))); + Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(3))); + ability.setRuleVisible(false); + this.addAbility(ability); this.addAbility(new VanishingUpkeepAbility(3)); this.addAbility(new VanishingSacrificeAbility()); diff --git a/Mage.Sets/src/mage/sets/planarchaos/BraidsConjurerAdept.java b/Mage.Sets/src/mage/sets/planarchaos/BraidsConjurerAdept.java new file mode 100644 index 0000000000..6938504723 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/BraidsConjurerAdept.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.common.PutPermanentOnBattlefieldEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; + +/** + * + * @author LoneFox + */ +public class BraidsConjurerAdept extends CardImpl { + + private static final FilterCard filter = new FilterCard("artifact, creature, or land card") +; + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.LAND))); + } + + public BraidsConjurerAdept(UUID ownerId) { + super(ownerId, 36, "Braids, Conjurer Adept", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); + this.expansionSetCode = "PLC"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Wizard"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // At the beginning of each player's upkeep, that player may put an artifact, creature, or land card from his or her hand onto the battlefield. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new PutPermanentOnBattlefieldEffect(filter, true), TargetController.ANY, false)); + } + + public BraidsConjurerAdept(final BraidsConjurerAdept card) { + super(card); + } + + @Override + public BraidsConjurerAdept copy() { + return new BraidsConjurerAdept(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/Calciderm.java b/Mage.Sets/src/mage/sets/planarchaos/Calciderm.java index 39865b67a5..3bc5e17017 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/Calciderm.java +++ b/Mage.Sets/src/mage/sets/planarchaos/Calciderm.java @@ -28,15 +28,16 @@ package mage.sets.planarchaos; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.ShroudAbility; import mage.abilities.keyword.VanishingSacrificeAbility; import mage.abilities.keyword.VanishingUpkeepAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.counters.CounterType; /** @@ -56,7 +57,9 @@ public class Calciderm extends CardImpl { // Shroud this.addAbility(ShroudAbility.getInstance()); // Vanishing 4 - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(4)))); + Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(4))); + ability.setRuleVisible(false); + this.addAbility(ability); this.addAbility(new VanishingUpkeepAbility(4)); this.addAbility(new VanishingSacrificeAbility()); } diff --git a/Mage.Sets/src/mage/sets/planarchaos/Chronozoa.java b/Mage.Sets/src/mage/sets/planarchaos/Chronozoa.java index a97add2ef4..ce30729322 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/Chronozoa.java +++ b/Mage.Sets/src/mage/sets/planarchaos/Chronozoa.java @@ -28,8 +28,8 @@ package mage.sets.planarchaos; import java.util.UUID; - import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.common.LastTimeCounterRemovedCondition; @@ -64,7 +64,9 @@ public class Chronozoa extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Vanishing 3 - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(timeCounters)))); + Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(timeCounters))); + ability.setRuleVisible(false); + this.addAbility(ability); this.addAbility(new VanishingUpkeepAbility(timeCounters)); this.addAbility(new VanishingSacrificeAbility()); // When Chronozoa is put into a graveyard from play, if it had no time counters on it, put two tokens into play that are copies of it. diff --git a/Mage.Sets/src/mage/sets/planarchaos/GhostTactician.java b/Mage.Sets/src/mage/sets/planarchaos/GhostTactician.java new file mode 100644 index 0000000000..0dd988d363 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/GhostTactician.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class GhostTactician extends CardImpl { + + public GhostTactician(UUID ownerId) { + super(ownerId, 6, "Ghost Tactician", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{W}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Spirit"); + this.subtype.add("Spellshaper"); + this.power = new MageInt(2); + this.toughness = new MageInt(5); + + // {W}, {T}, Discard a card: Creatures you control get +1/+0 until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new BoostControlledEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{W}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardCardCost()); + this.addAbility(ability); + } + + public GhostTactician(final GhostTactician card) { + super(card); + } + + @Override + public GhostTactician copy() { + return new GhostTactician(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/GossamerPhantasm.java b/Mage.Sets/src/mage/sets/planarchaos/GossamerPhantasm.java new file mode 100644 index 0000000000..651ed2bd33 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/GossamerPhantasm.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesTargetTriggeredAbility; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class GossamerPhantasm extends CardImpl { + + public GossamerPhantasm(UUID ownerId) { + super(ownerId, 55, "Gossamer Phantasm", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{U}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Illusion"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // When Gossamer Phantasm becomes the target of a spell or ability, sacrifice it. + this.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); + } + + public GossamerPhantasm(final GossamerPhantasm card) { + super(card); + } + + @Override + public GossamerPhantasm copy() { + return new GossamerPhantasm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/HealingLeaves.java b/Mage.Sets/src/mage/sets/planarchaos/HealingLeaves.java new file mode 100644 index 0000000000..f412e8438c --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/HealingLeaves.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.abilities.Mode; +import mage.abilities.effects.common.GainLifeTargetEffect; +import mage.abilities.effects.common.PreventDamageToTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.TargetPlayer; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LoneFox + */ +public class HealingLeaves extends CardImpl { + + public HealingLeaves(UUID ownerId) { + super(ownerId, 150, "Healing Leaves", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{G}"); + this.expansionSetCode = "PLC"; + + // Choose one - Target player gains 3 life; or prevent the next 3 damage that would be dealt to target creature or player this turn. + this.getSpellAbility().addEffect(new GainLifeTargetEffect(3)); + this.getSpellAbility().addTarget(new TargetPlayer()); + Mode mode = new Mode(); + mode.getEffects().add(new PreventDamageToTargetEffect(Duration.EndOfTurn, 3)); + mode.getTargets().add(new TargetCreatureOrPlayer()); + this.getSpellAbility().addMode(mode); + } + + public HealingLeaves(final HealingLeaves card) { + super(card); + } + + @Override + public HealingLeaves copy() { + return new HealingLeaves(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/KeldonMarauders.java b/Mage.Sets/src/mage/sets/planarchaos/KeldonMarauders.java index d342e0f28d..952005b8c6 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/KeldonMarauders.java +++ b/Mage.Sets/src/mage/sets/planarchaos/KeldonMarauders.java @@ -28,8 +28,6 @@ package mage.sets.planarchaos; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; @@ -39,6 +37,8 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.VanishingSacrificeAbility; import mage.abilities.keyword.VanishingUpkeepAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.counters.CounterType; import mage.target.TargetPlayer; @@ -58,12 +58,14 @@ public class KeldonMarauders extends CardImpl { this.toughness = new MageInt(3); // Vanishing 2 - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(2)))); + Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(2))); + ability.setRuleVisible(false); + this.addAbility(ability); this.addAbility(new VanishingUpkeepAbility(2)); this.addAbility(new VanishingSacrificeAbility()); - + // When Keldon Marauders enters the battlefield or leaves the battlefield, it deals 1 damage to target player. - Ability ability = new EntersOrLeavesTheBattlefieldSourceTriggeredAbility(new DamageTargetEffect(1), false); + ability = new EntersOrLeavesTheBattlefieldSourceTriggeredAbility(new DamageTargetEffect(1), false); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/planarchaos/LavacoreElemental.java b/Mage.Sets/src/mage/sets/planarchaos/LavacoreElemental.java index c7ffdca38b..972e529d88 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/LavacoreElemental.java +++ b/Mage.Sets/src/mage/sets/planarchaos/LavacoreElemental.java @@ -29,6 +29,7 @@ package mage.sets.planarchaos; import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.effects.Effect; @@ -56,10 +57,12 @@ public class LavacoreElemental extends CardImpl { this.toughness = new MageInt(3); // Vanishing 1 - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(1)))); + Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(1))); + ability.setRuleVisible(false); + this.addAbility(ability); this.addAbility(new VanishingUpkeepAbility(1)); this.addAbility(new VanishingSacrificeAbility()); - + // Whenever a creature you control deals combat damage to a player, put a time counter on Lavacore Elemental. Effect effect = new AddCountersSourceEffect(CounterType.TIME.createInstance(1)); effect.setText("put a time counter on {this}"); diff --git a/Mage.Sets/src/mage/sets/planarchaos/MagusOfTheBazaar.java b/Mage.Sets/src/mage/sets/planarchaos/MagusOfTheBazaar.java new file mode 100644 index 0000000000..fa9b7eaf22 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/MagusOfTheBazaar.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class MagusOfTheBazaar extends CardImpl { + + public MagusOfTheBazaar(UUID ownerId) { + super(ownerId, 43, "Magus of the Bazaar", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Human"); + this.subtype.add("Wizard"); + this.power = new MageInt(0); + this.toughness = new MageInt(1); + + // {tap}: Draw two cards, then discard three cards. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawDiscardControllerEffect(2, 3), new TapSourceCost())); } + + public MagusOfTheBazaar(final MagusOfTheBazaar card) { + super(card); + } + + @Override + public MagusOfTheBazaar copy() { + return new MagusOfTheBazaar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/MalachOfTheDawn.java b/Mage.Sets/src/mage/sets/planarchaos/MalachOfTheDawn.java new file mode 100644 index 0000000000..6bbae42c67 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/MalachOfTheDawn.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class MalachOfTheDawn extends CardImpl { + + public MalachOfTheDawn(UUID ownerId) { + super(ownerId, 24, "Malach of the Dawn", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Angel"); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // {W}{W}{W}: Regenerate Malach of the Dawn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{W}{W}{W}"))); + } + + public MalachOfTheDawn(final MalachOfTheDawn card) { + super(card); + } + + @Override + public MalachOfTheDawn copy() { + return new MalachOfTheDawn(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/Melancholy.java b/Mage.Sets/src/mage/sets/planarchaos/Melancholy.java new file mode 100644 index 0000000000..9a5c7cc3e6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/Melancholy.java @@ -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.sets.planarchaos; + +import java.util.UUID; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect; +import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; +import mage.abilities.effects.common.TapEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; +/** + * + * @author LoneFox + */ +public class Melancholy extends CardImpl { + + public Melancholy(UUID ownerId) { + super(ownerId, 88, "Melancholy", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + // When Melancholy enters the battlefield, tap enchanted creature. + this.addAbility(new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect())); + // Enchanted creature doesn't untap during its controller's untap step. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontUntapInControllersUntapStepEnchantedEffect())); + // At the beginning of your upkeep, sacrifice Melancholy unless you pay {B}. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{B}")), + TargetController.YOU, false)); + } + + public Melancholy(final Melancholy card) { + super(card); + } + + @Override + public Melancholy copy() { + return new Melancholy(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/MidnightCharm.java b/Mage.Sets/src/mage/sets/planarchaos/MidnightCharm.java new file mode 100644 index 0000000000..3e28029181 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/MidnightCharm.java @@ -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.planarchaos; + +import java.util.UUID; +import mage.abilities.Mode; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class MidnightCharm extends CardImpl { + + public MidnightCharm(UUID ownerId) { + super(ownerId, 74, "Midnight Charm", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{B}"); + this.expansionSetCode = "PLC"; + + // Choose one - Midnight Charm deals 1 damage to target creature and you gain 1 life; or target creature gains first strike until end of turn; or tap target creature. + this.getSpellAbility().addEffect(new DamageTargetEffect(1)); + this.getSpellAbility().addEffect(new GainLifeEffect(1)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + Mode mode = new Mode(); + mode.getEffects().add(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn)); + mode.getTargets().add(new TargetCreaturePermanent()); + this.getSpellAbility().addMode(mode); + mode = new Mode(); + mode.getEffects().add(new TapTargetEffect()); + mode.getTargets().add(new TargetCreaturePermanent()); + this.getSpellAbility().addMode(mode); + } + + public MidnightCharm(final MidnightCharm card) { + super(card); + } + + @Override + public MidnightCharm copy() { + return new MidnightCharm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/RealityAcid.java b/Mage.Sets/src/mage/sets/planarchaos/RealityAcid.java index 4357565e29..425d94127d 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/RealityAcid.java +++ b/Mage.Sets/src/mage/sets/planarchaos/RealityAcid.java @@ -69,7 +69,9 @@ public class RealityAcid extends CardImpl { this.addAbility(ability); // Vanishing 3 - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(3)))); + ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(3))); + ability.setRuleVisible(false); + this.addAbility(ability); this.addAbility(new VanishingUpkeepAbility(3)); this.addAbility(new VanishingSacrificeAbility()); diff --git a/Mage.Sets/src/mage/sets/planarchaos/ReveredDead.java b/Mage.Sets/src/mage/sets/planarchaos/ReveredDead.java new file mode 100644 index 0000000000..18abc74511 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/ReveredDead.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class ReveredDead extends CardImpl { + + public ReveredDead(UUID ownerId) { + super(ownerId, 29, "Revered Dead", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Spirit"); + this.subtype.add("Soldier"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {W}: Regenerate Revered Dead. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{W}"))); + } + + public ReveredDead(final ReveredDead card) { + super(card); + } + + @Override + public ReveredDead copy() { + return new ReveredDead(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/RidgedKusite.java b/Mage.Sets/src/mage/sets/planarchaos/RidgedKusite.java new file mode 100644 index 0000000000..87ab8078e8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/RidgedKusite.java @@ -0,0 +1,83 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class RidgedKusite extends CardImpl { + + public RidgedKusite(UUID ownerId) { + super(ownerId, 78, "Ridged Kusite", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{B}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Horror"); + this.subtype.add("Spellshaper"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {1}{B}, {tap}, Discard a card: Target creature gets +1/+0 and gains first strike until end of turn. + Effect effect = new BoostTargetEffect(1, 0, Duration.EndOfTurn); + effect.setText("Target creature gets +1/+0"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{B}")); + effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and gains first strike until end of turn"); + ability.addEffect(effect); + ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardCardCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public RidgedKusite(final RidgedKusite card) { + super(card); + } + + @Override + public RidgedKusite copy() { + return new RidgedKusite(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/RiptidePilferer.java b/Mage.Sets/src/mage/sets/planarchaos/RiptidePilferer.java new file mode 100644 index 0000000000..dbb0b57f71 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/RiptidePilferer.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.abilities.keyword.MorphAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class RiptidePilferer extends CardImpl { + + public RiptidePilferer(UUID ownerId) { + super(ownerId, 60, "Riptide Pilferer", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{U}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Merfolk"); + this.subtype.add("Rogue"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever Riptide Pilferer deals combat damage to a player, that player discards a card. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1), false, true)); // Morph {U} + this.addAbility(new MorphAbility(this, new ManaCostsImpl("{U}"))); + } + + public RiptidePilferer(final RiptidePilferer card) { + super(card); + } + + @Override + public RiptidePilferer copy() { + return new RiptidePilferer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/ShroudedLore.java b/Mage.Sets/src/mage/sets/planarchaos/ShroudedLore.java new file mode 100644 index 0000000000..a9ffdeab0b --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/ShroudedLore.java @@ -0,0 +1,141 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +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.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.predicate.other.OwnerIdPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetOpponent; + +/** + * + * @author LoneFox + */ +public class ShroudedLore extends CardImpl { + + public ShroudedLore(UUID ownerId) { + super(ownerId, 91, "Shrouded Lore", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{B}"); + this.expansionSetCode = "PLC"; + + // Target opponent chooses a card in your graveyard. You may pay {B}. If you do, repeat this process except that opponent can't choose a card already chosen for Shrouded Lore. Then put the last chosen card into your hand. + this.getSpellAbility().addEffect(new ShroudedLoreEffect()); + this.getSpellAbility().addTarget(new TargetOpponent()); + } + + public ShroudedLore(final ShroudedLore card) { + super(card); + } + + @Override + public ShroudedLore copy() { + return new ShroudedLore(this); + } +} + +class ShroudedLoreEffect extends OneShotEffect { + + public ShroudedLoreEffect() { + super(Outcome.Benefit); + staticText = "Target opponent chooses a card in your graveyard. You may pay {B}. If you do, repeat this process except that opponent can't choose a card already chosen for {this}. Then put the last chosen card into your hand."; + } + + public ShroudedLoreEffect(final ShroudedLoreEffect effect) { + super(effect); + } + + @Override + public ShroudedLoreEffect copy() { + return new ShroudedLoreEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player you = game.getPlayer(source.getControllerId()); + Player opponent = game.getPlayer(targetPointer.getFirst(game, source)); + if(you != null && opponent != null) + { + FilterCard filter = new FilterCard(); + filter.add(new OwnerIdPredicate(you.getId())); + Cost cost = new ManaCostsImpl("{B}"); + TargetCardInGraveyard chosenCard; + Card card = null; + boolean done = false; + do { + chosenCard = new TargetCardInGraveyard(filter); + chosenCard.setNotTarget(true); + if(chosenCard.canChoose(opponent.getId(), game)) { + opponent.chooseTarget(Outcome.ReturnToHand, chosenCard, source, game); + card = game.getCard(chosenCard.getFirstTarget()); + filter.add(Predicates.not(new CardIdPredicate(card.getId()))); + game.informPlayers("Shrouded Lore: " + opponent.getLogName() + " has chosen " + card.getLogName()); + } + else { + done = true; + } + + if(!done) { + if(cost.canPay(source, source.getSourceId(), you.getId(), game) && you.chooseUse(Outcome.Benefit, "Pay {B} to choose a different card ?", source, game)) { + cost.clearPaid(); + if(!cost.pay(source, game, source.getSourceId(), you.getId(), false)) { + done = true; + } + } + else { + done = true; + } + } + + } while(!done); + + if(card != null) { + Cards cardsToHand = new CardsImpl(); + cardsToHand.add(card); + you.moveCards(cardsToHand, Zone.GRAVEYARD, Zone.HAND, source, game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/Timbermare.java b/Mage.Sets/src/mage/sets/planarchaos/Timbermare.java new file mode 100644 index 0000000000..3a3c321c9b --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/Timbermare.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.TapAllEffect; +import mage.abilities.keyword.EchoAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; + +/** + * + * @author LoneFox + */ +public class Timbermare extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); + + static { + filter.add(new AnotherPredicate()); + } + + public Timbermare(UUID ownerId) { + super(ownerId, 140, "Timbermare", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Elemental"); + this.subtype.add("Horse"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Haste + this.addAbility(HasteAbility.getInstance()); + // Echo {5}{G} + this.addAbility(new EchoAbility("{5}{G}")); + // When Timbermare enters the battlefield, tap all other creatures. + this.addAbility(new EntersBattlefieldTriggeredAbility(new TapAllEffect(filter))); + } + + public Timbermare(final Timbermare card) { + super(card); + } + + @Override + public Timbermare copy() { + return new Timbermare(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/UktabiDrake.java b/Mage.Sets/src/mage/sets/planarchaos/UktabiDrake.java new file mode 100644 index 0000000000..cd638634fa --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/UktabiDrake.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.EchoAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class UktabiDrake extends CardImpl { + + public UktabiDrake(UUID ownerId) { + super(ownerId, 141, "Uktabi Drake", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{G}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Drake"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Haste + this.addAbility(HasteAbility.getInstance()); + // Echo {1}{G}{G} + this.addAbility(new EchoAbility("{1}{G}{G}")); + } + + public UktabiDrake(final UktabiDrake card) { + super(card); + } + + @Override + public UktabiDrake copy() { + return new UktabiDrake(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/WaningWurm.java b/Mage.Sets/src/mage/sets/planarchaos/WaningWurm.java new file mode 100644 index 0000000000..7a37457f8d --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/WaningWurm.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.VanishingSacrificeAbility; +import mage.abilities.keyword.VanishingUpkeepAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.counters.CounterType; + +/** + * + * @author LoneFox + */ +public class WaningWurm extends CardImpl { + + public WaningWurm(UUID ownerId) { + super(ownerId, 83, "Waning Wurm", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Zombie"); + this.subtype.add("Wurm"); + this.power = new MageInt(7); + this.toughness = new MageInt(6); + + // Vanishing 2 + Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(2))); + ability.setRuleVisible(false); + this.addAbility(ability); + this.addAbility(new VanishingUpkeepAbility(2)); + this.addAbility(new VanishingSacrificeAbility()); + } + + public WaningWurm(final WaningWurm card) { + super(card); + } + + @Override + public WaningWurm copy() { + return new WaningWurm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portal/Thundermare.java b/Mage.Sets/src/mage/sets/portal/Thundermare.java new file mode 100644 index 0000000000..51a6fb7b48 --- /dev/null +++ b/Mage.Sets/src/mage/sets/portal/Thundermare.java @@ -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.portal; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.TapAllEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; + +/** + * + * @author LoneFox + */ +public class Thundermare extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures"); + + static { + filter.add(new AnotherPredicate()); + } + + public Thundermare(UUID ownerId) { + super(ownerId, 158, "Thundermare", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{R}"); + this.expansionSetCode = "POR"; + this.subtype.add("Elemental"); + this.subtype.add("Horse"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Haste + this.addAbility(HasteAbility.getInstance()); + // When Thundermare enters the battlefield, tap all other creatures. + this.addAbility(new EntersBattlefieldTriggeredAbility(new TapAllEffect(filter))); + } + + public Thundermare(final Thundermare card) { + super(card); + } + + @Override + public Thundermare copy() { + return new Thundermare(this); + } +} diff --git a/Mage.Sets/src/mage/sets/revisededition/Deathgrip.java b/Mage.Sets/src/mage/sets/revisededition/Deathgrip.java new file mode 100644 index 0000000000..220647d307 --- /dev/null +++ b/Mage.Sets/src/mage/sets/revisededition/Deathgrip.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.revisededition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Deathgrip extends mage.sets.limitedbeta.Deathgrip { + + public Deathgrip(UUID ownerId) { + super(ownerId); + this.cardNumber = 9; + this.expansionSetCode = "3ED"; + } + + public Deathgrip(final Deathgrip card) { + super(card); + } + + @Override + public Deathgrip copy() { + return new Deathgrip(this); + } +} diff --git a/Mage.Sets/src/mage/sets/tempest/Apocalypse.java b/Mage.Sets/src/mage/sets/tempest/Apocalypse.java new file mode 100644 index 0000000000..ec63ce33d5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tempest/Apocalypse.java @@ -0,0 +1,117 @@ +/* + * 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.tempest; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author markedagain + */ +public class Apocalypse extends CardImpl { + + public Apocalypse(UUID ownerId) { + super(ownerId, 162, "Apocalypse", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{R}{R}{R}"); + this.expansionSetCode = "TMP"; + + // Exile all permanents. You discard your hand. + this.getSpellAbility().addEffect(new ApocalypseExileAllPermanentsEffect()); + this.getSpellAbility().addEffect(new ApocalypseDiscardEffect()); + } + + public Apocalypse(final Apocalypse card) { + super(card); + } + + @Override + public Apocalypse copy() { + return new Apocalypse(this); + } +} +class ApocalypseDiscardEffect extends OneShotEffect { + + public ApocalypseDiscardEffect() { + super(Outcome.Discard); + this.staticText = "Discard your hand"; + } + + public ApocalypseDiscardEffect(final ApocalypseDiscardEffect effect) { + super(effect); + } + + @Override + public ApocalypseDiscardEffect copy() { + return new ApocalypseDiscardEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + for (Card card : player.getHand().getCards(game)) { + player.discard(card, source, game); + } + return true; + } + return false; + } +} +class ApocalypseExileAllPermanentsEffect extends OneShotEffect { + + public ApocalypseExileAllPermanentsEffect() { + super(Outcome.Exile); + staticText = "Exile all permanents"; + } + + public ApocalypseExileAllPermanentsEffect(final ApocalypseExileAllPermanentsEffect effect) { + super(effect); + } + + @Override + public ApocalypseExileAllPermanentsEffect copy() { + return new ApocalypseExileAllPermanentsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) { + permanent.moveToExile(null, null, source.getSourceId(), game); + } + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/unlimitededition/Deathgrip.java b/Mage.Sets/src/mage/sets/unlimitededition/Deathgrip.java new file mode 100644 index 0000000000..5467ba0936 --- /dev/null +++ b/Mage.Sets/src/mage/sets/unlimitededition/Deathgrip.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.unlimitededition; + +import java.util.UUID; + +/** + * + * @author anonymous + */ +public class Deathgrip extends mage.sets.limitedbeta.Deathgrip { + + public Deathgrip(UUID ownerId) { + super(ownerId); + this.cardNumber = 9; + this.expansionSetCode = "2ED"; + } + + public Deathgrip(final Deathgrip card) { + super(card); + } + + @Override + public Deathgrip copy() { + return new Deathgrip(this); + } +} diff --git a/Mage.Sets/src/mage/sets/visions/TarPitWarrior.java b/Mage.Sets/src/mage/sets/visions/TarPitWarrior.java new file mode 100644 index 0000000000..f6212d37c3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/visions/TarPitWarrior.java @@ -0,0 +1,64 @@ +/* + * 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.visions; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BecomesTargetTriggeredAbility; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class TarPitWarrior extends CardImpl { + + public TarPitWarrior(UUID ownerId) { + super(ownerId, 20, "Tar Pit Warrior", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "VIS"; + this.subtype.add("Cyclops"); + this.subtype.add("Warrior"); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // When Tar Pit Warrior becomes the target of a spell or ability, sacrifice it. + this.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect())); + } + + public TarPitWarrior(final TarPitWarrior card) { + super(card); + } + + @Override + public TarPitWarrior copy() { + return new TarPitWarrior(this); + } +} diff --git a/Mage.Sets/src/mage/sets/weatherlight/Thundermare.java b/Mage.Sets/src/mage/sets/weatherlight/Thundermare.java new file mode 100644 index 0000000000..6a8f1b8be5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/weatherlight/Thundermare.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.weatherlight; + +import java.util.UUID; + +/** + * + * @author LoneFox + */ +public class Thundermare extends mage.sets.portal.Thundermare { + + public Thundermare(UUID ownerId) { + super(ownerId); + this.cardNumber = 116; + this.expansionSetCode = "WTH"; + } + + public Thundermare(final Thundermare card) { + super(card); + } + + @Override + public Thundermare copy() { + return new Thundermare(this); + } +} diff --git a/Mage.Sets/src/mage/sets/worldwake/CanopyCover.java b/Mage.Sets/src/mage/sets/worldwake/CanopyCover.java index ca6ca52f35..71c8ff7ec9 100644 --- a/Mage.Sets/src/mage/sets/worldwake/CanopyCover.java +++ b/Mage.Sets/src/mage/sets/worldwake/CanopyCover.java @@ -28,12 +28,6 @@ package mage.sets.worldwake; import java.util.UUID; -import mage.constants.AttachmentType; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.RestrictionEffect; @@ -43,33 +37,32 @@ import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.ReachAbility; import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterObject; import mage.filter.FilterStackObject; -import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; - - /** * @author noxx */ public class CanopyCover extends CardImpl { - private static final FilterStackObject filter = new FilterStackObject("spells or abilities your opponents control"); + private static final FilterObject filter = new FilterStackObject("spells or abilities your opponents control"); - static { - filter.add(new ControllerPredicate(TargetController.OPPONENT)); - } - public CanopyCover(UUID ownerId) { super(ownerId, 98, "Canopy Cover", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); this.expansionSetCode = "WWK"; this.subtype.add("Aura"); - // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); @@ -81,7 +74,7 @@ public class CanopyCover extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new OrchardSpiritEffect())); // Enchanted creature can't be the target of spells or abilities your opponents control. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeTargetedAttachedEffect(filter, Duration.WhileOnBattlefield, AttachmentType.AURA))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeTargetedAttachedEffect(filter, Duration.WhileOnBattlefield, AttachmentType.AURA, TargetController.OPPONENT))); } public CanopyCover(final CanopyCover card) { diff --git a/Mage.Sets/src/mage/sets/worldwake/UrgeToFeed.java b/Mage.Sets/src/mage/sets/worldwake/UrgeToFeed.java index 63b2dd6025..ad2d8e2ba1 100644 --- a/Mage.Sets/src/mage/sets/worldwake/UrgeToFeed.java +++ b/Mage.Sets/src/mage/sets/worldwake/UrgeToFeed.java @@ -28,15 +28,14 @@ package mage.sets.worldwake; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.Rarity; import mage.constants.TargetController; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; @@ -45,6 +44,7 @@ import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.permanent.ControllerPredicate; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** @@ -59,7 +59,6 @@ public class UrgeToFeed extends CardImpl { super(ownerId, 70, "Urge to Feed", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{B}{B}"); this.expansionSetCode = "WWK"; - // Target creature gets -3/-3 until end of turn. You may tap any number of untapped Vampire creatures you control. If you do, put a +1/+1 counter on each of those Vampires. this.getSpellAbility().addEffect(new BoostTargetEffect(-3, -3, Duration.EndOfTurn)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); @@ -97,20 +96,17 @@ class UrgeToFeedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - while (true) { - target.clearChosen(); - if (target.canChoose(source.getControllerId(), game) && target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), game)) { - UUID vampire = target.getFirstTarget(); + TargetCreaturePermanent target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true); + if (target.canChoose(source.getControllerId(), game) && target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), game)) { + for (UUID vampireId : target.getTargets()) { + Permanent vampire = game.getPermanent(vampireId); if (vampire != null) { - game.getPermanent(vampire).tap(game); - game.getPermanent(vampire).addCounters(CounterType.P1P1.createInstance(), game); + vampire.tap(game); + vampire.addCounters(CounterType.P1P1.createInstance(), game); } - } else { - break; } } - return false; + return true; } @Override diff --git a/Mage.Sets/src/mage/sets/zendikar/VinesOfVastwood.java b/Mage.Sets/src/mage/sets/zendikar/VinesOfVastwood.java index d67de8aa3f..cb72eb9e98 100644 --- a/Mage.Sets/src/mage/sets/zendikar/VinesOfVastwood.java +++ b/Mage.Sets/src/mage/sets/zendikar/VinesOfVastwood.java @@ -25,23 +25,22 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.zendikar; import java.util.UUID; import mage.abilities.condition.LockedInCondition; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.effects.common.CantBeTargetedTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; import mage.constants.TargetController; +import mage.filter.FilterObject; import mage.filter.FilterStackObject; -import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.common.TargetCreaturePermanent; /** @@ -49,12 +48,8 @@ import mage.target.common.TargetCreaturePermanent; */ public class VinesOfVastwood extends CardImpl { - private static final FilterStackObject filter = new FilterStackObject("spells or abilities your opponents control"); + private static final FilterObject filter = new FilterStackObject("spells or abilities your opponents control"); - static { - filter.add(new ControllerPredicate(TargetController.OPPONENT)); - } - private static final String staticText = "If {this} was kicked, that creature gets +4/+4 until end of turn"; public VinesOfVastwood(UUID ownerId) { @@ -66,7 +61,7 @@ public class VinesOfVastwood extends CardImpl { // Target creature can't be the target of spells or abilities your opponents control this turn. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new CantBeTargetedTargetEffect(filter, Duration.EndOfTurn)); + this.getSpellAbility().addEffect(new CantBeTargetedTargetEffect(filter, Duration.EndOfTurn, TargetController.OPPONENT)); // If Vines of Vastwood was kicked, that creature gets +4/+4 until end of turn. this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new BoostTargetEffect(4, 4, Duration.EndOfTurn), @@ -82,4 +77,3 @@ public class VinesOfVastwood extends CardImpl { return new VinesOfVastwood(this); } } - diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/canttarget/CanopyCoverTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/canttarget/CanopyCoverTest.java new file mode 100644 index 0000000000..d3c0125f01 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/canttarget/CanopyCoverTest.java @@ -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 org.mage.test.cards.replacement.canttarget; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class CanopyCoverTest extends CardTestPlayerBase { + + /** + * Test spell + */ + @Test + public void testCantBeTargetedWithSpells() { + addCard(Zone.HAND, playerB, "Lightning Bolt"); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // 2/2 Creature - Lion + // Enchanted creature can't be the target of spells or abilities your opponents control. + addCard(Zone.HAND, playerA, "Canopy Cover"); // Enchantment - Aura + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Canopy Cover", "Silvercoat Lion"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", "Silvercoat Lion"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Canopy Cover", 1); + assertPermanentCount(playerA, "Silvercoat Lion", 1); + + assertHandCount(playerB, "Lightning Bolt", 1); + } + + @Test + public void testCantBeTargetedWithAbilities() { + // {U},Sacrifice AEther Spellbomb: Return target creature to its owner's hand. + addCard(Zone.BATTLEFIELD, playerB, "AEther Spellbomb"); + addCard(Zone.BATTLEFIELD, playerB, "Island", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // 2/2 Creature - Lion + // Enchanted creature can't be the target of spells or abilities your opponents control. + addCard(Zone.HAND, playerA, "Canopy Cover"); // Enchantment - Aura + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Canopy Cover", "Silvercoat Lion"); + + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{U},Sacrifice", "Silvercoat Lion"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Canopy Cover", 1); + assertPermanentCount(playerA, "Silvercoat Lion", 1); + + assertGraveyardCount(playerB, "AEther Spellbomb", 0); + assertPermanentCount(playerB, "AEther Spellbomb", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/canttarget/GaeasRevengeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/canttarget/GaeasRevengeTest.java new file mode 100644 index 0000000000..34fa2d0976 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/canttarget/GaeasRevengeTest.java @@ -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 org.mage.test.cards.replacement.canttarget; + +import mage.abilities.keyword.TrampleAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class GaeasRevengeTest extends CardTestPlayerBase { + + /** + * Test spell + */ + @Test + public void testGreenCanTargetWithSpells() { + addCard(Zone.HAND, playerA, "Titanic Growth"); + // Gaea's Revenge can't be countered. + // Haste + // Gaea's Revenge can't be the target of nongreen spells or abilities from nongreen sources. + addCard(Zone.BATTLEFIELD, playerA, "Gaea's Revenge"); // 8/5 Creature - Elemental + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Titanic Growth", "Gaea's Revenge"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + assertPowerToughness(playerA, "Gaea's Revenge", 12, 9); + } + + @Test + public void testGreenCanTargetWithAnAbilitiy() { + // Gaea's Revenge can't be countered. + // Haste + // Gaea's Revenge can't be the target of nongreen spells or abilities from nongreen sources. + addCard(Zone.BATTLEFIELD, playerB, "Gaea's Revenge"); // 8/5 Creature - Elemental + // Whenever a creature you control becomes blocked, it gets +1/+1 until end of turn. + // {1}{G}: Target creature you control gains trample until end of turn. + addCard(Zone.BATTLEFIELD, playerB, "Somberwald Alpha"); // 3/2 Creature - Wolf + + addCard(Zone.BATTLEFIELD, playerB, "Forest", 2); + + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{G}: Target creature", "Gaea's Revenge"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + assertAbility(playerB, "Gaea's Revenge", TrampleAbility.getInstance(), true); + assertPowerToughness(playerB, "Gaea's Revenge", 8, 5); + } +} diff --git a/Mage/src/mage/abilities/effects/common/CantBeTargetedAttachedEffect.java b/Mage/src/mage/abilities/effects/common/CantBeTargetedAttachedEffect.java index bf055b1806..132375bef2 100644 --- a/Mage/src/mage/abilities/effects/common/CantBeTargetedAttachedEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantBeTargetedAttachedEffect.java @@ -27,39 +27,43 @@ */ package mage.abilities.effects.common; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.constants.AttachmentType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.FilterStackObject; +import mage.constants.TargetController; +import mage.filter.FilterObject; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; +import mage.game.stack.StackAbility; /** * * @author LevelX2 */ - public class CantBeTargetedAttachedEffect extends ContinuousRuleModifyingEffectImpl { - private final FilterStackObject filterSource; + private final FilterObject filterSource; private final AttachmentType attachmentType; - - public CantBeTargetedAttachedEffect(FilterStackObject filterSource, Duration duration, AttachmentType attachmentType) { + private final TargetController targetController; + + public CantBeTargetedAttachedEffect(FilterObject filterSource, Duration duration, AttachmentType attachmentType, TargetController targetController) { super(duration, Outcome.Benefit); this.filterSource = filterSource; this.attachmentType = attachmentType; + this.targetController = targetController; } public CantBeTargetedAttachedEffect(final CantBeTargetedAttachedEffect effect) { super(effect); this.filterSource = effect.filterSource.copy(); this.attachmentType = effect.attachmentType; + this.targetController = effect.targetController; } @Override @@ -81,8 +85,18 @@ public class CantBeTargetedAttachedEffect extends ContinuousRuleModifyingEffectI public boolean applies(GameEvent event, Ability source, Game game) { Permanent attachment = game.getPermanent(source.getSourceId()); if (attachment != null && event.getTargetId().equals(attachment.getAttachedTo())) { - StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceObject != null && filterSource.match(sourceObject, source.getControllerId(), game)) { + if (targetController.equals(TargetController.OPPONENT) + && !game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + return false; + } + MageObject mageObject = game.getObject(event.getSourceId()); + MageObject sourceObject; + if (mageObject instanceof StackAbility) { + sourceObject = ((StackAbility) mageObject).getSourceObject(game); + } else { + sourceObject = mageObject; + } + if (mageObject != null && filterSource.match(sourceObject, game)) { return true; } } @@ -103,13 +117,13 @@ public class CantBeTargetedAttachedEffect extends ContinuousRuleModifyingEffectI sb.append(" can't be the target of "); sb.append(filterSource.getMessage()); if (!duration.toString().isEmpty()) { - sb.append(" "); + sb.append(" "); if (duration.equals(Duration.EndOfTurn)) { sb.append("this turn"); } else { sb.append(duration.toString()); } - } + } return sb.toString(); } diff --git a/Mage/src/mage/abilities/effects/common/CantBeTargetedSourceEffect.java b/Mage/src/mage/abilities/effects/common/CantBeTargetedSourceEffect.java index d49b331c81..2a09645f96 100644 --- a/Mage/src/mage/abilities/effects/common/CantBeTargetedSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantBeTargetedSourceEffect.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,22 +20,23 @@ * 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.MageObject; import mage.abilities.Ability; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.FilterStackObject; +import mage.filter.FilterObject; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.StackAbility; import mage.game.stack.StackObject; /** @@ -44,9 +45,9 @@ import mage.game.stack.StackObject; */ public class CantBeTargetedSourceEffect extends ContinuousRuleModifyingEffectImpl { - private final FilterStackObject filterSource; + private final FilterObject filterSource; - public CantBeTargetedSourceEffect(FilterStackObject filterSource, Duration duration) { + public CantBeTargetedSourceEffect(FilterObject filterSource, Duration duration) { super(duration, Outcome.Benefit); this.filterSource = filterSource; setText(); @@ -66,7 +67,7 @@ public class CantBeTargetedSourceEffect extends ContinuousRuleModifyingEffectImp public boolean apply(Game game, Ability source) { return true; } - + @Override public boolean checksEventType(GameEvent event, Game game) { return event.getType() == EventType.TARGET; @@ -75,8 +76,14 @@ public class CantBeTargetedSourceEffect extends ContinuousRuleModifyingEffectImp @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getTargetId().equals(source.getSourceId())) { - StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceObject != null && filterSource.match(sourceObject, source.getControllerId(), game)) { + StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); + MageObject sourceObject; + if (stackObject instanceof StackAbility) { + sourceObject = ((StackAbility) stackObject).getSourceObject(game); + } else { + sourceObject = stackObject; + } + if (sourceObject != null && filterSource.match(sourceObject, game)) { return true; } } diff --git a/Mage/src/mage/abilities/effects/common/CantBeTargetedTargetEffect.java b/Mage/src/mage/abilities/effects/common/CantBeTargetedTargetEffect.java index 644b78b645..387a5e03bf 100644 --- a/Mage/src/mage/abilities/effects/common/CantBeTargetedTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/CantBeTargetedTargetEffect.java @@ -27,34 +27,43 @@ */ package mage.abilities.effects.common; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.FilterStackObject; +import mage.constants.TargetController; +import mage.filter.FilterObject; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.stack.StackAbility; import mage.game.stack.StackObject; /** * * @author LevelX2 */ - public class CantBeTargetedTargetEffect extends ContinuousRuleModifyingEffectImpl { - private final FilterStackObject filterSource; + private final FilterObject filterSource; + private final TargetController targetController; - public CantBeTargetedTargetEffect(FilterStackObject filterSource, Duration duration) { + public CantBeTargetedTargetEffect(FilterObject filterSource, Duration duration) { + this(filterSource, duration, TargetController.ANY); + } + + public CantBeTargetedTargetEffect(FilterObject filterSource, Duration duration, TargetController targetController) { super(duration, Outcome.Benefit, false, false); + this.targetController = targetController; this.filterSource = filterSource; } public CantBeTargetedTargetEffect(final CantBeTargetedTargetEffect effect) { super(effect); this.filterSource = effect.filterSource.copy(); + this.targetController = effect.targetController; } @Override @@ -75,8 +84,18 @@ public class CantBeTargetedTargetEffect extends ContinuousRuleModifyingEffectImp @Override public boolean applies(GameEvent event, Ability source, Game game) { if (getTargetPointer().getTargets(game, source).contains(event.getTargetId())) { - StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceObject != null && filterSource.match(sourceObject, source.getControllerId(), game)) { + if (targetController.equals(TargetController.OPPONENT) + && !game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { + return false; + } + StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); + MageObject sourceObject; + if (stackObject instanceof StackAbility) { + sourceObject = ((StackAbility) stackObject).getSourceObject(game); + } else { + sourceObject = stackObject; + } + if (sourceObject != null && filterSource.match(sourceObject, game)) { return true; } } @@ -95,13 +114,13 @@ public class CantBeTargetedTargetEffect extends ContinuousRuleModifyingEffectImp sb.append(" can't be the target of "); sb.append(filterSource.getMessage()); if (!duration.toString().isEmpty()) { - sb.append(" "); + sb.append(" "); if (duration.equals(Duration.EndOfTurn)) { sb.append("this turn"); } else { sb.append(duration.toString()); } - } + } return sb.toString(); } diff --git a/Mage/src/mage/abilities/effects/common/PutPermanentOnBattlefieldEffect.java b/Mage/src/mage/abilities/effects/common/PutPermanentOnBattlefieldEffect.java index 09a89be195..12a208ab19 100644 --- a/Mage/src/mage/abilities/effects/common/PutPermanentOnBattlefieldEffect.java +++ b/Mage/src/mage/abilities/effects/common/PutPermanentOnBattlefieldEffect.java @@ -18,19 +18,26 @@ import mage.target.common.TargetCardInHand; public class PutPermanentOnBattlefieldEffect extends OneShotEffect { private final FilterCard filter; + private final boolean useTargetController; public PutPermanentOnBattlefieldEffect() { - this(new FilterPermanentCard("a permanent card")); + this(new FilterPermanentCard("a permanent card"), false); } public PutPermanentOnBattlefieldEffect(FilterCard filter) { + this(filter, false); + } + + public PutPermanentOnBattlefieldEffect(FilterCard filter, boolean useTargetController) { super(Outcome.PutCardInPlay); this.filter = filter; + this.useTargetController = useTargetController; } public PutPermanentOnBattlefieldEffect(final PutPermanentOnBattlefieldEffect effect) { super(effect); this.filter = effect.filter.copy(); + this.useTargetController = effect.useTargetController; } @Override @@ -40,7 +47,13 @@ public class PutPermanentOnBattlefieldEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); + Player player; + if(useTargetController) { + player = game.getPlayer(getTargetPointer().getFirst(game, source)); + } + else { + player = game.getPlayer(source.getControllerId()); + } String choiceText = "Put " + filter.getMessage() + " from your hand onto the battlefield?"; if (player == null || !player.chooseUse(Outcome.PutCardInPlay, choiceText, source, game)) { return false; @@ -63,6 +76,11 @@ public class PutPermanentOnBattlefieldEffect extends OneShotEffect { return staticText; } - return "you may put " + filter.getMessage() + " from your hand onto the battlefield"; + if(useTargetController) { + return "that player may put " + filter.getMessage() + " from his or her hand onto the battlefield"; + } + else { + return "you may put " + filter.getMessage() + " from your hand onto the battlefield"; + } } } diff --git a/Mage/src/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java b/Mage/src/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java index 36c62e51ad..80e7bcdb69 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java @@ -6,8 +6,11 @@ package mage.abilities.effects.common.continuous; import java.util.ArrayList; +import java.util.Iterator; +import mage.MageObjectReference; import mage.abilities.Ability; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; import mage.constants.Layer; @@ -25,21 +28,23 @@ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl { protected ArrayList subtypes = new ArrayList(); protected boolean loseOther; // loses other subtypes + protected FilterCreaturePermanent filter; - public BecomesSubtypeAllEffect(Duration duration, String subtype) { + public BecomesSubtypeAllEffect(Duration duration, String subtype) { this(duration, createArrayList(subtype)); } public BecomesSubtypeAllEffect(Duration duration, ArrayList subtypes) { - this(duration, subtypes, true); + this(duration, subtypes, new FilterCreaturePermanent("All creatures"), true); } public BecomesSubtypeAllEffect(Duration duration, - ArrayList subtypes, boolean loseOther) { + ArrayList subtypes, FilterCreaturePermanent filter, boolean loseOther) { super(duration, Outcome.Detriment); this.subtypes = subtypes; this.staticText = setText(); this.loseOther = loseOther; + this.filter = filter; } private static ArrayList createArrayList(String subtype) { @@ -52,7 +57,7 @@ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl { super(effect); this.subtypes.addAll(effect.subtypes); this.loseOther = effect.loseOther; - this.loseOther = effect.loseOther; + this.filter = effect.filter; } @Override @@ -68,9 +73,7 @@ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - - for (Permanent permanent : game.getBattlefield() - .getAllActivePermanents(new FilterCreaturePermanent(), game)) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, game)) { if (permanent != null) { switch (layer) { case TypeChangingEffects_4: diff --git a/Mage/src/mage/counters/CounterType.java b/Mage/src/mage/counters/CounterType.java index 4ed223d9f2..a8dc32e0ef 100644 --- a/Mage/src/mage/counters/CounterType.java +++ b/Mage/src/mage/counters/CounterType.java @@ -55,6 +55,7 @@ public enum CounterType { FEATHER("feather"), FLOOD("flood"), FUSE("fuse"), + GOLD("gold"), HATCHLING("hatchling"), HOOFPRINT("hoofprint"), ICE("ice"), diff --git a/Mage/src/mage/counters/Counters.java b/Mage/src/mage/counters/Counters.java index 6b1aca15ed..473106f081 100644 --- a/Mage/src/mage/counters/Counters.java +++ b/Mage/src/mage/counters/Counters.java @@ -96,6 +96,16 @@ public class Counters extends HashMap implements Serializable { } } + public void removeAllCounters(CounterType counterType){ + removeAllCounters(counterType.getName()); + } + + public void removeAllCounters(String name){ + if (this.containsKey(name)){ + this.remove(name); + } + } + public int getCount(String name) { if (this.containsKey(name)) { return this.get(name).getCount(); diff --git a/Mage/src/mage/filter/FilterImpl.java b/Mage/src/mage/filter/FilterImpl.java index ecb3f9ee92..7def209d6e 100644 --- a/Mage/src/mage/filter/FilterImpl.java +++ b/Mage/src/mage/filter/FilterImpl.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.filter; import java.util.ArrayList; @@ -52,7 +51,7 @@ public abstract class FilterImpl implements Filter { this.message = name; } - public FilterImpl(FilterImpl filter) { + public FilterImpl(FilterImpl filter) { this.message = filter.message; this.predicates = new ArrayList<>(filter.predicates); } diff --git a/Mage/src/mage/filter/FilterObject.java b/Mage/src/mage/filter/FilterObject.java index 29402389df..3fc96e9c6b 100644 --- a/Mage/src/mage/filter/FilterObject.java +++ b/Mage/src/mage/filter/FilterObject.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.filter; import mage.MageObject; @@ -46,7 +45,7 @@ public class FilterObject extends FilterImpl { super(name); } - public FilterObject(FilterObject filter) { + public FilterObject(FilterObject filter) { super(filter); } } diff --git a/Mage/src/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java b/Mage/src/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java index 787a14d2ac..7284bd1943 100644 --- a/Mage/src/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java +++ b/Mage/src/mage/filter/predicate/mageobject/NumberOfTargetsPredicate.java @@ -34,7 +34,6 @@ import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.stack.Spell; import mage.target.Target; -import mage.target.Targets; /** * @@ -57,7 +56,7 @@ public class NumberOfTargetsPredicate implements Predicate { Mode mode = spell.getSpellAbility().getModes().get(modeId); for (Target target : mode.getTargets()) { numberOfTargets += target.getTargets().size(); - } + } } if (numberOfTargets == targets) { return true; diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index e4c858c6d4..2b0cd6990c 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -390,6 +390,11 @@ public abstract class GameImpl implements Game, Serializable { object = state.getBattlefield().getPermanent(objectId); return object; } + // can be an ability of a sacrificed Token trying to get it's source object + object = getLastKnownInformation(objectId, Zone.BATTLEFIELD); + if (object != null) { + return object; + } for (CommandObject commandObject : state.getCommand()) { if (commandObject instanceof Commander && commandObject.getId().equals(objectId)) { return commandObject; @@ -402,8 +407,6 @@ public abstract class GameImpl implements Game, Serializable { return commandObject; } } - // can be an ability of a sacrificed Token trying to get it's source object - object = getLastKnownInformation(objectId, Zone.BATTLEFIELD); } return object; } diff --git a/Mage/src/mage/game/stack/StackAbility.java b/Mage/src/mage/game/stack/StackAbility.java index 0ab2eeb7ba..aa8d58de40 100644 --- a/Mage/src/mage/game/stack/StackAbility.java +++ b/Mage/src/mage/game/stack/StackAbility.java @@ -1,41 +1,45 @@ /* -* 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. -*/ - + * 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.game.stack; -import mage.constants.AbilityType; -import mage.constants.CardType; -import mage.constants.EffectType; -import mage.constants.Zone; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.ObjectColor; -import mage.abilities.*; +import mage.abilities.Abilities; +import mage.abilities.AbilitiesImpl; +import mage.abilities.Ability; +import mage.abilities.MageSingleton; +import mage.abilities.Mode; +import mage.abilities.Modes; +import mage.abilities.StateTriggeredAbility; import mage.abilities.costs.AlternativeCost; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; @@ -45,19 +49,19 @@ import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; +import mage.cards.Card; import mage.choices.Choice; import mage.choices.Choices; -import mage.game.Game; -import mage.target.Target; -import mage.target.Targets; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import mage.cards.Card; +import mage.constants.AbilityType; import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.EffectType; +import mage.constants.Zone; +import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import mage.target.Target; +import mage.target.Targets; import mage.util.GameLog; import mage.watchers.Watcher; @@ -96,7 +100,7 @@ public class StackAbility extends StackObjImpl implements Ability { public boolean isActivated() { return ability.isActivated(); } - + @Override public boolean resolve(Game game) { if (ability.getTargets().stillLegal(ability, game)) { @@ -110,13 +114,14 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public void reset(Game game) { } + public void reset(Game game) { + } @Override public void counter(UUID sourceId, Game game) { //20100716 - 603.8 if (ability instanceof StateTriggeredAbility) { - ((StateTriggeredAbility)ability).counter(game); + ((StateTriggeredAbility) ability).counter(game); } } @@ -127,14 +132,14 @@ public class StackAbility extends StackObjImpl implements Ability { @Override public String getIdName() { - return getName() + " ["+getId().toString().substring(0,3) +"]"; + return getName() + " [" + getId().toString().substring(0, 3) + "]"; } - + @Override public String getLogName() { return GameLog.getColoredObjectIdName(this); } - + @Override public String getImageName() { return name; @@ -221,9 +226,9 @@ public class StackAbility extends StackObjImpl implements Ability { @Override public int getConvertedManaCost() { - // Activated abilities have an "activation cost" but they don't have a characteristic related to that while on the stack. + // Activated abilities have an "activation cost" but they don't have a characteristic related to that while on the stack. // There are certain effects that interact with the cost to activate an ability (e.g., Training Grounds, Power Artifact) - // but nothing that looks for that quality of an ability once it's on the stack. + // but nothing that looks for that quality of an ability once it's on the stack. return 0; } @@ -258,13 +263,16 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public void setSourceId(UUID sourceID) {} + public void setSourceId(UUID sourceID) { + } @Override - public void addCost(Cost cost) {} + public void addCost(Cost cost) { + } @Override - public void addEffect(Effect effect) {} + public void addEffect(Effect effect) { + } @Override public boolean activate(Game game, boolean noMana) { @@ -277,7 +285,8 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public void addTarget(Target target) {} + public void addTarget(Target target) { + } @Override public UUID getFirstTarget() { @@ -290,7 +299,8 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public void addChoice(Choice choice) {} + public void addChoice(Choice choice) { + } @Override public List getAlternativeCosts() { @@ -298,7 +308,8 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public void addAlternativeCost(AlternativeCost cost) { } + public void addAlternativeCost(AlternativeCost cost) { + } @Override public ManaCosts getManaCosts() { @@ -306,12 +317,13 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public ManaCosts getManaCostsToPay ( ) { + public ManaCosts getManaCostsToPay() { return ability.getManaCostsToPay(); } @Override - public void addManaCost(ManaCost cost) { } + public void addManaCost(ManaCost cost) { + } @Override public AbilityType getAbilityType() { @@ -329,7 +341,7 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public void setName(String name) { + public void setName(String name) { this.name = name; } @@ -344,7 +356,7 @@ public class StackAbility extends StackObjImpl implements Ability { card.adjustChoices(ability, game); } } - + @Override public void adjustCosts(Ability ability, Game game) { Card card = game.getCard(ability.getSourceId()); @@ -367,7 +379,8 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public void addOptionalCost(Cost cost) {} + public void addOptionalCost(Cost cost) { + } @Override public boolean checkIfClause(Game game) { @@ -382,7 +395,8 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public void newOriginalId() {} + public void newOriginalId() { + } @Override public Ability getStackAbility() { @@ -395,7 +409,8 @@ public class StackAbility extends StackObjImpl implements Ability { } @Override - public void addMode(Mode mode) {} + public void addMode(Mode mode) { + } @Override public Modes getModes() { @@ -455,7 +470,7 @@ public class StackAbility extends StackObjImpl implements Ability { public void setAdditionalCostsRuleVisible(boolean ruleAdditionalCostsVisible) { this.ability.setAdditionalCostsRuleVisible(ruleAdditionalCostsVisible); } - + @Override public UUID getOriginalId() { return this.ability.getOriginalId(); @@ -478,7 +493,7 @@ public class StackAbility extends StackObjImpl implements Ability { @Override public void setCostModificationActive(boolean active) { - throw new UnsupportedOperationException("Not supported. Only neede for flashbacked spells"); + throw new UnsupportedOperationException("Not supported. Only neede for flashbacked spells"); } @Override @@ -500,7 +515,7 @@ public class StackAbility extends StackObjImpl implements Ability { public void addWatcher(Watcher watcher) { throw new UnsupportedOperationException("Not supported."); } - + @Override public List getSubAbilities() { return this.ability.getSubAbilities(); @@ -513,7 +528,7 @@ public class StackAbility extends StackObjImpl implements Ability { @Override public MageObject getSourceObject(Game game) { - throw new UnsupportedOperationException("Not supported."); + return game.getBaseObject(getSourceId()); } @Override @@ -529,7 +544,7 @@ public class StackAbility extends StackObjImpl implements Ability { @Override public void setSourceObject(MageObject sourceObject, Game game) { throw new UnsupportedOperationException("Not supported."); - } + } @Override public int getZoneChangeCounter(Game game) {