diff --git a/Mage.Client/plugins/sounds/OnPlayerJoinedTable.wav b/Mage.Client/plugins/sounds/OnPlayerJoinedTable.wav new file mode 100644 index 00000000000..a8c11bb354e Binary files /dev/null and b/Mage.Client/plugins/sounds/OnPlayerJoinedTable.wav differ diff --git a/Mage.Client/release/backgrounds/Blue-Abstract.jpg b/Mage.Client/release/backgrounds/Blue-Abstract.jpg new file mode 100644 index 00000000000..dc16db47092 Binary files /dev/null and b/Mage.Client/release/backgrounds/Blue-Abstract.jpg differ diff --git a/Mage.Client/release/backgrounds/Distant-Galaxy.jpg b/Mage.Client/release/backgrounds/Distant-Galaxy.jpg new file mode 100644 index 00000000000..a8e1c1c0153 Binary files /dev/null and b/Mage.Client/release/backgrounds/Distant-Galaxy.jpg differ diff --git a/Mage.Client/release/backgrounds/Galaxy.jpg b/Mage.Client/release/backgrounds/Galaxy.jpg new file mode 100644 index 00000000000..5de98c77430 Binary files /dev/null and b/Mage.Client/release/backgrounds/Galaxy.jpg differ diff --git a/Mage.Client/release/backgrounds/Gray.jpg b/Mage.Client/release/backgrounds/Gray.jpg new file mode 100644 index 00000000000..284a678ea93 Binary files /dev/null and b/Mage.Client/release/backgrounds/Gray.jpg differ diff --git a/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Adam Moore's Beck and Affinity.txt.dck b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Adam Moore's Beck and Affinity.txt.dck new file mode 100644 index 00000000000..720432a7664 --- /dev/null +++ b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Adam Moore's Beck and Affinity.txt.dck @@ -0,0 +1,17 @@ +NAME:Adam Moore's Beck and Affinity +4 [DDF:72] Darksteel Citadel +4 [GTC:240] Breeding Pool +4 [MBS:145] Inkmoth Nexus +4 [NPH:76] Vault Skirge +4 [MMA:207] Frogmite +4 [MMA:223] Glimmervoid +3 [LRW:261] Springleaf Drum +4 [M11:211] Ornithopter +3 [SOM:179] Mox Opal +2 [SOM:122] Genesis Wave +4 [MMA:209] Myr Enforcer +4 [DGM:123] Beck // Call +4 [DDF:71] Thoughtcast +4 [SOM:174] Memnite +4 [MBS:131] Signal Pest +4 [DDF:44] Steel Overseer diff --git a/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Daniel Watson's Zhur-Taawin.txt.dck b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Daniel Watson's Zhur-Taawin.txt.dck new file mode 100644 index 00000000000..3c928fc7432 --- /dev/null +++ b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Daniel Watson's Zhur-Taawin.txt.dck @@ -0,0 +1,17 @@ +NAME:Daniel Watson's Zhur-Taawin +4 [MMA:59] Pestermite +3 [SOM:225] Copperline Gorge +2 [NPH:159] Spellskite +4 [ROE:165] Splinter Twin +4 [M12:63] Mana Leak +4 [NPH:33] Deceiver Exarch +4 [CHK:234] Orochi Leafcaller +4 [GTC:240] Breeding Pool +4 [MMA:56] Pact of Negation +4 [DGM:120] Zhur-Taa Druid +4 [GTC:247] Stomping Ground +4 [ZEN:229] Verdant Catacombs +3 [MMA:120] Kiki-Jiki, Mirror Breaker +4 [SOK:38] Freed from the Real +4 [RTR:247] Steam Vents +4 [ZEN:220] Misty Rainforest diff --git a/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Elias Rudin's RUG Vial.dck b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Elias Rudin's RUG Vial.dck new file mode 100644 index 00000000000..54ed5861f5d --- /dev/null +++ b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Elias Rudin's RUG Vial.dck @@ -0,0 +1,24 @@ +NAME:Elias Rudin's RUG Vial +4 [MMA:166] Tarmogoyf +4 [SOM:225] Copperline Gorge +1 [ZEN:67] Spell Pierce +4 [ZEN:223] Scalding Tarn +4 [ISD:78] Snapcaster Mage +3 [EVE:177] Flooded Grove +2 [M12:63] Mana Leak +1 [GTC:240] Breeding Pool +1 [MMA:64] Spell Snare +4 [M11:149] Lightning Bolt +3 [MMA:144] Eternal Witness +1 [GTC:247] Stomping Ground +1 [RTR:265] Mountain +3 [RAV:63] Remand +3 [DKA:140] Huntmaster of the Fells +1 [MMA:190] Kitchen Finks +4 [MMA:197] AEther Vial +1 [RTR:247] Steam Vents +3 [ZEN:220] Misty Rainforest +4 [RTR:255] Island +4 [MMA:38] Cryptic Command +3 [MMA:70] Vendilion Clique +1 [RTR:270] Forest diff --git a/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Liam Puknys's Possibility Brand.dck b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Liam Puknys's Possibility Brand.dck new file mode 100644 index 00000000000..844e91ad7af --- /dev/null +++ b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Liam Puknys's Possibility Brand.dck @@ -0,0 +1,19 @@ +NAME:Liam Puknys's Possibility Brand +1 [ROE:4] Emrakul, the Aeons Torn +2 [AVR:106] Griselbrand +4 [ZEN:223] Scalding Tarn +4 [GTC:240] Breeding Pool +4 [GTC:247] Stomping Ground +4 [DKA:87] Faithless Looting +2 [ROE:6] Kozilek, Butcher of Truth +4 [RTR:247] Steam Vents +4 [M11:211] Ornithopter +4 [DGM:34] Possibility Storm +4 [WWK:37] Selective Memory +1 [M13:63] Omniscience +4 [ZEN:220] Misty Rainforest +4 [M13:160] Arbor Elf +4 [DGM:123] Beck // Call +4 [ZEN:211] Arid Mesa +2 [CMD:1] Artisan of Kozilek +4 [SOM:174] Memnite diff --git a/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Trevor Cashmore's Just Kiln Time.dck b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Trevor Cashmore's Just Kiln Time.dck new file mode 100644 index 00000000000..944e92278e0 --- /dev/null +++ b/Mage.Client/release/sample-decks/2013/Modern/DailyMTG/Trevor Cashmore's Just Kiln Time.dck @@ -0,0 +1,18 @@ +NAME:Trevor Cashmore's Just Kiln Time +4 [ISD:248] Sulfur Falls +2 [ZEN:67] Spell Pierce +4 [ZEN:223] Scalding Tarn +4 [ROE:153] Kiln Fiend +4 [SOM:82] Assault Strobe +3 [5DN:36] Serum Visions +2 [DKA:27] Artful Dodge +4 [NPH:2] Apostle's Blessing +4 [ROE:60] Distortion Strike +4 [MMA:191] Manamorphose +2 [RTR:265] Mountain +4 [RTR:247] Steam Vents +4 [NPH:116] Mutagenic Growth +4 [RTR:255] Island +3 [9ED:99] Sleight of Hand +4 [DGM:87] Nivix Cyclops +4 [NPH:35] Gitaxian Probe diff --git a/Mage.Client/release/sample-decks/2013/Modern/Modern Romance/Gadin's Robots.dck b/Mage.Client/release/sample-decks/2013/Modern/Modern Romance/Gadin's Robots.dck new file mode 100644 index 00000000000..7847a4cf292 --- /dev/null +++ b/Mage.Client/release/sample-decks/2013/Modern/Modern Romance/Gadin's Robots.dck @@ -0,0 +1,28 @@ +NAME:Gadin's Robots +4 [DDF:72] Darksteel Citadel +3 [MMA:220] Blinkmoth Nexus +3 [MBS:145] Inkmoth Nexus +4 [NPH:76] Vault Skirge +4 [HOP:110] Cranial Plating +4 [MMA:223] Glimmervoid +3 [LRW:261] Springleaf Drum +2 [MMA:198] Arcbound Ravager +1 [RTR:265] Mountain +3 [SOM:154] Etched Champion +4 [DDF:48] Master of Etherium +4 [M11:211] Ornithopter +3 [SOM:179] Mox Opal +4 [SOM:91] Galvanic Blast +4 [DDF:71] Thoughtcast +1 [RTR:255] Island +3 [SOM:174] Memnite +3 [MBS:131] Signal Pest +3 [DDF:44] Steel Overseer +SB: 1 [ROE:92] Unified Will +SB: 3 [NPH:159] Spellskite +SB: 1 [NPH:102] Whipflare +SB: 3 [MMA:213] Relic of Progenitus +SB: 1 [M13:62] Negate +SB: 3 [MMA:106] Blood Moon +SB: 2 [PC2:7] Ghostly Prison +SB: 1 [ISD:127] Ancient Grudge diff --git a/Mage.Client/release/sample-decks/2013/Standard/DailyMTG/Robert Seder's Esper Control.dck b/Mage.Client/release/sample-decks/2013/Standard/DailyMTG/Robert Seder's Esper Control.dck new file mode 100644 index 00000000000..a5e7c1ed67d --- /dev/null +++ b/Mage.Client/release/sample-decks/2013/Standard/DailyMTG/Robert Seder's Esper Control.dck @@ -0,0 +1,33 @@ +NAME:Robert Seder's Esper Control +1 [DKA:142] Sorin, Lord of Innistrad +1 [DGM:11] AEtherling +4 [M13:225] Glacial Fortress +3 [ISD:83] Think Twice +3 [RTR:145] Azorius Charm +4 [ISD:78] Snapcaster Mage +2 [RTR:54] Syncopate +4 [GTC:249] Watery Grave +1 [M13:56] Jace, Memory Adept +1 [RTR:35] Cyclonic Rift +1 [AVR:79] Tamiyo, the Moon Sage +1 [AVR:32] Restoration Angel +2 [RTR:44] Jace, Architect of Thought +4 [ISD:242] Isolated Chapel +4 [DGM:127] Far // Away +4 [ISD:245] Nephalia Drownyard +2 [ISD:53] Dissipate +4 [AVR:38] Terminus +4 [RTR:241] Hallowed Fountain +4 [M13:223] Drowned Catacomb +3 [GTC:242] Godless Shrine +4 [RTR:200] Sphinx's Revelation +SB: 2 [DKA:76] Tragic Slip +SB: 2 [M13:26] Planar Cleansing +SB: 1 [GTC:63] Devour Flesh +SB: 1 [ISD:212] Evil Twin +SB: 1 [RTR:18] Rest in Peace +SB: 1 [ISD:27] Purify the Grave +SB: 3 [M13:62] Negate +SB: 1 [RTR:47] Psychic Spiral +SB: 1 [M13:56] Jace, Memory Adept +SB: 1 [ISD:119] Tribute to Hunger diff --git a/Mage.Client/src/main/java/mage/client/components/HoverButton.java b/Mage.Client/src/main/java/mage/client/components/HoverButton.java index 4d78bbc3c11..fc8ac09de2c 100644 --- a/Mage.Client/src/main/java/mage/client/components/HoverButton.java +++ b/Mage.Client/src/main/java/mage/client/components/HoverButton.java @@ -26,8 +26,11 @@ public class HoverButton extends JPanel implements MouseListener { private int textOffsetY = 0; private int textOffsetButtonY = 2; private int textOffsetX = -1; + private int topTextOffsetX = -1; private Dimension overlayImageSize; + private String topText; + private boolean isHovered = false; private boolean isSelected = false; private boolean drawSet = false; @@ -36,6 +39,7 @@ public class HoverButton extends JPanel implements MouseListener { private Command observer = null; private Command onHover = null; private Color textColor = Color.white; + private Color textBGColor = Color.black; static final Font textFont = new Font("Arial", Font.PLAIN, 12); static final Font textFontMini = new Font("Arial", Font.PLAIN, 11); @@ -100,6 +104,18 @@ public class HoverButton extends JPanel implements MouseListener { } else { g.drawImage(disabledImage, 0, 0, imageSize.width, imageSize.height, this); } + if (topText != null) { + if (useMiniFont) { + g2d.setFont(textFontMini); + } else { + g2d.setFont(textFont); + } + topTextOffsetX = calculateOffsetForTop(g2d, topText); + g2d.setColor(textBGColor); + g2d.drawString(topText, topTextOffsetX+1, 13); + g2d.setColor(textColor); + g2d.drawString(topText, topTextOffsetX, 12); + } if (overlayImage != null) { g.drawImage(overlayImage, (imageSize.width - overlayImageSize.width) / 2, 10, this); } else if (set != null) { @@ -136,6 +152,15 @@ public class HoverButton extends JPanel implements MouseListener { return textOffsetX; } + private int calculateOffsetForTop(Graphics2D g2d, String text) { + if (topTextOffsetX == -1) { // calculate once + FontRenderContext frc = g2d.getFontRenderContext(); + int textWidth = (int) textFont.getStringBounds(text, frc).getWidth(); + topTextOffsetX = (imageSize.width - textWidth) / 2; + } + return topTextOffsetX; + } + public void setTextColor(Color textColor) { this.textColor = textColor; } @@ -242,4 +267,8 @@ public class HoverButton extends JPanel implements MouseListener { observer.execute(); } } + + public void setTopText(String topText) { + this.topText = topText; + } } diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java index 95a8b39973e..c4090addec9 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -102,12 +102,12 @@ public class DeckEditorPanel extends javax.swing.JPanel { @Override public void actionPerformed(ActionEvent e) { if (--timeout > 0) { - setTimeout(Integer.toString(timeout)); + setTimeout(timeout); } else { if (updateDeckTask != null) updateDeckTask.cancel(true); - setTimeout("0"); + setTimeout(0); countdown.stop(); hideDeckEditor(); } @@ -136,7 +136,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { this.deckArea.showSideboard(false); countdown.stop(); this.timeout = time; - setTimeout(Integer.toString(timeout)); + setTimeout(timeout); if (timeout != 0) { countdown.start(); if (updateDeckTask == null || updateDeckTask.isDone()) { @@ -308,7 +308,20 @@ public class DeckEditorPanel extends javax.swing.JPanel { } } - private void setTimeout(String text) { + private void setTimeout(int s){ + int minute = s/60; + int second = s - (minute*60); + String text; + if(minute < 10){ + text = "0" + Integer.toString(minute) + ":"; + }else{ + text = Integer.toString(minute) + ":"; + } + if(second < 10){ + text = text + "0" + Integer.toString(second); + }else{ + text = text + Integer.toString(second); + } this.txtTimeRemaining.setText(text); } diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form index 5dfc2743e95..ff9e1bb9b35 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form @@ -25,41 +25,49 @@ - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + - - - + + + + + - - - + - - + + @@ -88,6 +96,7 @@ + @@ -98,7 +107,7 @@ - + @@ -107,17 +116,19 @@ - - - - - - - + + + + + + + + + @@ -157,10 +168,12 @@ - + + + - + @@ -174,7 +187,7 @@ - + @@ -198,6 +211,14 @@ + + + + + + + + @@ -211,6 +232,7 @@ + @@ -264,6 +286,7 @@ + @@ -281,6 +304,8 @@ + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java index 655f289493e..0fd129f5f72 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java @@ -27,21 +27,23 @@ */ package mage.client.dialog; - import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import javax.swing.*; -import mage.constants.MultiplayerAttackOption; -import mage.constants.RangeOfInfluence; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JOptionPane; +import javax.swing.SpinnerNumberModel; import mage.cards.decks.importer.DeckImporterUtil; import mage.client.MageFrame; import mage.client.components.MageComponents; -import mage.client.table.*; +import mage.client.table.TablePlayerPanel; import mage.client.util.Event; import mage.client.util.Listener; +import mage.constants.MatchTimeLimit; +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; import mage.game.match.MatchOptions; import mage.remote.Session; import mage.view.GameTypeView; @@ -85,6 +87,8 @@ public class NewTableDialog extends MageDialog { txtName = new javax.swing.JTextField(); lbDeckType = new javax.swing.JLabel(); cbDeckType = new javax.swing.JComboBox(); + lbTimeLimit = new javax.swing.JLabel(); + cbTimeLimit = new javax.swing.JComboBox(); lblGameType = new javax.swing.JLabel(); cbGameType = new javax.swing.JComboBox(); lblFreeMulligans = new javax.swing.JLabel(); @@ -114,6 +118,9 @@ public class NewTableDialog extends MageDialog { lbDeckType.setText("Deck Type:"); + lbTimeLimit.setText("Time Limit:"); + lbTimeLimit.setToolTipText("The activie time a player may use to finish the match. If the time runs out, the player looses the current game."); + lblGameType.setText("Game Type:"); cbGameType.addActionListener(new java.awt.event.ActionListener() { @@ -123,6 +130,7 @@ public class NewTableDialog extends MageDialog { }); lblFreeMulligans.setText("Free Mulligans:"); + lblFreeMulligans.setToolTipText("The number of mulligans a player can use without decreasing the number of drawn cards."); lblNumPlayers.setLabelFor(spnNumPlayers); lblNumPlayers.setText("Players"); @@ -141,6 +149,7 @@ public class NewTableDialog extends MageDialog { lblNumWins.setLabelFor(spnNumWins); lblNumWins.setText("Wins"); + lblNumWins.setToolTipText("How many games has a player to win to win the match."); spnNumWins.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { @@ -177,33 +186,39 @@ public class NewTableDialog extends MageDialog { .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel1)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel2)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() .addGap(16, 16, 16) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lbDeckType) .addComponent(lblGameType) - .addComponent(lblName)) + .addComponent(lblName))) + .addGroup(layout.createSequentialGroup() + .addGap(30, 30, 30) + .addComponent(lbDeckType))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 398, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblFreeMulligans) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 9, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(cbDeckType, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 398, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 546, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addComponent(cbDeckType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lbTimeLimit) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnFreeMulligans, javax.swing.GroupLayout.DEFAULT_SIZE, 50, Short.MAX_VALUE)) - .addComponent(txtName)))) - .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE)))))) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(btnOK) @@ -233,27 +248,30 @@ public class NewTableDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 625, Short.MAX_VALUE) + .addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 633, Short.MAX_VALUE) .addContainerGap())) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(lblName) .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lbDeckType) - .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblGameType) + .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lbDeckType) + .addComponent(lbTimeLimit)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblFreeMulligans))) + .addComponent(lblFreeMulligans)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblGameType))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) @@ -282,7 +300,7 @@ public class NewTableDialog extends MageDialog { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) + .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 181, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -294,7 +312,7 @@ public class NewTableDialog extends MageDialog { .addGroup(layout.createSequentialGroup() .addGap(201, 201, 201) .addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(240, Short.MAX_VALUE))) + .addContainerGap(252, Short.MAX_VALUE))) ); pack(); @@ -315,6 +333,7 @@ public class NewTableDialog extends MageDialog { } options.setDeckType((String) this.cbDeckType.getSelectedItem()); options.setLimited(false); + options.setMatchTimeLimit((MatchTimeLimit) this.cbTimeLimit.getSelectedItem()); options.setAttackOption((MultiplayerAttackOption) this.cbAttackOption.getSelectedItem()); options.setRange((RangeOfInfluence) this.cbRange.getSelectedItem()); options.setWinsNeeded((Integer)this.spnNumWins.getValue()); @@ -422,6 +441,7 @@ public class NewTableDialog extends MageDialog { cbGameType.setModel(new DefaultComboBoxModel(session.getGameTypes().toArray())); cbDeckType.setModel(new DefaultComboBoxModel(session.getDeckTypes())); selectLimitedByDefault(); + cbTimeLimit.setModel(new DefaultComboBoxModel(MatchTimeLimit.values())); cbRange.setModel(new DefaultComboBoxModel(RangeOfInfluence.values())); cbAttackOption.setModel(new DefaultComboBoxModel(MultiplayerAttackOption.values())); @@ -464,13 +484,19 @@ public class NewTableDialog extends MageDialog { break; } } + int timeLimit = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_TIME_LIMIT, "1500")); + for (MatchTimeLimit mtl :MatchTimeLimit.values()) { + if (mtl.getTimeLimit() == timeLimit) { + this.cbTimeLimit.setSelectedItem(mtl); + break; + } + } cbDeckType.setSelectedItem(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_DECK_TYPE, "Limited")); String deckFile = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_DECK_FILE, null); if (deckFile != null) { this.player1Panel.setDeckFile(deckFile); } this.spnNumWins.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_WINS, "2"))); - this.spnFreeMulligans.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS, "0"))); this.spnNumPlayers.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_PLAYERS, "2"))); int range = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, "1")); for (RangeOfInfluence roi :RangeOfInfluence.values()) { @@ -497,9 +523,9 @@ public class NewTableDialog extends MageDialog { private void saveGameSettingsToPrefs(MatchOptions options, String deckFile) { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NAME, options.getName()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_DECK_TYPE, options.getDeckType()); + PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_TIME_LIMIT, Integer.toString(options.getPriorityTime())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_GAME_TYPE, options.getGameType()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_WINS, Integer.toString(options.getWinsNeeded())); - PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS, Integer.toString(options.getFreeMulligans())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_DECK_FILE, deckFile); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_PLAYERS, spnNumPlayers.getValue().toString()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, Integer.toString(options.getRange().getRange())); @@ -513,12 +539,14 @@ public class NewTableDialog extends MageDialog { private javax.swing.JComboBox cbDeckType; private javax.swing.JComboBox cbGameType; private javax.swing.JComboBox cbRange; + private javax.swing.JComboBox cbTimeLimit; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JSeparator jSeparator1; private javax.swing.JSeparator jSeparator2; private javax.swing.JSeparator jSeparator3; private javax.swing.JLabel lbDeckType; + private javax.swing.JLabel lbTimeLimit; private javax.swing.JLabel lblAttack; private javax.swing.JLabel lblFreeMulligans; private javax.swing.JLabel lblGameType; @@ -534,4 +562,4 @@ public class NewTableDialog extends MageDialog { private javax.swing.JTextField txtName; // End of variables declaration//GEN-END:variables -} \ No newline at end of file +} diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form index a11795a9219..fb97f4a2e45 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form @@ -27,54 +27,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -85,39 +88,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - + @@ -140,6 +134,13 @@ + + + + + + + @@ -233,7 +234,7 @@ - + diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index 497513246e2..16f567f10c5 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -41,12 +41,13 @@ import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JOptionPane; import javax.swing.SpinnerNumberModel; -import mage.constants.MultiplayerAttackOption; -import mage.constants.RangeOfInfluence; import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.client.MageFrame; import mage.client.table.TournamentPlayerPanel; +import mage.constants.MatchTimeLimit; +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; import mage.game.draft.DraftOptions; import mage.game.draft.DraftOptions.TimingOption; import mage.game.tournament.LimitedOptions; @@ -86,6 +87,7 @@ public class NewTournamentDialog extends MageDialog { session = MageFrame.getSession(); this.txtPlayer1Name.setText(session.getUserName()); cbTournamentType.setModel(new DefaultComboBoxModel(session.getTournamentTypes().toArray())); + cbTimeLimit.setModel(new DefaultComboBoxModel(MatchTimeLimit.values())); cbDraftTiming.setModel(new DefaultComboBoxModel(DraftOptions.TimingOption.values())); this.setModal(true); setTournamentOptions(); @@ -104,6 +106,8 @@ public class NewTournamentDialog extends MageDialog { lblName = new javax.swing.JLabel(); txtName = new javax.swing.JTextField(); + lbTimeLimit = new javax.swing.JLabel(); + cbTimeLimit = new javax.swing.JComboBox(); lblConstructionTime = new javax.swing.JLabel(); spnConstructTime = new javax.swing.JSpinner(); jLabel1 = new javax.swing.JLabel(); @@ -131,6 +135,8 @@ public class NewTournamentDialog extends MageDialog { lblName.setText("Name:"); + lbTimeLimit.setText("Time Limit:"); + lblConstructionTime.setText("Construction Time (Minutes):"); jLabel1.setText("Tournament Type:"); @@ -198,7 +204,7 @@ public class NewTournamentDialog extends MageDialog { .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() .addComponent(jLabel4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtPlayer1Name, javax.swing.GroupLayout.DEFAULT_SIZE, 638, Short.MAX_VALUE))) + .addComponent(txtPlayer1Name))) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( @@ -247,76 +253,76 @@ public class NewTournamentDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lblName) - .addComponent(jLabel1)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(txtName) - .addComponent(cbTournamentType, 0, 330, Short.MAX_VALUE)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lblFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lblNumWins)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(19, 19, 19) - .addComponent(lblConstructionTime))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(spnConstructTime, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE) - .addComponent(spnNumWins))) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(btnOk) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(btnCancel)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlDraftOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING)) - .addGap(0, 0, Short.MAX_VALUE))) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pnlDraftOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(lblName) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 233, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbTimeLimit) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbTimeLimit, 0, 115, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbTournamentType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(lblConstructionTime) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(lblFreeMulligans) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblNumWins) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)))))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblName)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel1) - .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblConstructionTime) - .addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblNumWins) - .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblFreeMulligans)))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblName) + .addComponent(lbTimeLimit) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblConstructionTime) + .addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblFreeMulligans) + .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblNumWins) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 65, Short.MAX_VALUE) + .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 62, Short.MAX_VALUE) .addGap(11, 11, 11) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(spnNumPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE) + .addComponent(spnNumPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE) .addComponent(pnlDraftOptions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel2)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -351,12 +357,13 @@ public class NewTournamentDialog extends MageDialog { if (tournamentType.isLimited()) { if (tOptions.getLimitedOptions() == null) { tOptions.setLimitedOptions(new LimitedOptions()); - tOptions.getLimitedOptions().setConstructionTime((Integer)this.spnConstructTime.getValue()); + tOptions.getLimitedOptions().setConstructionTime((Integer)this.spnConstructTime.getValue() * 60); } for (JComboBox pack: packs) { tOptions.getLimitedOptions().getSetCodes().add(((ExpansionSet) pack.getSelectedItem()).getCode()); } } + tOptions.getMatchOptions().setMatchTimeLimit((MatchTimeLimit) this.cbTimeLimit.getSelectedItem()); tOptions.getMatchOptions().setDeckType("Limited"); tOptions.getMatchOptions().setWinsNeeded((Integer)this.spnNumWins.getValue()); tOptions.getMatchOptions().setFreeMulligans((Integer)this.spnFreeMulligans.getValue()); @@ -512,6 +519,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JButton btnCancel; private javax.swing.JButton btnOk; private javax.swing.JComboBox cbDraftTiming; + private javax.swing.JComboBox cbTimeLimit; private javax.swing.JComboBox cbTournamentType; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; @@ -520,6 +528,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; private javax.swing.JPanel jPanel1; + private javax.swing.JLabel lbTimeLimit; private javax.swing.JLabel lblConstructionTime; private javax.swing.JLabel lblFreeMulligans; private javax.swing.JLabel lblName; 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 3248afeff32..46f230051d6 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -92,6 +92,7 @@ public class PreferencesDialog extends javax.swing.JDialog { // default setting for new table dialog public static final String KEY_NEW_TABLE_NAME = "newTableName"; public static final String KEY_NEW_TABLE_DECK_TYPE = "newTableDeckType"; + public static final String KEY_NEW_TABLE_TIME_LIMIT = "newTableTimeLimit"; public static final String KEY_NEW_TABLE_GAME_TYPE = "newTableGameType"; public static final String KEY_NEW_TABLE_NUMBER_OF_WINS = "newTableNumberOfWins"; public static final String KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS = "newTableNumberOfFreeMulligans"; @@ -154,24 +155,18 @@ public class PreferencesDialog extends javax.swing.JDialog { private final JFileChooser fc_i = new JFileChooser(); { fc_i.setAcceptAllFileFilterUsed(false); - fc_i.addChoosableFileFilter(new ImageFileFilter(".jpg")); - fc_i.addChoosableFileFilter(new ImageFileFilter(".jpeg")); - fc_i.addChoosableFileFilter(new ImageFileFilter(".png")); - fc_i.addChoosableFileFilter(new ImageFileFilter(".bmp")); + fc_i.addChoosableFileFilter(new ImageFileFilter()); } private static class ImageFileFilter extends FileFilter{ - String extend; - public ImageFileFilter(String extend){ - this.extend = extend; - } @Override public boolean accept(File f) { String filename = f.getName(); if(f.isDirectory()) return true; if(filename != null){ - if(filename.endsWith(extend)){ + if(filename.endsWith(".jpg") || filename.endsWith(".jpeg") || + filename.endsWith(".png") || filename.endsWith(".bmp")){ return true; } } @@ -180,13 +175,8 @@ public class PreferencesDialog extends javax.swing.JDialog { @Override public String getDescription() { - if(extend.equals(".png") || extend.equals(".bmp")) - return "Image File(*.png, *.bmp)"; - if(extend.equals(".jpg") || extend.equals(".jpg")) - return "JEGP file(*.jpg,*.jepg)"; - return ""; - } - + return "*.png | *.bmp |*.jpg | *.jpeg"; + } } diff --git a/Mage.Client/src/main/java/mage/client/dialog/TableWaitingDialog.java b/Mage.Client/src/main/java/mage/client/dialog/TableWaitingDialog.java index 99a5dd0c6b7..6d1a0666b1c 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/TableWaitingDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/TableWaitingDialog.java @@ -49,6 +49,7 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; +import mage.client.util.AudioManager; /** * @@ -392,6 +393,7 @@ class UpdateSeatsTask extends SwingWorker { if (count > 0) { if (current > count) { MageTray.getInstance().displayMessage("New player joined your game."); + AudioManager.playPlayerJoinedTable(); } else { MageTray.getInstance().displayMessage("A player left your game."); } 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 a81eea2ce76..7b02c770fa7 100644 --- a/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java +++ b/Mage.Client/src/main/java/mage/client/draft/DraftPanel.java @@ -78,10 +78,10 @@ public class DraftPanel extends javax.swing.JPanel { @Override public void actionPerformed(ActionEvent e) { if (--timeout > 0) { - setTimeout(Integer.toString(timeout)); + setTimeout(timeout); } else { - setTimeout("0"); + setTimeout(0); countdown.stop(); } } @@ -119,7 +119,6 @@ public class DraftPanel extends javax.swing.JPanel { SimpleCardView source = (SimpleCardView) event.getSource(); DraftPickView view = session.sendCardPick(draftId, source.getId()); if (view != null) { - //draftBooster.loadBooster(view.getBooster(), bigCard); draftBooster.loadBooster(emptyView, bigCard); draftPicks.loadCards(CardsViewUtil.convertSimple(view.getPicks()), bigCard, null); Plugins.getInstance().getActionCallback().hidePopup(); @@ -132,13 +131,26 @@ public class DraftPanel extends javax.swing.JPanel { setMessage("Pick a card"); countdown.stop(); this.timeout = draftPickView.getTimeout(); - setTimeout(Integer.toString(timeout)); + setTimeout(timeout); if (timeout != 0) { countdown.start(); } } - - private void setTimeout(String text) { + + private void setTimeout(int s){ + int minute = s/60; + int second = s - (minute*60); + String text; + if(minute < 10){ + text = "0" + Integer.toString(minute) + ":"; + }else{ + text = Integer.toString(minute) + ":"; + } + if(second < 10){ + text = text + "0" + Integer.toString(second); + }else{ + text = text + Integer.toString(second); + } this.txtTimeRemaining.setText(text); } diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index d5e08a492e4..fa4137f8435 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -353,7 +353,7 @@ public final class GamePanel extends javax.swing.JPanel { } } PlayerView player = game.getPlayers().get(playerSeat); - PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId, true); + PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId, true, game.getPriorityTime()); players.put(player.getPlayerId(), sessionPlayer); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; @@ -385,7 +385,7 @@ public final class GamePanel extends javax.swing.JPanel { col = numColumns - 1; } player = game.getPlayers().get(playerNum); - PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, false); + PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, false, game.getPriorityTime()); players.put(player.getPlayerId(), playerPanel); c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; diff --git a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java index 5f763feb966..48a77a1ec33 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java @@ -64,9 +64,9 @@ public class PlayAreaPanel extends javax.swing.JPanel { addPopupMenu(); } - public PlayAreaPanel(PlayerView player, BigCard bigCard, UUID gameId, boolean me) { + public PlayAreaPanel(PlayerView player, BigCard bigCard, UUID gameId, boolean me, int priorityTime) { this(); - init(player, bigCard, gameId); + init(player, bigCard, gameId, priorityTime); update(player); } @@ -99,8 +99,8 @@ public class PlayAreaPanel extends javax.swing.JPanel { }); } - public final void init(PlayerView player, BigCard bigCard, UUID gameId) { - this.playerPanel.init(gameId, player.getPlayerId(), bigCard); + public final void init(PlayerView player, BigCard bigCard, UUID gameId, int priorityTime) { + this.playerPanel.init(gameId, player.getPlayerId(), bigCard, priorityTime); this.battlefieldPanel.init(gameId, bigCard); this.gameId = gameId; if (MageFrame.getSession().isTestMode()) { diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java index ccd02a41b3f..90f21edbcb0 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java @@ -34,6 +34,7 @@ package mage.client.game; +import mage.MageException; import mage.cards.MageCard; import mage.cards.action.ActionCallback; import mage.cards.decks.importer.DckDeckImporter; @@ -52,6 +53,7 @@ import mage.client.util.ImageHelper; import mage.client.util.gui.BufferedImageBuilder; import mage.components.ImagePanel; import mage.remote.Session; +import mage.utils.timer.PriorityTimer; import mage.view.CardView; import mage.view.ManaPoolView; import mage.view.PlayerView; @@ -101,19 +103,43 @@ public class PlayerPanelExt extends javax.swing.JPanel { private int avatarId = -1; + private PriorityTimer timer; + /** Creates new form PlayerPanel */ public PlayerPanelExt() { setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT)); initComponents(); } - public void init(UUID gameId, UUID playerId, BigCard bigCard) { + public void init(UUID gameId, UUID playerId, BigCard bigCard, int priorityTime) { this.gameId = gameId; this.playerId = playerId; this.bigCard = bigCard; session = MageFrame.getSession(); cheat.setVisible(session.isTestMode()); cheat.setFocusable(false); + + if (priorityTime > 0) { + long delay = 1000L; + + timer = new PriorityTimer(priorityTime, delay, new mage.interfaces.Action() { + @Override + public void execute() throws MageException { + // do nothing + } + }); + final PriorityTimer pt = timer; + timer.setTaskOnTick(new mage.interfaces.Action() { + @Override + public void execute() throws MageException { + int priorityTimeValue = pt.getCount(); + String text = getPriorityTimeLeftString(priorityTimeValue); + PlayerPanelExt.this.avatar.setTopText(text); + PlayerPanelExt.this.avatar.repaint(); + } + }); + timer.init(); + } } public void update(PlayerView player) { @@ -182,6 +208,19 @@ public class PlayerPanelExt extends javax.swing.JPanel { } } this.avatar.setText(player.getName()); + if (this.timer != null) { + if (player.getPriorityTimeLeft() != Integer.MAX_VALUE) { + String priorityTimeValue = getPriorityTimeLeftString(player); + this.timer.setCount(player.getPriorityTimeLeft()); + this.avatar.setTopText(priorityTimeValue); + } + if (player.hasPriority()) { + this.timer.resume(); + } else { + this.timer.pause(); + } + } + this.btnPlayer.setText(player.getName()); if (player.isActive()) { this.avatar.setBorder(greenBorder); @@ -193,6 +232,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { this.avatar.setBorder(emptyBorder); this.btnPlayer.setBorder(emptyBorder); } + synchronized (this) { if (player.getTopCard() != null) { @@ -216,6 +256,18 @@ public class PlayerPanelExt extends javax.swing.JPanel { update(player.getManaPool()); } + private String getPriorityTimeLeftString(PlayerView player) { + int priorityTimeLeft = player.getPriorityTimeLeft(); + return getPriorityTimeLeftString(priorityTimeLeft); + } + + private String getPriorityTimeLeftString(int priorityTimeLeft) { + int h = priorityTimeLeft / 3600; + int m = (priorityTimeLeft % 3600) / 60; + int s = priorityTimeLeft % 60; + return (h < 10 ? "0" : "") + h + ":" + (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s; + } + protected void update(ManaPoolView pool) { manaLabels.get("B").setText(Integer.toString(pool.getBlack())); manaLabels.get("R").setText(Integer.toString(pool.getRed())); diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.form b/Mage.Client/src/main/java/mage/client/table/TablesPanel.form index 7d5dea9d538..3a514255d88 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.form +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.form @@ -19,11 +19,7 @@ - - - - - + @@ -128,13 +124,12 @@ + - + - - diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java index 2e100e73fb5..9e8dbac6446 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -422,7 +422,7 @@ public class TablesPanel extends javax.swing.JPanel { jPanel2.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); jPanel2.setPreferredSize(new java.awt.Dimension(664, 39)); - jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11)); + jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N jLabel1.setText("Message of the Day:"); jLabel1.setAlignmentY(0.3F); @@ -443,13 +443,12 @@ public class TablesPanel extends javax.swing.JPanel { jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout.createSequentialGroup() - .addContainerGap() + .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jLabel2, 449, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(440, 440, 440)) + .addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 701, Short.MAX_VALUE) + .addContainerGap()) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -486,7 +485,7 @@ public class TablesPanel extends javax.swing.JPanel { jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 743, Short.MAX_VALUE) + .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 803, Short.MAX_VALUE) ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -502,21 +501,18 @@ public class TablesPanel extends javax.swing.JPanel { .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 848, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(0, 0, 0) - .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 779, Short.MAX_VALUE) - .addContainerGap(69, Short.MAX_VALUE))) + .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 908, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0) - .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 501, Short.MAX_VALUE) + .addComponent(jSplitPane1) .addGap(0, 0, 0) .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 576, Short.MAX_VALUE)) + .addGap(0, 580, Short.MAX_VALUE)) ); }// //GEN-END:initComponents diff --git a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.form b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.form index 6b8c260a15b..4b690eba5f3 100644 --- a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.form +++ b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.form @@ -1,6 +1,11 @@ - +
+ + + + + @@ -16,59 +21,233 @@ - - - - - - - - + + - - - - + + + + - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java index aa87cf7a2b7..938592368f8 100644 --- a/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java +++ b/Mage.Client/src/main/java/mage/client/tournament/TournamentPanel.java @@ -36,14 +36,17 @@ package mage.client.tournament; import java.awt.*; import java.awt.event.ActionEvent; +import java.text.DateFormat; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; +import javafx.scene.layout.Pane; import javax.swing.*; import javax.swing.table.AbstractTableModel; import mage.client.MageFrame; +import mage.client.MagePane; import mage.client.chat.ChatPanel; import mage.client.util.ButtonColumn; import mage.remote.Session; @@ -66,6 +69,8 @@ public class TournamentPanel extends javax.swing.JPanel { private TournamentPlayersTableModel playersModel; private TournamentMatchesTableModel matchesModel; private UpdateTournamentTask updateTask; + private boolean titleSet = false; + private DateFormat df; /** Creates new form TournamentPanel */ public TournamentPanel() { @@ -74,6 +79,8 @@ public class TournamentPanel extends javax.swing.JPanel { initComponents(); + df = DateFormat.getDateTimeInstance(); + tablePlayers.createDefaultColumnsFromModel(); tableMatches.createDefaultColumnsFromModel(); @@ -95,6 +102,7 @@ public class TournamentPanel extends javax.swing.JPanel { } }; + // replay button, don't delete this ButtonColumn buttonColumn = new ButtonColumn(tableMatches, action, 6); } @@ -128,6 +136,31 @@ public class TournamentPanel extends javax.swing.JPanel { } public void update(TournamentView tournament) { + + if (!titleSet) { + Component c = this.getParent(); + while (c != null && !(c instanceof TournamentPane)) { + c = c.getParent(); + } + if (c != null) { + ((TournamentPane)c).setTitle("Tournament [" + tournament.getTournamentName() +"]"); + } + titleSet = true; + } + + txtName.setText(tournament.getTournamentName()); + txtType.setText(tournament.getTournamentType()); + + txtStartTime.setText(df.format(tournament.getStartTime())); + + if (tournament.getEndTime() != null) { + txtEndTime.setText(df.format(tournament.getEndTime())); + btnCloseWindow.setVisible(true); + } else { + txtEndTime.setText("running..."); + btnCloseWindow.setVisible(false); + } + playersModel.loadData(tournament); matchesModel.loadData(tournament); this.tablePlayers.repaint(); @@ -144,8 +177,9 @@ public class TournamentPanel extends javax.swing.JPanel { } public void stopTasks() { - if (updateTask != null) + if (updateTask != null) { updateTask.cancel(true); + } } /** This method is called from within the constructor to @@ -157,46 +191,175 @@ public class TournamentPanel extends javax.swing.JPanel { // //GEN-BEGIN:initComponents private void initComponents() { - chatPanel1 = new mage.client.chat.ChatPanel(); + actionPanel = new javax.swing.JPanel(); + lblName = new javax.swing.JLabel(); + txtName = new javax.swing.JTextField(); + lblType = new javax.swing.JLabel(); + txtType = new javax.swing.JTextField(); + lblStartTime = new javax.swing.JLabel(); + txtStartTime = new javax.swing.JTextField(); + lablEndTime = new javax.swing.JLabel(); + txtEndTime = new javax.swing.JTextField(); + btnCloseWindow = new javax.swing.JButton(); + jSplitPane2 = new javax.swing.JSplitPane(); + jSplitPane1 = new javax.swing.JSplitPane(); jScrollPane1 = new javax.swing.JScrollPane(); tablePlayers = new javax.swing.JTable(); jScrollPane2 = new javax.swing.JScrollPane(); tableMatches = new javax.swing.JTable(); + chatPanel1 = new mage.client.chat.ChatPanel(); + + setPreferredSize(new java.awt.Dimension(908, 580)); + + lblName.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); + lblName.setText("Name:"); + + txtName.setEditable(false); + txtName.setHorizontalAlignment(javax.swing.JTextField.LEFT); + txtName.setText("tournament name"); + txtName.setFocusable(false); + txtName.setMaximumSize(new java.awt.Dimension(50, 22)); + + lblType.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); + lblType.setText("Type:"); + + txtType.setEditable(false); + txtType.setHorizontalAlignment(javax.swing.JTextField.LEFT); + txtType.setText("tournament type"); + txtType.setFocusable(false); + + lblStartTime.setText("Start time:"); + + txtStartTime.setEditable(false); + txtStartTime.setHorizontalAlignment(javax.swing.JTextField.CENTER); + txtStartTime.setText("jTextField1"); + txtStartTime.setFocusable(false); + + lablEndTime.setText("End time:"); + + txtEndTime.setEditable(false); + txtEndTime.setHorizontalAlignment(javax.swing.JTextField.CENTER); + txtEndTime.setText("jTextField2"); + txtEndTime.setFocusable(false); + + btnCloseWindow.setText("Close Window"); + btnCloseWindow.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + btnCloseWindow.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCloseWindowActionPerformed(evt); + } + }); + + javax.swing.GroupLayout actionPanelLayout = new javax.swing.GroupLayout(actionPanel); + actionPanel.setLayout(actionPanelLayout); + actionPanelLayout.setHorizontalGroup( + actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(actionPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblName) + .addComponent(lblType)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(txtName, javax.swing.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE) + .addComponent(txtType)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(actionPanelLayout.createSequentialGroup() + .addComponent(lablEndTime) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(txtEndTime)) + .addGroup(actionPanelLayout.createSequentialGroup() + .addComponent(lblStartTime) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtStartTime, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnCloseWindow, javax.swing.GroupLayout.PREFERRED_SIZE, 129, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + actionPanelLayout.setVerticalGroup( + actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(actionPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblName, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblStartTime) + .addComponent(txtStartTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(9, 9, 9) + .addGroup(actionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblType) + .addComponent(txtType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lablEndTime) + .addComponent(txtEndTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnCloseWindow)) + .addGap(0, 14, Short.MAX_VALUE)) + ); + + jSplitPane2.setResizeWeight(1.0); + jSplitPane2.setToolTipText(""); + + jSplitPane1.setDividerLocation(230); + jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + jSplitPane1.setResizeWeight(0.5); + + jScrollPane1.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); + jScrollPane1.setPreferredSize(new java.awt.Dimension(400, 100)); tablePlayers.setModel(this.playersModel); jScrollPane1.setViewportView(tablePlayers); + jSplitPane1.setTopComponent(jScrollPane1); + + jScrollPane2.setPreferredSize(new java.awt.Dimension(400, 100)); + tableMatches.setModel(matchesModel); jScrollPane2.setViewportView(tableMatches); + jSplitPane1.setBottomComponent(jScrollPane2); + + jSplitPane2.setLeftComponent(jSplitPane1); + jSplitPane2.setRightComponent(chatPanel1); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 573, Short.MAX_VALUE) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 573, Short.MAX_VALUE)) - .addGap(0, 0, 0) - .addComponent(chatPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(actionPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jSplitPane2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 908, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 262, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE)) - .addComponent(chatPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 522, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(actionPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE)) ); }// //GEN-END:initComponents + private void btnCloseWindowActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseWindowActionPerformed + hideTournament(); + }//GEN-LAST:event_btnCloseWindowActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel actionPanel; + private javax.swing.JButton btnCloseWindow; private mage.client.chat.ChatPanel chatPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JSplitPane jSplitPane1; + private javax.swing.JSplitPane jSplitPane2; + private javax.swing.JLabel lablEndTime; + private javax.swing.JLabel lblName; + private javax.swing.JLabel lblStartTime; + private javax.swing.JLabel lblType; private javax.swing.JTable tableMatches; private javax.swing.JTable tablePlayers; + private javax.swing.JTextField txtEndTime; + private javax.swing.JTextField txtName; + private javax.swing.JTextField txtStartTime; + private javax.swing.JTextField txtType; // End of variables declaration//GEN-END:variables } @@ -237,8 +400,9 @@ class TournamentPlayersTableModel extends AbstractTableModel { public String getColumnName(int columnIndex) { String colName = ""; - if (columnIndex <= getColumnCount()) + if (columnIndex <= getColumnCount()) { colName = columnNames[columnIndex]; + } return colName; } @@ -308,8 +472,9 @@ class TournamentMatchesTableModel extends AbstractTableModel { public String getColumnName(int columnIndex) { String colName = ""; - if (columnIndex <= getColumnCount()) + if (columnIndex <= getColumnCount()) { colName = columnNames[columnIndex]; + } return colName; } @@ -321,8 +486,9 @@ class TournamentMatchesTableModel extends AbstractTableModel { @Override public boolean isCellEditable(int rowIndex, int columnIndex) { - if (columnIndex != 6) + if (columnIndex != 6) { return false; + } return true; } diff --git a/Mage.Client/src/main/java/mage/client/util/AudioManager.java b/Mage.Client/src/main/java/mage/client/util/AudioManager.java index 252ab22a300..cfed0bd6b4f 100644 --- a/Mage.Client/src/main/java/mage/client/util/AudioManager.java +++ b/Mage.Client/src/main/java/mage/client/util/AudioManager.java @@ -1,12 +1,15 @@ package mage.client.util; +import java.io.File; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; import mage.client.constants.Constants; import mage.client.dialog.PreferencesDialog; import org.apache.log4j.Logger; -import javax.sound.sampled.*; -import java.io.File; - /** * Manager class for playing audio files. * @@ -42,6 +45,8 @@ public class AudioManager { audioManager.addArtifactClip = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnAddArtifact.wav"); audioManager.updateStackClip = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnStackNew.wav"); audioManager.onHover = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnHover.wav"); + + audioManager.playerJoinedTable = audioManager.loadClip(Constants.BASE_SOUND_PATH + "OnPlayerJoinedTable.wav"); } return audioManager; } @@ -114,6 +119,10 @@ public class AudioManager { checkAndPlayClip(getManager().onHover); } + public static void playPlayerJoinedTable() { + checkAndPlayClip(getManager().playerJoinedTable); + } + private static void checkAndPlayClip(Clip clip) { try { if (clip != null) { @@ -175,4 +184,6 @@ public class AudioManager { private Clip addArtifactClip = null; private Clip updateStackClip = null; private Clip onHover = null; + + private Clip playerJoinedTable = null; } diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java index 8067b9d56e4..cc9ce07983e 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java @@ -65,6 +65,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti public final ScaledImagePanel imagePanel; public ImagePanel overlayPanel; public JPanel buttonPanel; + public JPanel iconPanel; private GlowText titleText; private GlowText ptText; @@ -94,6 +95,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti private boolean transformed; private boolean animationInProgress = false; private JButton dayNightButton; + private JButton tokenButton; private boolean displayTitleAnyway; @@ -142,6 +144,23 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti } }); + // token icon + iconPanel = new JPanel(); + iconPanel.setLayout(null); + iconPanel.setOpaque(false); + add(iconPanel); + + tokenButton = new JButton(""); + tokenButton.setLocation(2, 2); + tokenButton.setSize(25, 25); + + iconPanel.setVisible(this.gameCard.isToken()); + + BufferedImage tokenIconImage = ImageManagerImpl.getInstance().getTokenIconImage(); + tokenButton.setIcon(new ImageIcon(tokenIconImage)); + + iconPanel.add(tokenButton); + setBackground(Color.black); setOpaque(false); @@ -411,6 +430,9 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti buttonPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); buttonPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); + iconPanel.setLocation(cardXOffset + borderSize, cardYOffset + borderSize); + iconPanel.setSize(cardWidth - borderSize * 2, cardHeight - borderSize * 2); + int fontHeight = Math.round(cardHeight * (27f / 680)); boolean showText = (!isAnimationPanel && fontHeight < 12); titleText.setVisible(showText); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java b/Mage.Client/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java index bc47999e41c..16269a07503 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/info/CardInfoPaneImpl.java @@ -154,12 +154,15 @@ public class CardInfoPaneImpl extends JEditorPane implements CardInfoPane { } else if (CardUtil.isPlaneswalker(card)) { pt = card.getLoyalty().toString(); } - if (pt.length() > 0) { - buffer.append("
"); - buffer.append(""); - buffer.append(pt); - buffer.append(""); - buffer.append("
"); + + if (pt.length() > 0 || card.isToken()) { + buffer.append(""); + if (card.isToken()) { + buffer.append(""); + } + + buffer.append("
"); + buffer.append(pt).append("Token
"); } StringBuilder rule = new StringBuilder("
"); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/utils/ImageManager.java b/Mage.Client/src/main/java/org/mage/plugins/card/utils/ImageManager.java index 390e2dd121a..fd8a65891ee 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/utils/ImageManager.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/utils/ImageManager.java @@ -11,6 +11,8 @@ public interface ImageManager { Image getSicknessImage(); Image getDayImage(); Image getNightImage(); + + Image getTokenIconImage(); Image getDlgAcceptButtonImage(); Image getDlgActiveAcceptButtonImage(); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/utils/impl/ImageManagerImpl.java b/Mage.Client/src/main/java/org/mage/plugins/card/utils/impl/ImageManagerImpl.java index c99196e2ac3..a161c643c4d 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/utils/impl/ImageManagerImpl.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/utils/impl/ImageManagerImpl.java @@ -97,6 +97,15 @@ public class ImageManagerImpl implements ImageManager { return imageNight; } + @Override + public BufferedImage getTokenIconImage() { + if (imageTokenIcon == null) { + Image image = getImageFromResourceTransparent("/card/token.png", Color.WHITE, new Rectangle(20, 20)); + imageTokenIcon = BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB); + } + return imageTokenIcon; + } + @Override public Image getDlgCancelButtonImage() { if (imageDlgCancelButton == null) { @@ -216,6 +225,8 @@ public class ImageManagerImpl implements ImageManager { private static BufferedImage imageDay; private static BufferedImage imageNight; + private static BufferedImage imageTokenIcon; + private static BufferedImage imageDlgAcceptButton; private static BufferedImage imageDlgActiveAcceptButton; private static BufferedImage imageDlgCancelButton; diff --git a/Mage.Client/src/main/java/org/mage/plugins/theme/ThemePluginImpl.java b/Mage.Client/src/main/java/org/mage/plugins/theme/ThemePluginImpl.java index f2a10884a10..46e8ab67637 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/theme/ThemePluginImpl.java +++ b/Mage.Client/src/main/java/org/mage/plugins/theme/ThemePluginImpl.java @@ -78,25 +78,12 @@ public class ThemePluginImpl implements ThemePlugin { background = loadbuffer_default(); } - - - /* - if(loadimages()){ - int it = (int)Math.abs(Math.random()*(flist.getItemCount())); - filename = BackgroundDir + flist.getItem(it); - background = ImageIO.read(new File(filename)); - }else{ - filename = "/dragon.png"; - InputStream is = this.getClass().getResourceAsStream(filename); - if (is == null) - throw new FileNotFoundException("Couldn't find " + filename + " in resources."); - background = ImageIO.read(is); + if (background == null) { + background = loadbuffer_default(); + } + if (background == null){ + throw new FileNotFoundException("Couldn't find in resources."); } - */ - if (background == null) { - throw new FileNotFoundException("Couldn't find background file in resources."); - } - if (ui.containsKey("gamePanel") && ui.containsKey("jLayeredPane")) { ImagePanel bgPanel = new ImagePanel(background, ImagePanel.TILED); @@ -143,9 +130,13 @@ public class ThemePluginImpl implements ThemePlugin { BufferedImage res; String path = PreferencesDialog.getCachedValue(PreferencesDialog. KEY_BATTLEFIELD_IMAGE, ""); - if(path != null){ - res = ImageIO.read(new File(path)); - return res; + if(path != null && !path.equals("")){ + try{ + res = ImageIO.read(new File(path)); + return res; + }catch(Exception e){ + res = null; + } } return null; } @@ -176,23 +167,28 @@ public class ThemePluginImpl implements ThemePlugin { if (is == null) throw new FileNotFoundException("Couldn't find " + filename + " in resources."); background = ImageIO.read(is); - }else if(PreferencesDialog.getCachedValue(PreferencesDialog. - KEY_BACKGROUND_IMAGE, "") != null){ + }else{ String path = PreferencesDialog.getCachedValue(PreferencesDialog. - KEY_BATTLEFIELD_IMAGE, ""); - if(path != null){ - background = ImageIO.read(new File(path)); - }else{ - InputStream is = this.getClass().getResourceAsStream(filename); - if (is == null) - throw new FileNotFoundException("Couldn't find " + filename + " in resources."); - background = ImageIO.read(is); - } + KEY_BACKGROUND_IMAGE, ""); + if(path != null && !path.equals("")){ + try{ + File f = new File(path); + if(f != null) + background = ImageIO.read(f); + }catch(Exception e){ + background = null; + } + } } - - if (background == null) + if (background == null){ + InputStream is = this.getClass().getResourceAsStream(filename); + if (is == null) throw new FileNotFoundException("Couldn't find " + filename + " in resources."); - } catch (Exception e) { + background = ImageIO.read(is); + } + if(background == null) throw new + FileNotFoundException("Couldn't find " + filename + " in resources."); + }catch (Exception e) { log.error(e.getMessage(), e); return null; } diff --git a/Mage.Client/src/main/resources/card/token.png b/Mage.Client/src/main/resources/card/token.png new file mode 100644 index 00000000000..e63f67cb091 Binary files /dev/null and b/Mage.Client/src/main/resources/card/token.png differ diff --git a/Mage.Client/src/main/resources/image.url.properties b/Mage.Client/src/main/resources/image.url.properties index b8e0d66da16..e182c246172 100644 --- a/Mage.Client/src/main/resources/image.url.properties +++ b/Mage.Client/src/main/resources/image.url.properties @@ -60,6 +60,6 @@ ptk=p3k gur=guru mpr=mprp # Remove DGM as sson as the images can be downloaded -ignore.urls=TOK,EMBLEM +ignore.urls=TOK,EMBLEM,M14 # sets ordered by release time (newest goes first) token.lookup.order=MMA,DGM,GTC,RTR,M13,AVR,DDI,DKA,ISD,M12,NPH,MBS,SOM,M11,ROE,PVC,WWK,ZEN,M10,GVL,ARB,DVD,CFX,JVC,ALA,EVE,SHM,EVG,MOR,LRW,10E,CLS,CHK \ No newline at end of file diff --git a/Mage.Common/src/mage/constants/Constants.java b/Mage.Common/src/mage/constants/Constants.java index a2e837dd0bf..c6b76fcb3b6 100644 --- a/Mage.Common/src/mage/constants/Constants.java +++ b/Mage.Common/src/mage/constants/Constants.java @@ -68,6 +68,11 @@ public final class Constants { public static final double SCALE_FACTOR = 0.5; + /** + * Time each player has during the game to play using his\her priority. + */ + public static final int PRIORITY_TIME_SEC = 1200; + public enum SessionState { DISCONNECTED, CONNECTED, CONNECTING, DISCONNECTING, SERVER_UNAVAILABLE, SERVER_STARTING; } diff --git a/Mage.Common/src/mage/utils/timer/PriorityTimer.java b/Mage.Common/src/mage/utils/timer/PriorityTimer.java new file mode 100644 index 00000000000..90911c8ddd2 --- /dev/null +++ b/Mage.Common/src/mage/utils/timer/PriorityTimer.java @@ -0,0 +1,127 @@ +package mage.utils.timer; + +import mage.MageException; +import mage.interfaces.Action; +import org.apache.log4j.Logger; + +import java.util.Timer; +import java.util.TimerTask; + +/** + * @author noxx + */ +public class PriorityTimer extends TimerTask { + + private static final Logger logger = Logger.getLogger(PriorityTimer.class); + + private int count; + + private long delay; + + private Action taskOnTimeout; + + private Action taskOnTick; + + private States state = States.NONE; + + enum States { + NONE, + INIT, + RUNNING, + PAUSED, + FINISHED + } + + public PriorityTimer(int count, long delay, Action taskOnTimeout) { + this.count = count; + this.delay = delay; + this.taskOnTimeout = taskOnTimeout; + } + + public void init() { + state = States.INIT; + Timer timer = new Timer("Priority Timer", false); + long delayMs = delay * (int) (1000L / delay); + timer.scheduleAtFixedRate(this, delayMs, delayMs); + } + + public void start() { + if (state == States.NONE) { + throw new IllegalStateException("Timer should have been initialized first"); + } + if (state == States.FINISHED) { + throw new IllegalStateException("Timer has already finished its work"); + } + state = States.RUNNING; + } + + public void pause() { + state = States.PAUSED; + } + + public void stop() { + state = States.FINISHED; + count = 0; + } + + public void resume() { + if (state == States.FINISHED) { + throw new IllegalStateException("Timer has already finished its work"); + } + state = States.RUNNING; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public void setTaskOnTick(Action taskOnTick) { + this.taskOnTick = taskOnTick; + } + + @Override + public void run() { + if (state == States.RUNNING) { + count--; + if (taskOnTick != null) { + try { + taskOnTick.execute(); + } catch (MageException e) { + throw new RuntimeException(e); + } + } + } + if (logger.isDebugEnabled()) logger.debug("Count is: " + count); + //System.out.println("Count is: " + count); + if (count <= 0) { + cancel(); + try { + taskOnTimeout.execute(); + } catch (MageException e) { + throw new RuntimeException(e); + } + } + } + + public static void main(String[] args) throws Exception { + long delay = 250L; + int count = 5; + PriorityTimer timer = new PriorityTimer(count, delay, new Action() { + @Override + public void execute() throws MageException { + System.out.println("Exit"); + System.exit(0); + } + }); + timer.init(); + timer.start(); + Thread.sleep(2000); + timer.pause(); + Thread.sleep(3000); + timer.resume(); + } +} diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index 1c27582361f..d619065ea54 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -47,6 +47,7 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; import mage.abilities.Mode; +import mage.abilities.Modes; import mage.abilities.SpellAbility; import mage.abilities.costs.mana.ManaCosts; import mage.cards.SplitCard; @@ -82,6 +83,7 @@ public class CardView extends SimpleCardView { protected boolean transformed; protected boolean isSplitCard; + protected boolean isToken; protected String leftSplitName; protected ManaCosts leftSplitCosts; protected List leftSplitRules; @@ -152,12 +154,23 @@ public class CardView extends SimpleCardView { if (card instanceof PermanentToken) { + this.isToken = true; this.rarity = Rarity.COMMON; - this.expansionSetCode = ((PermanentToken) card).getExpansionSetCode(); + if (((PermanentToken) card).getToken().getOriginalCardNumber() > 0) { + // a token copied from permanent + this.expansionSetCode = ((PermanentToken) card).getToken().getOriginalExpansionSetCode(); + this.cardNumber = ((PermanentToken) card).getToken().getOriginalCardNumber(); + } else { + // a created token + this.expansionSetCode = ((PermanentToken) card).getExpansionSetCode(); + } + // + // set code und card number for token copies to get the image this.rules = ((PermanentToken) card).getRules(); this.type = ((PermanentToken)card).getToken().getTokenType(); } else { this.rarity = card.getRarity(); + this.isToken = false; } if (card.getCounters() != null && !card.getCounters().isEmpty()) { counters = new ArrayList(); @@ -172,15 +185,19 @@ public class CardView extends SimpleCardView { if (card instanceof Spell) { Spell spell = (Spell) card; for (SpellAbility spellAbility: spell.getSpellAbilities()) { - if (spellAbility.getTargets().size() > 0) { - setTargets(spellAbility.getTargets()); + for(UUID modeId : spellAbility.getModes().getSelectedModes()) { + spellAbility.getModes().setMode(spellAbility.getModes().get(modeId)); + if (spellAbility.getTargets().size() > 0) { + setTargets(spellAbility.getTargets()); + } } } // show for modal spell, which mode was choosen if (spell.getSpellAbility().isModal()) { - Mode activeMode = spell.getSpellAbility().getModes().getMode(); - if (activeMode != null) { - this.rules.add("Chosen mode: " + activeMode.getEffects().getText(activeMode)+""); + Modes modes = spell.getSpellAbility().getModes(); + for(UUID modeId : modes.getSelectedModes()) { + modes.setMode(modes.get(modeId)); + this.rules.add("Chosen mode: " + spell.getSpellAbility().getEffects().getText(modes.get(modeId))+""); } } } @@ -453,6 +470,10 @@ public class CardView extends SimpleCardView { return this.secondCardFace; } + public boolean isToken() { + return this.isToken; + } + public void setTransformed(boolean transformed) { this.transformed = transformed; } diff --git a/Mage.Common/src/mage/view/GameView.java b/Mage.Common/src/mage/view/GameView.java index 09d2734ea6b..db5535cf492 100644 --- a/Mage.Common/src/mage/view/GameView.java +++ b/Mage.Common/src/mage/view/GameView.java @@ -28,11 +28,16 @@ package mage.view; -import mage.constants.PhaseStep; -import mage.constants.TurnPhase; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; import mage.MageObject; import mage.abilities.costs.Cost; import mage.cards.Card; +import mage.constants.PhaseStep; +import mage.constants.TurnPhase; import mage.constants.Zone; import mage.game.ExileZone; import mage.game.Game; @@ -46,11 +51,6 @@ import mage.game.stack.StackAbility; import mage.game.stack.StackObject; import mage.players.Player; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; /** * @@ -59,6 +59,7 @@ import java.util.UUID; public class GameView implements Serializable { private static final long serialVersionUID = 1L; + private int priorityTime; private List players = new ArrayList(); private SimpleCardsView hand; private Map opponentHands; @@ -75,7 +76,9 @@ public class GameView implements Serializable { private int turn; private boolean special = false; + public GameView(GameState state, Game game) { + priorityTime = game.getPriorityTime(); for (Player player: state.getPlayers().values()) { players.add(new PlayerView(player, state, game)); } @@ -131,14 +134,16 @@ public class GameView implements Serializable { this.phase = state.getTurn().getPhaseType(); this.step = state.getTurn().getStepType(); this.turn = state.getTurnNum(); - if (state.getActivePlayerId() != null) + if (state.getActivePlayerId() != null) { this.activePlayerName = state.getPlayer(state.getActivePlayerId()).getName(); - else + } else { this.activePlayerName = ""; - if (state.getPriorityPlayerId() != null) + } + if (state.getPriorityPlayerId() != null) { this.priorityPlayerName = state.getPlayer(state.getPriorityPlayerId()).getName(); - else + } else { this.priorityPlayerName = ""; + } for (CombatGroup combatGroup: state.getCombat().getGroups()) { combat.add(new CombatGroupView(combatGroup, game)); } @@ -253,4 +258,9 @@ public class GameView implements Serializable { public boolean getSpecial() { return special; } + + public int getPriorityTime() { + return priorityTime; + } + } diff --git a/Mage.Common/src/mage/view/PermanentView.java b/Mage.Common/src/mage/view/PermanentView.java index a88791d000a..09e00e4e419 100644 --- a/Mage.Common/src/mage/view/PermanentView.java +++ b/Mage.Common/src/mage/view/PermanentView.java @@ -50,7 +50,6 @@ public class PermanentView extends CardView { private boolean summoningSickness; private int damage; private List attachments; - private List counters; private CardView original; public PermanentView(Permanent permanent, Card card) { @@ -66,13 +65,7 @@ public class PermanentView extends CardView { attachments = new ArrayList(); attachments.addAll(permanent.getAttachments()); } - if (permanent.getCounters().size() > 0) { - counters = new ArrayList(); - for (Counter counter: permanent.getCounters().values()) { - counters.add(new CounterView(counter)); - } - } - if (permanent instanceof PermanentToken) { + if (isToken()) { original = new CardView(((PermanentToken)permanent).getToken()); original.expansionSetCode = permanent.getExpansionSetCode(); } @@ -110,10 +103,6 @@ public class PermanentView extends CardView { return attachments; } - public List getCounters() { - return counters; - } - public CardView getOriginal() { return original; } diff --git a/Mage.Common/src/mage/view/PlayerView.java b/Mage.Common/src/mage/view/PlayerView.java index a7cad2dfda0..711e037d859 100644 --- a/Mage.Common/src/mage/view/PlayerView.java +++ b/Mage.Common/src/mage/view/PlayerView.java @@ -54,6 +54,7 @@ public class PlayerView implements Serializable { private int libraryCount; private int handCount; private boolean isActive; + private boolean hasPriority; private boolean hasLeft; private ManaPoolView manaPool; private SimpleCardsView graveyard = new SimpleCardsView(); @@ -63,6 +64,7 @@ public class PlayerView implements Serializable { private List emblemList = new ArrayList(); private List attachments = new ArrayList(); private int statesSavedSize; + private int priorityTimeLeft; public PlayerView(Player player, GameState state, Game game) { this.playerId = player.getId(); @@ -73,6 +75,7 @@ public class PlayerView implements Serializable { this.handCount = player.getHand().size(); this.manaPool = new ManaPoolView(player.getManaPool()); this.isActive = (player.getId().equals(state.getActivePlayerId())); + this.hasPriority = player.getId().equals(state.getPriorityPlayerId()); this.hasLeft = player.hasLeft(); for (Card card: player.getGraveyard().getCards(game)) { graveyard.put(card.getId(), new SimpleCardView(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.isFaceDown())); @@ -108,6 +111,7 @@ public class PlayerView implements Serializable { } this.statesSavedSize = player.getStoredBookmark(); + this.priorityTimeLeft = player.getPriorityTimeLeft(); } private boolean showInBattlefield(Permanent permanent, GameState state) { @@ -191,4 +195,12 @@ public class PlayerView implements Serializable { public int getStatesSavedSize() { return statesSavedSize; } + + public int getPriorityTimeLeft() { + return priorityTimeLeft; + } + + public boolean hasPriority() { + return hasPriority; + } } diff --git a/Mage.Common/src/mage/view/StackAbilityView.java b/Mage.Common/src/mage/view/StackAbilityView.java index 60d5534d375..1b4d35124fc 100644 --- a/Mage.Common/src/mage/view/StackAbilityView.java +++ b/Mage.Common/src/mage/view/StackAbilityView.java @@ -28,17 +28,17 @@ package mage.view; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import mage.MageObject; +import mage.abilities.Modes; import mage.abilities.effects.Effect; import mage.game.Game; import mage.game.stack.StackAbility; import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.TargetPointer; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - /** * * @author BetaSteward_at_googlemail.com @@ -68,30 +68,43 @@ public class StackAbilityView extends CardView { } private void updateTargets(Game game, StackAbility ability) { - if (ability.getTargets().size() > 0) { - setTargets(ability.getTargets()); - } else { - List targetList = new ArrayList(); - for (Effect effect : ability.getEffects()) { - TargetPointer targetPointer = effect.getTargetPointer(); - if (targetPointer instanceof FixedTarget) { - targetList.add(((FixedTarget) targetPointer).getTarget()); - } - } - if (targetList.size() > 0) { - overrideTargets(targetList); - List names = new ArrayList(); - for (UUID uuid : targetList) { - MageObject mageObject = game.getObject(uuid); - if (mageObject != null) { - names.add(mageObject.getName()); + List names = new ArrayList(); + for(UUID modeId : ability.getModes().getSelectedModes()) { + ability.getModes().setMode(ability.getModes().get(modeId)); + if (ability.getTargets().size() > 0) { + setTargets(ability.getTargets()); + } else { + List targetList = new ArrayList(); + for (Effect effect : ability.getEffects()) { + TargetPointer targetPointer = effect.getTargetPointer(); + if (targetPointer instanceof FixedTarget) { + targetList.add(((FixedTarget) targetPointer).getTarget()); } } - if (!names.isEmpty()) { - getRules().add("Targets: " + names.toString() + ""); + if (targetList.size() > 0) { + overrideTargets(targetList); + + for (UUID uuid : targetList) { + MageObject mageObject = game.getObject(uuid); + if (mageObject != null) { + names.add(mageObject.getName()); + } + } + } } } + if (!names.isEmpty()) { + getRules().add("Targets: " + names.toString() + ""); + } + // show for modal ability, which mode was choosen + if (ability.isModal()) { + Modes modes = ability.getModes(); + for(UUID modeId : modes.getSelectedModes()) { + modes.setMode(modes.get(modeId)); + this.rules.add("Chosen mode: " + ability.getEffects().getText(modes.get(modeId))+""); + } + } } public CardView getSourceCard() { diff --git a/Mage.Common/src/mage/view/TournamentView.java b/Mage.Common/src/mage/view/TournamentView.java index af5800fa13b..ad113af0ebc 100644 --- a/Mage.Common/src/mage/view/TournamentView.java +++ b/Mage.Common/src/mage/view/TournamentView.java @@ -30,6 +30,7 @@ package mage.view; import java.io.Serializable; import java.util.ArrayList; +import java.util.Date; import java.util.List; import mage.game.tournament.Round; import mage.game.tournament.Tournament; @@ -42,10 +43,23 @@ import mage.game.tournament.TournamentPlayer; public class TournamentView implements Serializable { private static final long serialVersionUID = 1L; - List rounds = new ArrayList(); - List players = new ArrayList(); + private String tournamentName; + private String tournamentType; + + private Date startTime; + private Date endTime; + + + private List rounds = new ArrayList(); + private List players = new ArrayList(); public TournamentView(Tournament tournament) { + + tournamentName = tournament.getOptions().getName(); + tournamentType = tournament.getOptions().getTournamentType(); + startTime = tournament.getStartTime(); + endTime = tournament.getEndTime(); + for (TournamentPlayer player: tournament.getPlayers()) { players.add(new TournamentPlayerView(player)); } @@ -54,6 +68,22 @@ public class TournamentView implements Serializable { } } + public String getTournamentName() { + return tournamentName; + } + + public String getTournamentType() { + return tournamentType; + } + + public Date getStartTime() { + return startTime; + } + + public Date getEndTime() { + return endTime; + } + public List getPlayers() { return players; } diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index ba03a462982..24cf4203a6f 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -1230,7 +1230,13 @@ public class ComputerPlayer> extends PlayerImpl i return modes.getMode(); } //TODO: improve this; - return modes.values().iterator().next(); + for (Mode mode: modes.values()) { + if (!modes.getSelectedModes().contains(mode.getId()) // select only modes not already selected + && mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and where targets are available + return mode; + } + } + return null; } @Override diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 79165bf6b9a..cc6a3bbb5df 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -28,11 +28,6 @@ package mage.player.human; -import java.io.Serializable; -import java.util.*; -import mage.constants.Outcome; -import mage.constants.RangeOfInfluence; -import mage.constants.Zone; import mage.MageObject; import mage.abilities.*; import mage.abilities.costs.common.SacrificeSourceCost; @@ -46,6 +41,9 @@ import mage.cards.Cards; import mage.cards.decks.Deck; import mage.choices.Choice; import mage.choices.ChoiceImpl; +import mage.constants.Outcome; +import mage.constants.RangeOfInfluence; +import mage.constants.Zone; import mage.filter.common.FilterAttackingCreature; import mage.filter.common.FilterBlockingCreature; import mage.filter.common.FilterCreatureForCombat; @@ -67,6 +65,9 @@ import mage.target.common.TargetDefender; import mage.util.ManaUtil; import org.apache.log4j.Logger; +import java.io.Serializable; +import java.util.*; + /** * @@ -98,40 +99,43 @@ public class HumanPlayer extends PlayerImpl { super(player); } - protected void waitForResponse() { + protected void waitForResponse(Game game) { response.clear(); log.debug("Waiting response from player: " + getId()); + game.resumeTimer(playerId); synchronized(response) { try { response.wait(); log.debug("Got response from player: " + getId()); } catch (InterruptedException ex) { ex.printStackTrace(); + } finally { + game.pauseTimer(playerId); } } } - protected void waitForBooleanResponse() { + protected void waitForBooleanResponse(Game game) { do { - waitForResponse(); + waitForResponse(game); } while (response.getBoolean() == null && !abort); } - protected void waitForUUIDResponse() { + protected void waitForUUIDResponse(Game game) { do { - waitForResponse(); + waitForResponse(game); } while (response.getUUID() == null && !abort); } - protected void waitForStringResponse() { + protected void waitForStringResponse(Game game) { do { - waitForResponse(); + waitForResponse(game); } while (response.getString() == null && !abort); } - protected void waitForIntegerResponse() { + protected void waitForIntegerResponse(Game game) { do { - waitForResponse(); + waitForResponse(game); } while (response.getInteger() == null && !abort); } @@ -143,7 +147,7 @@ public class HumanPlayer extends PlayerImpl { .append(getHand().size() > nextHandSize?"down to ":"for free, draw ") .append(nextHandSize) .append(nextHandSize == 1?" card?":" cards?").toString()); - waitForBooleanResponse(); + waitForBooleanResponse(game); if (!abort) { return response.getBoolean(); } @@ -154,7 +158,7 @@ public class HumanPlayer extends PlayerImpl { public boolean chooseUse(Outcome outcome, String message, Game game) { updateGameStatePriority("chooseUse", game); game.fireAskPlayerEvent(playerId, message); - waitForBooleanResponse(); + waitForBooleanResponse(game); if (!abort) { return response.getBoolean(); } @@ -175,7 +179,7 @@ public class HumanPlayer extends PlayerImpl { } while (!abort) { game.fireChooseEvent(playerId, replacementEffectChoice); - waitForResponse(); + waitForResponse(game); log.debug("Choose effect: " + response.getString()); if (response.getString() != null) { replacementEffectChoice.setChoice(response.getString()); @@ -196,7 +200,7 @@ public class HumanPlayer extends PlayerImpl { updateGameStatePriority("choose(3)", game); while (!abort) { game.fireChooseEvent(playerId, choice); - waitForResponse(); + waitForResponse(game); if (response.getString() != null) { choice.setChoice(response.getString()); return true; @@ -218,7 +222,7 @@ public class HumanPlayer extends PlayerImpl { while (!abort) { Set cards = target.possibleTargets(null, playerId, game); game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired(), options); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { if (target instanceof TargetPermanent) { if (((TargetPermanent)target).canTarget(playerId, response.getUUID(), sourceId, game, false)) { @@ -267,7 +271,7 @@ public class HumanPlayer extends PlayerImpl { Set possibleTargets = target.possibleTargets(source==null?null:source.getSourceId(), playerId, game); boolean required = possibleTargets.isEmpty() ? false : target.isRequired(); game.fireSelectTargetEvent(playerId, target.getMessage(), possibleTargets, required, getOptions(target)); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { if (possibleTargets.contains(response.getUUID())) { if (target instanceof TargetPermanent) { @@ -323,7 +327,7 @@ public class HumanPlayer extends PlayerImpl { options.put("chosen", (Serializable)chosen); } game.fireSelectTargetEvent(playerId, target.getMessage(), cards, required, options); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { if (target.canTarget(response.getUUID(), cards, game)) { target.add(response.getUUID(), game); @@ -358,7 +362,7 @@ public class HumanPlayer extends PlayerImpl { } } game.fireSelectTargetEvent(playerId, target.getMessage(), cards, target.isRequired(), null); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { if (target.canTarget(response.getUUID(), cards, game)) { target.addTarget(response.getUUID(), source, game); @@ -383,7 +387,7 @@ public class HumanPlayer extends PlayerImpl { updateGameStatePriority("chooseTargetAmount", game); while (!abort) { game.fireSelectTargetEvent(playerId, target.getMessage() + "\n Amount remaining:" + target.getAmountRemaining(), target.possibleTargets(source==null?null:source.getId(), playerId, game), target.isRequired(), null); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { if (target.canTarget(response.getUUID(), source, game)) { UUID targetId = response.getUUID(); @@ -412,7 +416,7 @@ public class HumanPlayer extends PlayerImpl { } updateGameStatePriority("priority", game); game.firePriorityEvent(playerId); - waitForResponse(); + waitForResponse(game); if (response.getBoolean() != null) { pass(game); return false; @@ -450,7 +454,7 @@ public class HumanPlayer extends PlayerImpl { updateGameStatePriority("chooseTriggeredAbility", game); while (!abort) { game.fireSelectTargetEvent(playerId, "Pick triggered ability (goes to the stack first)", abilities); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { for (TriggeredAbility ability: abilities) { if (ability.getId().equals(response.getUUID())) { @@ -466,7 +470,7 @@ public class HumanPlayer extends PlayerImpl { public boolean playMana(ManaCost unpaid, Game game) { updateGameStatePriority("playMana", game); game.firePlayManaEvent(playerId, "Pay " + unpaid.getText()); - waitForResponse(); + waitForResponse(game); if (response.getBoolean() != null) { return false; } else if (response.getUUID() != null) { @@ -500,7 +504,7 @@ public class HumanPlayer extends PlayerImpl { public int announceXMana(int min, int max, String message, Game game, Ability ability) { updateGameStatePriority("announceXMana", game); game.fireGetAmountEvent(playerId, message, min, max); - waitForIntegerResponse(); + waitForIntegerResponse(game); return response.getInteger(); } @@ -530,7 +534,7 @@ public class HumanPlayer extends PlayerImpl { return; } game.fireSelectEvent(playerId, "Select attackers"); - waitForResponse(); + waitForResponse(game); if (response.getBoolean() != null) { return; } else if (response.getInteger() != null) { @@ -593,7 +597,7 @@ public class HumanPlayer extends PlayerImpl { filter.add(new ControllerIdPredicate(defendingPlayerId)); while (!abort) { game.fireSelectEvent(playerId, "Select blockers"); - waitForResponse(); + waitForResponse(game); if (response.getBoolean() != null) { return; } else if (response.getInteger() != null) { @@ -622,7 +626,7 @@ public class HumanPlayer extends PlayerImpl { updateGameStatePriority("chooseAttackerOrder", game); while (!abort) { game.fireSelectTargetEvent(playerId, "Pick attacker", attackers, true); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { for (Permanent perm: attackers) { if (perm.getId().equals(response.getUUID())) { @@ -640,7 +644,7 @@ public class HumanPlayer extends PlayerImpl { updateGameStatePriority("chooseBlockerOrder", game); while (!abort) { game.fireSelectTargetEvent(playerId, "Pick blocker", blockers, true); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { for (Permanent perm: blockers) { if (perm.getId().equals(response.getUUID())) { @@ -656,7 +660,7 @@ public class HumanPlayer extends PlayerImpl { updateGameStatePriority("selectCombatGroup", game); TargetAttackingCreature target = new TargetAttackingCreature(); game.fireSelectTargetEvent(playerId, "Select attacker to block", target.possibleTargets(null, playerId, game), target.isRequired(), null); - waitForResponse(); + waitForResponse(game); if (response.getBoolean() != null) { // do nothing } else if (response.getUUID() != null) { @@ -696,7 +700,7 @@ public class HumanPlayer extends PlayerImpl { public int getAmount(int min, int max, String message, Game game) { updateGameStatePriority("getAmount", game); game.fireGetAmountEvent(playerId, message, min, max); - waitForIntegerResponse(); + waitForIntegerResponse(game); return response.getInteger(); } @@ -719,7 +723,7 @@ public class HumanPlayer extends PlayerImpl { updateGameStatePriority("specialAction", game); LinkedHashMap specialActions = game.getState().getSpecialActions().getControlledBy(playerId); game.fireGetChoiceEvent(playerId, name, new ArrayList(specialActions.values())); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { if (specialActions.containsKey(response.getUUID())) { activateAbility(specialActions.get(response.getUUID()), game); @@ -737,7 +741,7 @@ public class HumanPlayer extends PlayerImpl { } } game.fireGetChoiceEvent(playerId, name, new ArrayList(abilities.values())); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { if (abilities.containsKey(response.getUUID())) { activateAbility(abilities.get(response.getUUID()), game); @@ -757,7 +761,7 @@ public class HumanPlayer extends PlayerImpl { return (SpellAbility) useableAbilities.values().iterator().next(); } else if (useableAbilities != null && useableAbilities.size() > 0) { game.fireGetChoiceEvent(playerId, name, new ArrayList(useableAbilities.values())); - waitForResponse(); + waitForResponse(game); if (response.getUUID() != null) { if (useableAbilities.containsKey(response.getUUID())) { return (SpellAbility) useableAbilities.get(response.getUUID()); @@ -778,18 +782,23 @@ public class HumanPlayer extends PlayerImpl { MageObject obj = game.getObject(source.getSourceId()); Map modeMap = new LinkedHashMap(); for (Mode mode: modes.values()) { - String modeText = mode.getEffects().getText(mode); - if (obj != null) { - modeText = modeText.replace("{source}", obj.getName()); + if (!modes.getSelectedModes().contains(mode.getId()) // show only modes not already selected + && mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and where targets are available + String modeText = mode.getEffects().getText(mode); + if (obj != null) { + modeText = modeText.replace("{source}", obj.getName()); + } + modeMap.put(mode.getId(), modeText); } - modeMap.put(mode.getId(), modeText); } - game.fireGetModeEvent(playerId, "Choose Mode", modeMap); - waitForResponse(); - if (response.getUUID() != null) { - for (Mode mode: modes.values()) { - if (mode.getId().equals(response.getUUID())) { - return mode; + if (modeMap.size() > 0) { + game.fireGetModeEvent(playerId, "Choose Mode", modeMap); + waitForResponse(game); + if (response.getUUID() != null) { + for (Mode mode: modes.values()) { + if (mode.getId().equals(response.getUUID())) { + return mode; + } } } } @@ -802,7 +811,7 @@ public class HumanPlayer extends PlayerImpl { public boolean choosePile(Outcome outcome, String message, List pile1, List pile2, Game game) { updateGameStatePriority("choosePile", game); game.fireChoosePileEvent(playerId, message, pile1, pile2); - waitForBooleanResponse(); + waitForBooleanResponse(game); if (!abort) { return response.getBoolean(); } diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournament.java b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournament.java index 92f8ee92e3d..d541f4537df 100644 --- a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournament.java +++ b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/BoosterDraftEliminationTournament.java @@ -50,7 +50,6 @@ public class BoosterDraftEliminationTournament extends TournamentSingleEliminati public BoosterDraftEliminationTournament(TournamentOptions options) { super(options); - this.getOptions().getLimitedOptions().setConstructionTime(600); currentStep = TournamentStep.START; } diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournament.java b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournament.java index 702ab4630fb..7f8689f9545 100644 --- a/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournament.java +++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/SealedEliminationTournament.java @@ -45,7 +45,6 @@ public class SealedEliminationTournament extends TournamentSingleElimination { public SealedEliminationTournament(TournamentOptions options) { super(options); - this.getOptions().getLimitedOptions().setConstructionTime(1200); currentStep = TournamentStep.START; } diff --git a/Mage.Server/release/config/log4j.properties b/Mage.Server/release/config/log4j.properties index 932d8c71066..6a3d87231f1 100644 --- a/Mage.Server/release/config/log4j.properties +++ b/Mage.Server/release/config/log4j.properties @@ -1,5 +1,5 @@ #default levels -log4j.rootLogger=info, console, logfile +log4j.rootLogger=warn, console, logfile #console log log4j.appender.console=org.apache.log4j.ConsoleAppender diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 44f1fd3c43b..b37d884d9b3 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -396,6 +396,7 @@ public class TableController { User user = UserManager.getInstance().getUser(entry.getKey()); user.tournamentStarted(tournament.getId(), entry.getValue()); } + ServerMessagesUtil.getInstance().incTournamentsStarted(); } } catch (Exception ex) { diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index bd8c491074b..925539e12aa 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -28,7 +28,6 @@ package mage.server.game; -import mage.constants.Zone; import mage.MageException; import mage.abilities.Ability; import mage.cards.Card; @@ -37,17 +36,21 @@ import mage.cards.decks.Deck; import mage.cards.decks.DeckCardLists; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; +import mage.constants.Constants; +import mage.constants.Zone; import mage.game.Game; import mage.game.GameException; import mage.game.events.Listener; import mage.game.events.PlayerQueryEvent; import mage.game.events.TableEvent; import mage.game.permanent.Permanent; +import mage.interfaces.Action; import mage.players.Player; import mage.server.*; import mage.server.util.Splitter; import mage.server.util.SystemUtil; import mage.server.util.ThreadExecutor; +import mage.utils.timer.PriorityTimer; import mage.view.AbilityPickerView; import mage.view.CardsView; import mage.view.ChatMessage.MessageColor; @@ -75,6 +78,8 @@ public class GameController implements GameCallback { private ConcurrentHashMap gameSessions = new ConcurrentHashMap(); private ConcurrentHashMap watchers = new ConcurrentHashMap(); + private ConcurrentHashMap timers = new ConcurrentHashMap(); + private ConcurrentHashMap userPlayerMap; private UUID gameSessionId; private Game game; @@ -106,6 +111,8 @@ public class GameController implements GameCallback { @Override public void event(TableEvent event) { try { + PriorityTimer timer; + UUID playerId; switch (event.getEventType()) { case UPDATE: updateGame(); @@ -124,6 +131,44 @@ public class GameController implements GameCallback { case ERROR: error(event.getMessage(), event.getException()); break; + case INIT_TIMER: + final UUID initPlayerId = event.getPlayerId(); + if (initPlayerId == null) { + throw new IllegalStateException("INIT_TIMER: playerId can't be null"); + } + long delay = 250L; // run each 250 ms + timer = new PriorityTimer(game.getPriorityTime(), delay, new Action() { + @Override + public void execute() throws MageException { + game.concede(initPlayerId); + logger.info("Game timeout for player: " + initPlayerId + ". Conceding."); + } + }); + timers.put(initPlayerId, timer); + timer.init(); + break; + case RESUME_TIMER: + playerId = event.getPlayerId(); + if (playerId == null) { + throw new IllegalStateException("RESUME_TIMER: playerId can't be null"); + } + timer = timers.get(playerId); + if (timer == null) { + throw new IllegalStateException("RESUME_TIMER: couldn't find timer for player: " + playerId); + } + timer.resume(); + break; + case PAUSE_TIMER: + playerId = event.getPlayerId(); + if (playerId == null) { + throw new IllegalStateException("PAUSE_TIMER: playerId can't be null"); + } + timer = timers.get(playerId); + if (timer == null) { + throw new IllegalStateException("PAUSE_TIMER: couldn't find timer for player: " + playerId); + } + timer.pause(); + break; } } catch (MageException ex) { logger.fatal("Table event listener error ", ex); @@ -388,6 +433,14 @@ public class GameController implements GameCallback { } private synchronized void updateGame() { + if (!timers.isEmpty()) { + for (Player player: game.getState().getPlayers().values()) { + PriorityTimer timer = timers.get(player.getId()); + if (timer != null) { + player.setPriorityTimeLeft(timer.getCount()); + } + } + } for (final GameSession gameSession: gameSessions.values()) { gameSession.update(); } diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java index 48edb9c3218..a408913541e 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -229,6 +229,10 @@ public class TournamentController { public void submitDeck(UUID playerId, Deck deck) { if (tournamentSessions.containsKey(playerId)) { tournamentSessions.get(playerId).submitDeck(deck); + TournamentPlayer player = tournament.getPlayer(playerId); + if (player != null) { + ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getName() + " has submitted the deck", MessageColor.BLACK); + } } } diff --git a/Mage.Server/src/main/java/mage/server/util/ServerMessagesUtil.java b/Mage.Server/src/main/java/mage/server/util/ServerMessagesUtil.java index 0d947069f2c..0db20f88218 100644 --- a/Mage.Server/src/main/java/mage/server/util/ServerMessagesUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/ServerMessagesUtil.java @@ -65,6 +65,7 @@ public class ServerMessagesUtil { private static long startDate; private static AtomicInteger gamesStarted = new AtomicInteger(0); + private static AtomicInteger tournamentsStarted = new AtomicInteger(0); static { pathToExternalMessages = System.getProperty("messagesPath"); @@ -170,6 +171,8 @@ public class ServerMessagesUtil { statistics.append(hours); statistics.append(" hour(s), games played: "); statistics.append(gamesStarted.get()); + statistics.append(" tournaments started: "); + statistics.append(tournamentsStarted.get()); return statistics.toString(); } @@ -189,4 +192,13 @@ public class ServerMessagesUtil { value = gamesStarted.get(); } while (!gamesStarted.compareAndSet(value, value + 1)); } + + public void incTournamentsStarted() { + int value; + do { + value = tournamentsStarted.get(); + } while (!tournamentsStarted.compareAndSet(value, value + 1)); + } + + } diff --git a/Mage.Sets/src/mage/sets/Magic2014.java b/Mage.Sets/src/mage/sets/Magic2014.java new file mode 100644 index 00000000000..390c116dec7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/Magic2014.java @@ -0,0 +1,55 @@ +/* + * 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; + +import java.util.GregorianCalendar; +import mage.cards.ExpansionSet; +import mage.constants.SetType; + +/** + * + * @author North + */ +public class Magic2014 extends ExpansionSet { + + private static final Magic2014 fINSTANCE = new Magic2014(); + + public static Magic2014 getInstance() { + return fINSTANCE; + } + + private Magic2014() { + super("Magic 2014", "M14", "mage.sets.magic2014", new GregorianCalendar(2013, 19, 7).getTime(), SetType.CORE); + this.hasBoosters = true; + this.numBoosterLands = 1; + this.numBoosterCommon = 10; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 8; + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/DeathbringerThoctar.java b/Mage.Sets/src/mage/sets/alarareborn/DeathbringerThoctar.java new file mode 100644 index 00000000000..9723565992d --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/DeathbringerThoctar.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.alarareborn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author jeffwadsworth + */ +public class DeathbringerThoctar extends CardImpl { + + public DeathbringerThoctar(UUID ownerId) { + super(ownerId, 36, "Deathbringer Thoctar", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{B}{R}"); + this.expansionSetCode = "ARB"; + this.subtype.add("Zombie"); + this.subtype.add("Beast"); + + this.color.setRed(true); + this.color.setBlack(true); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever another creature dies, you may put a +1/+1 counter on Deathbringer Thoctar. + this.addAbility(new DiesCreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), true, true)); + + // Remove a +1/+1 counter from Deathbringer Thoctar: Deathbringer Thoctar deals 1 damage to target creature or player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new RemoveCountersSourceCost(CounterType.P1P1.createInstance())); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public DeathbringerThoctar(final DeathbringerThoctar card) { + super(card); + } + + @Override + public DeathbringerThoctar copy() { + return new DeathbringerThoctar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/DoubleNegative.java b/Mage.Sets/src/mage/sets/alarareborn/DoubleNegative.java new file mode 100644 index 00000000000..4fb2cadd7d6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/DoubleNegative.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.alarareborn; + +import java.util.UUID; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterSpell; +import mage.target.TargetSpell; + +/** + * + * @author jeffwadsworth + */ +public class DoubleNegative extends CardImpl { + + public DoubleNegative(UUID ownerId) { + super(ownerId, 87, "Double Negative", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{U}{U}{R}"); + this.expansionSetCode = "ARB"; + + this.color.setRed(true); + this.color.setBlue(true); + + // Counter up to two target spells. + Effect effect = new CounterTargetEffect(); + effect.setText("Counter up to two target spells"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetSpell(0, 2, new FilterSpell())); + } + + public DoubleNegative(final DoubleNegative card) { + super(card); + } + + @Override + public DoubleNegative copy() { + return new DoubleNegative(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/DragonAppeasement.java b/Mage.Sets/src/mage/sets/alarareborn/DragonAppeasement.java new file mode 100644 index 00000000000..7ebc43da3ca --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/DragonAppeasement.java @@ -0,0 +1,143 @@ +/* + * 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.alarareborn; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.DrawCardControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author jeffwadsworth + */ +public class DragonAppeasement extends CardImpl { + + public DragonAppeasement(UUID ownerId) { + super(ownerId, 115, "Dragon Appeasement", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{R}{G}"); + this.expansionSetCode = "ARB"; + + this.color.setRed(true); + this.color.setGreen(true); + this.color.setBlack(true); + + // Skip your draw step. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SkipYourDrawStepEffect())); + + // Whenever you sacrifice a creature, you may draw a card. + this.addAbility(new DragonAppeasementTriggeredAbility()); + + } + + public DragonAppeasement(final DragonAppeasement card) { + super(card); + } + + @Override + public DragonAppeasement copy() { + return new DragonAppeasement(this); + } +} + +class SkipYourDrawStepEffect extends ReplacementEffectImpl { + + public SkipYourDrawStepEffect() { + super(Duration.WhileOnBattlefield, Outcome.Neutral); + staticText = "Skip your draw step"; + } + + public SkipYourDrawStepEffect(final SkipYourDrawStepEffect effect) { + super(effect); + } + + @Override + public SkipYourDrawStepEffect copy() { + return new SkipYourDrawStepEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.DRAW_STEP + && (event.getPlayerId().equals(source.getControllerId()))) { + return true; + } + return false; + } +} + +class DragonAppeasementTriggeredAbility extends TriggeredAbilityImpl { + + public DragonAppeasementTriggeredAbility() { + super(Zone.BATTLEFIELD, new DrawCardControllerEffect(1), true); + } + + public DragonAppeasementTriggeredAbility(final DragonAppeasementTriggeredAbility ability) { + super(ability); + } + + @Override + public DragonAppeasementTriggeredAbility copy() { + return new DragonAppeasementTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SACRIFICED_PERMANENT + && event.getPlayerId().equals(this.getControllerId()) + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getCardType().contains(CardType.CREATURE)) { + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever you sacrifice a creature, " + super.getRule(); + } +} + diff --git a/Mage.Sets/src/mage/sets/alarareborn/GodtrackerOfJund.java b/Mage.Sets/src/mage/sets/alarareborn/GodtrackerOfJund.java new file mode 100644 index 00000000000..3477f083c94 --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/GodtrackerOfJund.java @@ -0,0 +1,80 @@ +/* + * 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.alarareborn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.Filter; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; + +/** + * + * @author jeffwadsworth + */ +public class GodtrackerOfJund extends CardImpl { + + final private static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(new PowerPredicate(Filter.ComparisonType.GreaterThan, 4)); + } + + String rule = "Whenever a creature with power 5 or greater enters the battlefield under your control, you may put a +1/+1 counter on Godtracker of Jund."; + + public GodtrackerOfJund(UUID ownerId) { + super(ownerId, 55, "Godtracker of Jund", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{R}{G}"); + this.expansionSetCode = "ARB"; + this.subtype.add("Elf"); + this.subtype.add("Shaman"); + + this.color.setRed(true); + this.color.setGreen(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever a creature with power 5 or greater enters the battlefield under your control, you may put a +1/+1 counter on Godtracker of Jund. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter, true, rule, true)); + } + + public GodtrackerOfJund(final GodtrackerOfJund card) { + super(card); + } + + @Override + public GodtrackerOfJund copy() { + return new GodtrackerOfJund(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/JundSojourners.java b/Mage.Sets/src/mage/sets/alarareborn/JundSojourners.java new file mode 100644 index 00000000000..f3fd621bd93 --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/JundSojourners.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.alarareborn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.CycleTriggeredAbility; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.CyclingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author jeffwadsworth + */ +public class JundSojourners extends CardImpl { + + public JundSojourners(UUID ownerId) { + super(ownerId, 116, "Jund Sojourners", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{B}{R}{G}"); + this.expansionSetCode = "ARB"; + this.subtype.add("Viashino"); + this.subtype.add("Shaman"); + + this.color.setRed(true); + this.color.setGreen(true); + this.color.setBlack(true); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When you cycle Jund Sojourners or it dies, you may have it deal 1 damage to target creature or player. + Ability ability1 = new CycleTriggeredAbility(new DamageTargetEffect(1)); + Ability ability2 = new DiesTriggeredAbility(new DamageTargetEffect(1)); + ability1.addTarget(new TargetCreatureOrPlayer()); + ability2.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability1); + this.addAbility(ability2); + + // Cycling {2}{R} + this.addAbility(new CyclingAbility(new ManaCostsImpl("{2}{R}"))); + } + + public JundSojourners(final JundSojourners card) { + super(card); + } + + @Override + public JundSojourners copy() { + return new JundSojourners(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/KarrthusTyrantOfJund.java b/Mage.Sets/src/mage/sets/alarareborn/KarrthusTyrantOfJund.java new file mode 100644 index 00000000000..7f5033748ee --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/KarrthusTyrantOfJund.java @@ -0,0 +1,169 @@ +/* + * 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.alarareborn; + +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.GainAbilityAllEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author jeffwadsworth + */ +public class KarrthusTyrantOfJund extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("all dragons you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(new SubtypePredicate("Dragon")); + } + + public KarrthusTyrantOfJund(UUID ownerId) { + super(ownerId, 117, "Karrthus, Tyrant of Jund", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{4}{B}{R}{G}"); + this.expansionSetCode = "ARB"; + this.supertype.add("Legendary"); + this.subtype.add("Dragon"); + + this.color.setRed(true); + this.color.setGreen(true); + this.color.setBlack(true); + this.power = new MageInt(7); + this.toughness = new MageInt(7); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // When Karrthus, Tyrant of Jund enters the battlefield, gain control of all Dragons, then untap all Dragons. + this.addAbility(new EntersBattlefieldTriggeredAbility(new KarrthusEffect())); + + // Other Dragon creatures you control have haste. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter, true))); + + } + + public KarrthusTyrantOfJund(final KarrthusTyrantOfJund card) { + super(card); + } + + @Override + public KarrthusTyrantOfJund copy() { + return new KarrthusTyrantOfJund(this); + } +} + +class KarrthusEffect extends OneShotEffect { + + public KarrthusEffect() { + super(Outcome.GainControl); + this.staticText = "gain control of all dragons"; + } + + public KarrthusEffect(final KarrthusEffect effect) { + super(effect); + } + + @Override + public KarrthusEffect copy() { + return new KarrthusEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + FilterPermanent filter = new FilterPermanent(); + filter.add(new SubtypePredicate("Dragon")); + List dragons = game.getBattlefield().getAllActivePermanents(filter, game); + for (Permanent dragon : dragons) { + ContinuousEffect effect = new KarrthusControlEffect(source.getControllerId()); + effect.setTargetPointer(new FixedTarget(dragon.getId())); + game.addEffect(effect, source); + } + for (Permanent dragon : dragons) { + dragon.untap(game); + } + return true; + } +} + +class KarrthusControlEffect extends ContinuousEffectImpl { + + private UUID controllerId; + + public KarrthusControlEffect(UUID controllerId) { + super(Duration.EndOfGame, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); + this.controllerId = controllerId; + } + + public KarrthusControlEffect(final KarrthusControlEffect effect) { + super(effect); + this.controllerId = effect.controllerId; + } + + @Override + public KarrthusControlEffect copy() { + return new KarrthusControlEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent dragon = game.getPermanent(targetPointer.getFirst(game, source)); + if (dragon != null && controllerId != null) { + return dragon.changeControllerId(controllerId, game); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/KathariBomber.java b/Mage.Sets/src/mage/sets/alarareborn/KathariBomber.java new file mode 100644 index 00000000000..274527612db --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/KathariBomber.java @@ -0,0 +1,80 @@ +/* + * 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.alarareborn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.UnearthAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.permanent.token.GoblinToken; + +/** + * + * @author LevelX2 + */ +public class KathariBomber extends CardImpl { + + public KathariBomber(UUID ownerId) { + super(ownerId, 41, "Kathari Bomber", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}{R}"); + this.expansionSetCode = "ARB"; + this.subtype.add("Bird"); + this.subtype.add("Shaman"); + + this.color.setRed(true); + this.color.setBlack(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // When Kathari Bomber deals combat damage to a player, put two 1/1 red Goblin creature tokens onto the battlefield and sacrifice Kathari Bomber. + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new CreateTokenEffect(new GoblinToken(), 2), false); + ability.addEffect(new SacrificeSourceEffect()); + this.addAbility(ability); + + // Unearth {3}{B}{R} + this.addAbility(new UnearthAbility(new ManaCostsImpl("{3}{B}{R}"))); + } + + public KathariBomber(final KathariBomber card) { + super(card); + } + + @Override + public KathariBomber copy() { + return new KathariBomber(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/KnightOfNewAlara.java b/Mage.Sets/src/mage/sets/alarareborn/KnightOfNewAlara.java new file mode 100644 index 00000000000..505fbc33c52 --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/KnightOfNewAlara.java @@ -0,0 +1,150 @@ +/* + * 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.alarareborn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.MulticoloredPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author jeffwadsworth + */ +public class KnightOfNewAlara extends CardImpl { + + public KnightOfNewAlara(UUID ownerId) { + super(ownerId, 70, "Knight of New Alara", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{G}{W}"); + this.expansionSetCode = "ARB"; + this.subtype.add("Human"); + this.subtype.add("Knight"); + + this.color.setGreen(true); + this.color.setWhite(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Each other multicolored creature you control gets +1/+1 for each of its colors. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KnightOfNewAlaraEffect())); + + } + + public KnightOfNewAlara(final KnightOfNewAlara card) { + super(card); + } + + @Override + public KnightOfNewAlara copy() { + return new KnightOfNewAlara(this); + } +} + +class KnightOfNewAlaraEffect extends ContinuousEffectImpl { + + public KnightOfNewAlaraEffect() { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.BoostCreature); + staticText = "Each other multicolored creature you control gets +1/+1 for each of its colors"; + } + + public KnightOfNewAlaraEffect(final KnightOfNewAlaraEffect effect) { + super(effect); + } + + @Override + public KnightOfNewAlaraEffect copy() { + return new KnightOfNewAlaraEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + filter.add(new MulticoloredPredicate()); + for (Permanent creature : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { + DynamicValue colors = new KnightOfNewAlaraColorCount(creature); + if (creature != null + && creature != game.getPermanent(source.getSourceId())) { + creature.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(colors, colors, Duration.WhileOnBattlefield)), source.getId(), game); + } + } + return true; + } +} + +class KnightOfNewAlaraColorCount implements DynamicValue { + + final Permanent creature; + private int count; + + public KnightOfNewAlaraColorCount(Permanent creature) { + this.creature = creature; + this.count = 0; + } + + public KnightOfNewAlaraColorCount(final KnightOfNewAlaraColorCount dynamicValue) { + this.creature = dynamicValue.creature; + this.count = dynamicValue.count; + } + + @Override + public int calculate(Game game, Ability source) { + if (creature != null) { + count = creature.getColor().getColorCount(); + } + return count; + } + + @Override + public DynamicValue copy() { + return new KnightOfNewAlaraColorCount(this); + } + + @Override + public String toString() { + return "1"; + } + + @Override + public String getMessage() { + return "of its colors"; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/alarareborn/LeoninArmorguard.java b/Mage.Sets/src/mage/sets/alarareborn/LeoninArmorguard.java new file mode 100644 index 00000000000..17ffd5b5ebf --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/LeoninArmorguard.java @@ -0,0 +1,77 @@ +/* + * 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.alarareborn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.continious.BoostAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; + +/** + * + * @author jeffwadsworth + */ +public class LeoninArmorguard extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public LeoninArmorguard(UUID ownerId) { + super(ownerId, 72, "Leonin Armorguard", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}{W}"); + this.expansionSetCode = "ARB"; + this.subtype.add("Cat"); + this.subtype.add("Soldier"); + + this.color.setGreen(true); + this.color.setWhite(true); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Leonin Armorguard enters the battlefield, creatures you control get +1/+1 until end of turn. + this.addAbility(new EntersBattlefieldTriggeredAbility(new BoostAllEffect(1, 1, Duration.EndOfTurn, filter, false))); + } + + public LeoninArmorguard(final LeoninArmorguard card) { + super(card); + } + + @Override + public LeoninArmorguard copy() { + return new LeoninArmorguard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/RebornHope.java b/Mage.Sets/src/mage/sets/alarareborn/RebornHope.java new file mode 100644 index 00000000000..2ee8ed947cc --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/RebornHope.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.alarareborn; + +import java.util.UUID; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.MulticoloredPredicate; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author jeffwadsworth + */ +public class RebornHope extends CardImpl { + + private static final FilterCard filter = new FilterCard("multicolored card from your graveyard"); + + static { + filter.add(new MulticoloredPredicate()); + } + + public RebornHope(UUID ownerId) { + super(ownerId, 76, "Reborn Hope", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{G}{W}"); + this.expansionSetCode = "ARB"; + + this.color.setGreen(true); + this.color.setWhite(true); + + // Return target multicolored card from your graveyard to your hand. + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(filter)); + this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()); + } + + public RebornHope(final RebornHope card) { + super(card); + } + + @Override + public RebornHope copy() { + return new RebornHope(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/ShieldOfTheRighteous.java b/Mage.Sets/src/mage/sets/alarareborn/ShieldOfTheRighteous.java new file mode 100644 index 00000000000..9f77c7164ac --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/ShieldOfTheRighteous.java @@ -0,0 +1,80 @@ +/* + * 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.alarareborn; + +import java.util.UUID; +import mage.abilities.common.BlocksAttachedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.SkipNextUntapTargetEffect; +import mage.abilities.effects.common.continious.BoostEquippedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public class ShieldOfTheRighteous extends CardImpl { + + public ShieldOfTheRighteous(UUID ownerId) { + super(ownerId, 11, "Shield of the Righteous", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{W}{U}"); + this.expansionSetCode = "ARB"; + this.subtype.add("Equipment"); + + this.color.setBlue(true); + this.color.setWhite(true); + + // Equipped creature gets +0/+2 and has vigilance. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(0, 2))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.EQUIPMENT))); + + // Whenever equipped creature blocks a creature, that creature doesn't untap during its controller's next untap step. + this.addAbility(new BlocksAttachedTriggeredAbility(new SkipNextUntapTargetEffect("that creature"), "equipped", false, false, true)); + + // Equip {2} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), new TargetControlledCreaturePermanent())); + } + + public ShieldOfTheRighteous(final ShieldOfTheRighteous card) { + super(card); + } + + @Override + public ShieldOfTheRighteous copy() { + return new ShieldOfTheRighteous(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/ThoughtHemorrhage.java b/Mage.Sets/src/mage/sets/alarareborn/ThoughtHemorrhage.java new file mode 100644 index 00000000000..827e158f24f --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/ThoughtHemorrhage.java @@ -0,0 +1,133 @@ +/* + * 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.alarareborn; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.repository.CardRepository; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetPlayer; + +/** + * + * @author jeffwadsworth + */ +public class ThoughtHemorrhage extends CardImpl { + + public ThoughtHemorrhage(UUID ownerId) { + super(ownerId, 47, "Thought Hemorrhage", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{B}{R}"); + this.expansionSetCode = "ARB"; + + this.color.setRed(true); + this.color.setBlack(true); + + // Name a nonland card. Target player reveals his or her hand. Thought Hemorrhage deals 3 damage to that player for each card with that name revealed this way. Search that player's graveyard, hand, and library for all cards with that name and exile them. Then that player shuffles his or her library. + this.getSpellAbility().addTarget(new TargetPlayer()); + this.getSpellAbility().addEffect(new ThoughtHemorrhageEffect()); + } + + public ThoughtHemorrhage(final ThoughtHemorrhage card) { + super(card); + } + + @Override + public ThoughtHemorrhage copy() { + return new ThoughtHemorrhage(this); + } +} + +class ThoughtHemorrhageEffect extends OneShotEffect { + + String cardName; + final String rule = "Name a nonland card. Target player reveals his or her hand. Thought Hemorrhage deals 3 damage to that player for each card with that name revealed this way. Search that player's graveyard, hand, and library for all cards with that name and exile them. Then that player shuffles his or her library"; + + public ThoughtHemorrhageEffect() { + super(Outcome.Detriment); + staticText = rule; + } + + public ThoughtHemorrhageEffect(final ThoughtHemorrhageEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player you = game.getPlayer(source.getControllerId()); + if (you != null) { + Choice cardChoice = new ChoiceImpl(); + cardChoice.setChoices(CardRepository.instance.getNonLandNames()); + cardChoice.clearChoice(); + while (!you.choose(Outcome.Detriment, cardChoice, game)) { + game.debugMessage("player canceled choosing name. retrying."); + } + cardName = cardChoice.getChoice(); + game.informPlayers("Thought Hemorrhage, named card: [" + cardName + "]"); + } + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + if (targetPlayer != null) { + targetPlayer.revealCards("hand of target player", targetPlayer.getHand(), game); + for (Card card : targetPlayer.getHand().getCards(game)) { + if (card.getName().equals(cardName)) { + targetPlayer.damage(3, source.getId(), game, false, true); + } + } + for (Card card : targetPlayer.getGraveyard().getCards(game)) { + if (card.getName().equals(cardName)) { + card.moveToExile(null, "", source.getId(), game); + } + } + for (Card card : targetPlayer.getHand().getCards(game)) { + if (card.getName().equals(cardName)) { + card.moveToExile(null, "", source.getId(), game); + } + } + for (Card card : targetPlayer.getLibrary().getCards(game)) { + if (card.getName().equals(cardName)) { + card.moveToExile(null, "", source.getId(), game); + } + } + targetPlayer.shuffleLibrary(game); + return true; + } + return false; + } + + @Override + public ThoughtHemorrhageEffect copy() { + return new ThoughtHemorrhageEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/alarareborn/UnscytheKillerOfKings.java b/Mage.Sets/src/mage/sets/alarareborn/UnscytheKillerOfKings.java new file mode 100644 index 00000000000..b9e4fdc70bb --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/UnscytheKillerOfKings.java @@ -0,0 +1,207 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.alarareborn; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.BoostEquippedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.ZombieToken; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.targetpointer.FixedTarget; +import mage.watchers.WatcherImpl; + +/** + * + * @author jeffwadsworth + */ +public class UnscytheKillerOfKings extends CardImpl { + + public UnscytheKillerOfKings(UUID ownerId) { + super(ownerId, 114, "Unscythe, Killer of Kings", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{R}"); + this.expansionSetCode = "ARB"; + this.supertype.add("Legendary"); + this.subtype.add("Equipment"); + + this.color.setRed(true); + this.color.setBlue(true); + this.color.setBlack(true); + + // Equipped creature gets +3/+3 and has first strike. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 3))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT))); + + // Whenever a creature dealt damage by equipped creature this turn dies, you may exile that card. If you do, put a 2/2 black Zombie creature token onto the battlefield. + this.addAbility(new UnscytheKillerOfKingsTriggeredAbility(new UnscytheEffect())); + this.addWatcher(new EquippedDidDamageWatcher()); + + // Equip {2} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), new TargetControlledCreaturePermanent())); + } + + public UnscytheKillerOfKings(final UnscytheKillerOfKings card) { + super(card); + } + + @Override + public UnscytheKillerOfKings copy() { + return new UnscytheKillerOfKings(this); + } +} + +class UnscytheKillerOfKingsTriggeredAbility extends TriggeredAbilityImpl { + + public UnscytheKillerOfKingsTriggeredAbility(Effect effect) { + this(effect, true); + } + + public UnscytheKillerOfKingsTriggeredAbility(Effect effect, boolean optional) { + super(Zone.ALL, effect, optional); + } + + public UnscytheKillerOfKingsTriggeredAbility(final UnscytheKillerOfKingsTriggeredAbility ability) { + super(ability); + } + + @Override + public UnscytheKillerOfKingsTriggeredAbility copy() { + return new UnscytheKillerOfKingsTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent) event).isDiesEvent()) { + Card card = game.getCard(event.getTargetId()); + if (card != null) { + EquippedDidDamageWatcher watcher = (EquippedDidDamageWatcher) game.getState().getWatchers().get("equippedDamagedTargets", this.getSourceId()); + if (watcher != null + && watcher.equippedDamagedTargets.contains(event.getTargetId())) { + Effect effect = this.getEffects().get(0); + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + return true; + } + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever a creature dealt damage by {this} this turn dies, " + super.getRule(); + } +} + +class UnscytheEffect extends OneShotEffect { + + public UnscytheEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "put a 2/2 black Zombie creature token onto the battlefield"; + } + + public UnscytheEffect(final UnscytheEffect effect) { + super(effect); + } + + @Override + public UnscytheEffect copy() { + return new UnscytheEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(targetPointer.getFirst(game, source)); + if (card != null) { + if (card.moveToExile(null, "Unscythe Exile", source.getId(), game)) { + ZombieToken zombie = new ZombieToken(); + return zombie.putOntoBattlefield(1, game, source.getId(), source.getControllerId()); + } + } + return false; + } +} + +class EquippedDidDamageWatcher extends WatcherImpl { + + public List equippedDamagedTargets = new ArrayList(); + + public EquippedDidDamageWatcher() { + super("equippedDamagedTargets", WatcherScope.CARD); + } + + public EquippedDidDamageWatcher(final EquippedDidDamageWatcher watcher) { + super(watcher); + this.equippedDamagedTargets.addAll(watcher.equippedDamagedTargets); + } + + @Override + public EquippedDidDamageWatcher copy() { + return new EquippedDidDamageWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == EventType.DAMAGED_CREATURE) { + Permanent permanent = game.getPermanent(event.getSourceId()); + if (permanent != null) { + if (permanent.getAttachments().contains(this.getSourceId())) { + if (!equippedDamagedTargets.contains(event.getTargetId())) { + equippedDamagedTargets.add(event.getTargetId()); + } + } + } + } + } + + @Override + public void reset() { + super.reset(); + equippedDamagedTargets.clear(); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/alarareborn/VectisDominator.java b/Mage.Sets/src/mage/sets/alarareborn/VectisDominator.java new file mode 100644 index 00000000000..e76cd593fe5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/alarareborn/VectisDominator.java @@ -0,0 +1,121 @@ +/* + * 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.alarareborn; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public class VectisDominator extends CardImpl { + + public VectisDominator(UUID ownerId) { + super(ownerId, 84, "Vectis Dominator", Rarity.COMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}{W}{B}"); + this.expansionSetCode = "ARB"; + this.subtype.add("Human"); + this.subtype.add("Wizard"); + + this.color.setBlack(true); + this.color.setWhite(true); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // {tap}: Tap target creature unless its controller pays 2 life. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new VectisDominatorEffect(new PayLifeCost(2)), new ManaCostsImpl("{1}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public VectisDominator(final VectisDominator card) { + super(card); + } + + @Override + public VectisDominator copy() { + return new VectisDominator(this); + } +} + +class VectisDominatorEffect extends OneShotEffect { + + protected Cost cost; + + public VectisDominatorEffect(Cost cost) { + super(Outcome.Detriment); + this.staticText = "Tap target creature unless its controller pays 2 life"; + this.cost = cost; + } + + public VectisDominatorEffect(final VectisDominatorEffect effect) { + super(effect); + this.cost = effect.cost.copy(); + } + + @Override + public VectisDominatorEffect copy() { + return new VectisDominatorEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent targetCreature = game.getPermanent(source.getFirstTarget()); + if (targetCreature != null) { + Player player = game.getPlayer(targetCreature.getControllerId()); + if (player != null) { + cost.clearPaid(); + final StringBuilder sb = new StringBuilder("Pay 2 life otherwise ").append(targetCreature.getName()).append(" will be tapped)"); + if (player.chooseUse(Outcome.Benefit, sb.toString(), game)) { + cost.pay(source, game, targetCreature.getControllerId(), targetCreature.getControllerId(), true); + } + if (!cost.isPaid()) { + return targetCreature.tap(game); + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/HorobisWhisper.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/HorobisWhisper.java new file mode 100644 index 00000000000..32fe18a1506 --- /dev/null +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/HorobisWhisper.java @@ -0,0 +1,90 @@ +/* + * 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.betrayersofkamigawa; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.condition.common.ControlsPermanentCondition; +import mage.abilities.costs.common.ExileFromGraveCost; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.SpliceOntoArcaneAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class HorobisWhisper extends CardImpl { + + private static final FilterCreaturePermanent filterTarget = new FilterCreaturePermanent("nonblack creature"); + private static final FilterLandPermanent filterCondition = new FilterLandPermanent("Swamp"); + + static { + filterTarget.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); + filterCondition.add(new SubtypePredicate("Swamp")); + } + + public HorobisWhisper(UUID ownerId) { + super(ownerId, 70, "Horobi's Whisper", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{B}{B}"); + this.expansionSetCode = "BOK"; + this.subtype.add("Arcane"); + + this.color.setBlack(true); + + + // If you control a Swamp, destroy target nonblack creature. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new DestroyTargetEffect(), + new ControlsPermanentCondition(filterCondition),"If you control a Swamp, destroy target nonblack creature")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterTarget) ); + + // Splice onto Arcane-Exile four cards from your graveyard. + this.addAbility(new SpliceOntoArcaneAbility(new ExileFromGraveCost(new TargetCardInYourGraveyard(4,4, new FilterCard("cards"))))); + + + } + + public HorobisWhisper(final HorobisWhisper card) { + super(card); + } + + @Override + public HorobisWhisper copy() { + return new HorobisWhisper(this); + } +} diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/TorrentOfStone.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/TorrentOfStone.java new file mode 100644 index 00000000000..8c77e1470a5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/TorrentOfStone.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.betrayersofkamigawa; + +import java.util.UUID; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.SpliceOntoArcaneAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetControlledPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class TorrentOfStone extends CardImpl { + private static final FilterLandPermanent filterSacrifice = new FilterLandPermanent("two Mountains"); + + static { + filterSacrifice.add(new SubtypePredicate("Mountain")); + } + + public TorrentOfStone(UUID ownerId) { + super(ownerId, 119, "Torrent of Stone", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{3}{R}"); + this.expansionSetCode = "BOK"; + this.subtype.add("Arcane"); + + this.color.setRed(true); + + // Torrent of Stone deals 4 damage to target creature. + this.getSpellAbility().addEffect(new DamageTargetEffect(4)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + // Splice onto Arcane-Sacrifice two Mountains. + this.addAbility(new SpliceOntoArcaneAbility(new SacrificeTargetCost(new TargetControlledPermanent(2,2, filterSacrifice, false)))); + } + + public TorrentOfStone(final TorrentOfStone card) { + super(card); + } + + @Override + public TorrentOfStone copy() { + return new TorrentOfStone(this); + } +} diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/DampenThought.java b/Mage.Sets/src/mage/sets/championsofkamigawa/DampenThought.java new file mode 100644 index 00000000000..d055d3a1754 --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/DampenThought.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.championsofkamigawa; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class DampenThought extends mage.sets.modernmasters.DampenThought { + + public DampenThought(UUID ownerId) { + super(ownerId); + this.cardNumber = 57; + this.expansionSetCode = "CHK"; + this.rarity = Rarity.UNCOMMON; + } + + public DampenThought(final DampenThought card) { + super(card); + } + + @Override + public DampenThought copy() { + return new DampenThought(this); + } +} diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/DesperateRitual.java b/Mage.Sets/src/mage/sets/championsofkamigawa/DesperateRitual.java new file mode 100644 index 00000000000..f77e08f550d --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/DesperateRitual.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.championsofkamigawa; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class DesperateRitual extends mage.sets.modernmasters.DesperateRitual { + + public DesperateRitual(UUID ownerId) { + super(ownerId); + this.cardNumber = 163; + this.expansionSetCode = "CHK"; + this.rarity = Rarity.COMMON; + } + + public DesperateRitual(final DesperateRitual card) { + super(card); + } + + @Override + public DesperateRitual copy() { + return new DesperateRitual(this); + } +} diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/Earthshaker.java b/Mage.Sets/src/mage/sets/championsofkamigawa/Earthshaker.java index e7920ce8105..f658d9eb202 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/Earthshaker.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/Earthshaker.java @@ -62,6 +62,7 @@ public class Earthshaker extends CardImpl { this.color.setRed(true); this.power = new MageInt(4); this.toughness = new MageInt(5); + // Whenever you cast a Spirit or Arcane spell, Earthshaker deals 2 damage to each creature without flying. this.addAbility(new SpellCastTriggeredAbility(new DamageAllEffect(new StaticValue(2) , creatureFilter), filter, false)); } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/GlacialRay.java b/Mage.Sets/src/mage/sets/championsofkamigawa/GlacialRay.java new file mode 100644 index 00000000000..4fcec2c79cb --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/GlacialRay.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.championsofkamigawa; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class GlacialRay extends mage.sets.modernmasters.GlacialRay { + + public GlacialRay(UUID ownerId) { + super(ownerId); + this.cardNumber = 168; + this.expansionSetCode = "CHK"; + } + + public GlacialRay(final GlacialRay card) { + super(card); + } + + @Override + public GlacialRay copy() { + return new GlacialRay(this); + } +} diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/KodamasReach.java b/Mage.Sets/src/mage/sets/championsofkamigawa/KodamasReach.java new file mode 100644 index 00000000000..0929eb3d74a --- /dev/null +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/KodamasReach.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.championsofkamigawa; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class KodamasReach extends mage.sets.commander.KodamasReach { + + public KodamasReach(UUID ownerId) { + super(ownerId); + this.cardNumber = 225; + this.expansionSetCode = "CHK"; + } + + public KodamasReach(final KodamasReach card) { + super(card); + } + + @Override + public KodamasReach copy() { + return new KodamasReach(this); + } +} diff --git a/Mage.Sets/src/mage/sets/commander/AustereCommand.java b/Mage.Sets/src/mage/sets/commander/AustereCommand.java new file mode 100644 index 00000000000..a6f6581c2d3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/commander/AustereCommand.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.commander; + +import java.util.UUID; +import mage.abilities.Mode; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.Filter; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterEnchantmentPermanent; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; + +/** + * + * @author LevelX2 + */ +public class AustereCommand extends CardImpl { + + private static final FilterCreaturePermanent filter3orLess = new FilterCreaturePermanent("creatures with converted mana cost 3 or less"); + private static final FilterCreaturePermanent filter4orMore = new FilterCreaturePermanent("creatures with converted mana cost 4 or greater"); + static { + filter3orLess.add(new ConvertedManaCostPredicate(Filter.ComparisonType.LessThan, 4)); + filter4orMore.add(new ConvertedManaCostPredicate(Filter.ComparisonType.GreaterThan, 3)); + } + + public AustereCommand(UUID ownerId) { + super(ownerId, 8, "Austere Command", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{W}{W}"); + this.expansionSetCode = "CMD"; + + this.color.setWhite(true); + + // Choose two - + this.getSpellAbility().getModes().setMinModes(2); + this.getSpellAbility().getModes().setMaxModes(2); + // Destroy all artifacts; + this.getSpellAbility().addEffect(new DestroyAllEffect(new FilterArtifactPermanent("artifacts"))); + // or destroy all enchantments; + Mode mode = new Mode(); + mode.getEffects().add(new DestroyAllEffect(new FilterEnchantmentPermanent("enchantments"))); + this.getSpellAbility().getModes().addMode(mode); + // or destroy all creatures with converted mana cost 3 or less; + mode = new Mode(); + mode.getEffects().add(new DestroyAllEffect(filter3orLess)); + this.getSpellAbility().getModes().addMode(mode); + // or destroy all creatures with converted mana cost 4 or greater. + mode = new Mode(); + mode.getEffects().add(new DestroyAllEffect(filter4orMore)); + this.getSpellAbility().getModes().addMode(mode); + } + + public AustereCommand(final AustereCommand card) { + super(card); + } + + @Override + public AustereCommand copy() { + return new AustereCommand(this); + } +} diff --git a/Mage.Sets/src/mage/sets/commander/KodamasReach.java b/Mage.Sets/src/mage/sets/commander/KodamasReach.java new file mode 100644 index 00000000000..f05fa597b13 --- /dev/null +++ b/Mage.Sets/src/mage/sets/commander/KodamasReach.java @@ -0,0 +1,139 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.commander; + +import java.util.List; +import java.util.UUID; +import mage.abilities.Ability; +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.common.FilterBasicLandCard; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author LevelX2 + */ +public class KodamasReach extends CardImpl { + + public KodamasReach(UUID ownerId) { + super(ownerId, 163, "Kodama's Reach", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{G}"); + this.expansionSetCode = "CMD"; + this.subtype.add("Arcane"); + + this.color.setGreen(true); + + // Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Then shuffle your library. + this.getSpellAbility().addEffect(new KodamasReachEffect()); + } + + public KodamasReach(final KodamasReach card) { + super(card); + } + + @Override + public KodamasReach copy() { + return new KodamasReach(this); + } +} + +class KodamasReachEffect extends OneShotEffect { + + protected static final FilterCard filter = new FilterCard("card to put on the battlefield tapped"); + + public KodamasReachEffect() { + super(Outcome.PutLandInPlay); + staticText = "Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Then shuffle your library"; + } + + public KodamasReachEffect(final KodamasReachEffect effect) { + super(effect); + } + + @Override + public KodamasReachEffect copy() { + return new KodamasReachEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + TargetCardInLibrary target = new TargetCardInLibrary(0, 2, new FilterBasicLandCard()); + Player player = game.getPlayer(source.getControllerId()); + if (player.searchLibrary(target, game)) { + if (target.getTargets().size() > 0) { + Cards revealed = new CardsImpl(); + for (UUID cardId: (List)target.getTargets()) { + Card card = player.getLibrary().getCard(cardId, game); + revealed.add(card); + } + player.revealCards("Kodama's Reach", revealed, game); + if (target.getTargets().size() == 2) { + TargetCard target2 = new TargetCard(Zone.PICK, filter); + target2.setRequired(true); + player.choose(Outcome.Benefit, revealed, target2, game); + Card card = revealed.get(target2.getFirstTarget(), game); + card.putOntoBattlefield(game, Zone.LIBRARY, source.getId(), source.getControllerId()); + revealed.remove(card); + Permanent permanent = game.getPermanent(card.getId()); + if (permanent != null) { + permanent.setTapped(true); + } + card = revealed.getCards(game).iterator().next(); + card.moveToZone(Zone.HAND, source.getId(), game, false); + } + else if (target.getTargets().size() == 1) { + Card card = revealed.getCards(game).iterator().next(); + card.putOntoBattlefield(game, Zone.LIBRARY, source.getId(), source.getControllerId()); + Permanent permanent = game.getPermanent(card.getId()); + if (permanent != null) { + permanent.setTapped(true); + } + } + + } + player.shuffleLibrary(game); + return true; + } + player.shuffleLibrary(game); + return false; + + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/conflux/BrackwaterElemental.java b/Mage.Sets/src/mage/sets/conflux/BrackwaterElemental.java new file mode 100644 index 00000000000..b6b5c4ec8df --- /dev/null +++ b/Mage.Sets/src/mage/sets/conflux/BrackwaterElemental.java @@ -0,0 +1,108 @@ +/* + * 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.conflux; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.AttacksOrBlocksTriggeredAbility; +import mage.abilities.common.delayed.AtEndOfTurnDelayedTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.abilities.keyword.UnearthAbility; +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.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class BrackwaterElemental extends CardImpl { + + public BrackwaterElemental(UUID ownerId) { + super(ownerId, 21, "Brackwater Elemental", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{U}"); + this.expansionSetCode = "CON"; + this.subtype.add("Elemental"); + + this.color.setBlue(true); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // When Brackwater Elemental attacks or blocks, sacrifice it at the beginning of the next end step. + this.addAbility(new AttacksOrBlocksTriggeredAbility(new BrackwaterElementalSacrificeEffect(), false)); + // Unearth {2}{U} + this.addAbility(new UnearthAbility(new ManaCostsImpl("{2}{U}"))); + } + + public BrackwaterElemental(final BrackwaterElemental card) { + super(card); + } + + @Override + public BrackwaterElemental copy() { + return new BrackwaterElemental(this); + } +} + +class BrackwaterElementalSacrificeEffect extends OneShotEffect { + + public BrackwaterElementalSacrificeEffect() { + super(Outcome.Sacrifice); + this.staticText = "sacrifice it at the beginning of the next end step"; + } + + public BrackwaterElementalSacrificeEffect(final BrackwaterElementalSacrificeEffect effect) { + super(effect); + } + + @Override + public BrackwaterElementalSacrificeEffect copy() { + return new BrackwaterElementalSacrificeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent != null) { + SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("sacrifice {this}"); + sacrificeEffect.setTargetPointer(new FixedTarget(sourcePermanent.getId())); + DelayedTriggeredAbility delayedAbility = new AtEndOfTurnDelayedTriggeredAbility(sacrificeEffect); + delayedAbility.setSourceId(source.getSourceId()); + delayedAbility.setControllerId(source.getControllerId()); + game.addDelayedTriggeredAbility(delayedAbility); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/conflux/EtherswornAdjudicator.java b/Mage.Sets/src/mage/sets/conflux/EtherswornAdjudicator.java index e858987dfbd..4451bc8fc3b 100644 --- a/Mage.Sets/src/mage/sets/conflux/EtherswornAdjudicator.java +++ b/Mage.Sets/src/mage/sets/conflux/EtherswornAdjudicator.java @@ -63,7 +63,7 @@ public class EtherswornAdjudicator extends CardImpl { public EtherswornAdjudicator(UUID ownerId) { super(ownerId, 26, "Ethersworn Adjudicator", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}{U}"); this.expansionSetCode = "CON"; - this.supertype.add("Legendary"); + this.subtype.add("Vedalken"); this.subtype.add("Knight"); this.color.setBlue(true); diff --git a/Mage.Sets/src/mage/sets/darkascension/FaithlessLooting.java b/Mage.Sets/src/mage/sets/darkascension/FaithlessLooting.java index 010a6220169..1e690ccfa48 100644 --- a/Mage.Sets/src/mage/sets/darkascension/FaithlessLooting.java +++ b/Mage.Sets/src/mage/sets/darkascension/FaithlessLooting.java @@ -32,8 +32,7 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.DiscardControllerEffect; -import mage.abilities.effects.common.DrawCardControllerEffect; +import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.constants.TimingRule; @@ -51,8 +50,7 @@ public class FaithlessLooting extends CardImpl { this.color.setRed(true); // Draw two cards, then discard two cards. - this.getSpellAbility().addEffect(new DrawCardControllerEffect(2)); - this.getSpellAbility().addEffect(new DiscardControllerEffect(2)); + this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(2,2)); // Flashback {2}{R} this.addAbility(new FlashbackAbility(new ManaCostsImpl("{2}{R}"), TimingRule.SORCERY)); } diff --git a/Mage.Sets/src/mage/sets/darksteel/StirThePride.java b/Mage.Sets/src/mage/sets/darksteel/StirThePride.java new file mode 100644 index 00000000000..866b3ac875c --- /dev/null +++ b/Mage.Sets/src/mage/sets/darksteel/StirThePride.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.darksteel; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class StirThePride extends mage.sets.modernmasters.StirThePride { + + public StirThePride(UUID ownerId) { + super(ownerId); + this.cardNumber = 16; + this.expansionSetCode = "DST"; + } + + public StirThePride(final StirThePride card) { + super(card); + } + + @Override + public StirThePride copy() { + return new StirThePride(this); + } +} diff --git a/Mage.Sets/src/mage/sets/darksteel/TestOfFaith.java b/Mage.Sets/src/mage/sets/darksteel/TestOfFaith.java new file mode 100644 index 00000000000..a49381d692c --- /dev/null +++ b/Mage.Sets/src/mage/sets/darksteel/TestOfFaith.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.darksteel; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class TestOfFaith extends mage.sets.modernmasters.TestOfFaith { + + public TestOfFaith(UUID ownerId) { + super(ownerId); + this.cardNumber = 17; + this.expansionSetCode = "DST"; + this.rarity = Rarity.UNCOMMON; + } + + public TestOfFaith(final TestOfFaith card) { + super(card); + } + + @Override + public TestOfFaith copy() { + return new TestOfFaith(this); + } +} diff --git a/Mage.Sets/src/mage/sets/dissension/TrygonPredator.java b/Mage.Sets/src/mage/sets/dissension/TrygonPredator.java new file mode 100644 index 00000000000..e1417dabe0b --- /dev/null +++ b/Mage.Sets/src/mage/sets/dissension/TrygonPredator.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.dissension; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class TrygonPredator extends mage.sets.modernmasters.TrygonPredator { + + public TrygonPredator(UUID ownerId) { + super(ownerId); + this.cardNumber = 133; + this.expansionSetCode = "DIS"; + } + + public TrygonPredator(final TrygonPredator card) { + super(card); + } + + @Override + public TrygonPredator copy() { + return new TrygonPredator(this); + } +} diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/AdventOfTheWurm.java b/Mage.Sets/src/mage/sets/dragonsmaze/AdventOfTheWurm.java index 670e174ecfd..ea962b98eff 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/AdventOfTheWurm.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/AdventOfTheWurm.java @@ -75,6 +75,8 @@ public class AdventOfTheWurm extends CardImpl { subtype.add("Wurm"); power = new MageInt(5); toughness = new MageInt(5); + expansionSetCode = "RTR"; + addAbility(TrampleAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/sets/eighthedition/FertileGround.java b/Mage.Sets/src/mage/sets/eighthedition/FertileGround.java new file mode 100644 index 00000000000..578e3953e2e --- /dev/null +++ b/Mage.Sets/src/mage/sets/eighthedition/FertileGround.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.eighthedition; + +import java.util.UUID; + +/** + * + * @author Plopman + */ +public class FertileGround extends mage.sets.urzassaga.FertileGround { + + public FertileGround(UUID ownerId) { + super(ownerId); + this.cardNumber = 248; + this.expansionSetCode = "8ED"; + } + + public FertileGround(final FertileGround card) { + super(card); + } + + @Override + public FertileGround copy() { + return new FertileGround(this); + } +} diff --git a/Mage.Sets/src/mage/sets/elspethvstezzeret/BlindingBeam.java b/Mage.Sets/src/mage/sets/elspethvstezzeret/BlindingBeam.java new file mode 100644 index 00000000000..48c84451200 --- /dev/null +++ b/Mage.Sets/src/mage/sets/elspethvstezzeret/BlindingBeam.java @@ -0,0 +1,158 @@ +/* + * 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.elspethvstezzeret; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class BlindingBeam extends CardImpl { + + public BlindingBeam(UUID ownerId) { + super(ownerId, 28, "Blinding Beam", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{W}"); + this.expansionSetCode = "DDF"; + + this.color.setWhite(true); + + // Choose one - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // Tap two target creatures; + this.getSpellAbility().addEffect(new TapTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(2,2)); + // or creatures don't untap during target player's next untap step. + Mode mode = new Mode(); + mode.getEffects().add(new BlindingBeamEffect()); + this.getSpellAbility().getModes().addMode(mode); + + // Entwine {1} + this.addAbility(new EntwineAbility("{1}")); + } + + public BlindingBeam(final BlindingBeam card) { + super(card); + } + + @Override + public BlindingBeam copy() { + return new BlindingBeam(this); + } +} + +class BlindingBeamEffect extends OneShotEffect { + + public BlindingBeamEffect() { + super(Outcome.Tap); + staticText = "creatures don't untap during target player's next untap step"; + } + + public BlindingBeamEffect(final BlindingBeamEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getFirstTarget()); + if (player != null) { + for (Permanent creature: game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game)) { + game.addEffect(new BlindingBeamEffect2(creature.getId()), source); + } + return true; + } + return false; + } + + @Override + public BlindingBeamEffect copy() { + return new BlindingBeamEffect(this); + } + +} + +class BlindingBeamEffect2 extends ReplacementEffectImpl { + + protected UUID creatureId; + + public BlindingBeamEffect2(UUID creatureId) { + super(Duration.OneUse, Outcome.Detriment); + this.creatureId = creatureId; + } + + public BlindingBeamEffect2(final BlindingBeamEffect2 effect) { + super(effect); + creatureId = effect.creatureId; + } + + @Override + public BlindingBeamEffect2 copy() { + return new BlindingBeamEffect2(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + used = true; + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (game.getTurn().getStepType() == PhaseStep.UNTAP && + event.getType() == EventType.UNTAP && + event.getTargetId().equals(creatureId)) { + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/eventide/BelligerentHatchling.java b/Mage.Sets/src/mage/sets/eventide/BelligerentHatchling.java index a9d574a10e4..81236cbdf16 100644 --- a/Mage.Sets/src/mage/sets/eventide/BelligerentHatchling.java +++ b/Mage.Sets/src/mage/sets/eventide/BelligerentHatchling.java @@ -28,16 +28,16 @@ package mage.sets.eventide; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SpellCastTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.counters.CounterType; import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ColorPredicate; @@ -63,9 +63,14 @@ public class BelligerentHatchling extends CardImpl { this.color.setWhite(true); this.power = new MageInt(6); this.toughness = new MageInt(6); + + // First strike this.addAbility(FirstStrikeAbility.getInstance()); - this.addAbility(new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(4)))); + // Belligerent Hatchling enters the battlefield with four -1/-1 counters on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(4)))); + // Whenever you cast a red spell, remove a -1/-1 counter from Belligerent Hatchling. this.addAbility(new SpellCastTriggeredAbility(new RemoveCounterSourceEffect(CounterType.M1M1.createInstance(1)), filterRedSpell, false)); + // Whenever you cast a white spell, remove a -1/-1 counter from Belligerent Hatchling. this.addAbility(new SpellCastTriggeredAbility(new RemoveCounterSourceEffect(CounterType.M1M1.createInstance(1)), filterWhiteSpell, false)); } diff --git a/Mage.Sets/src/mage/sets/eventide/CloutOfTheDominus.java b/Mage.Sets/src/mage/sets/eventide/CloutOfTheDominus.java new file mode 100644 index 00000000000..00e75989b87 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/CloutOfTheDominus.java @@ -0,0 +1,90 @@ +/* + * 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.eventide; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.ShroudAbility; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class CloutOfTheDominus extends CardImpl { + + public CloutOfTheDominus(UUID ownerId) { + super(ownerId, 99, "Clout of the Dominus", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{U/R}"); + this.expansionSetCode = "EVE"; + this.subtype.add("Aura"); + + this.color.setRed(true); + this.color.setBlue(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is blue, it gets +1/+1 and has shroud. + SimpleStaticAbility blueAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.BLUE), "As long as enchanted creature is black, it gets +1/+1")); + blueAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(ShroudAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.BLUE), "and has deathtouch")); + this.addAbility(blueAbility); + // As long as enchanted creature is red, it gets +1/+1 and has haste. + SimpleStaticAbility redAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.RED), "As long as enchanted creature is red, it gets +1/+1")); + redAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(HasteAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.RED), "and has haste")); + this.addAbility(redAbility); + } + + public CloutOfTheDominus(final CloutOfTheDominus card) { + super(card); + } + + @Override + public CloutOfTheDominus copy() { + return new CloutOfTheDominus(this); + } +} diff --git a/Mage.Sets/src/mage/sets/eventide/ColdEyedSelkie.java b/Mage.Sets/src/mage/sets/eventide/ColdEyedSelkie.java new file mode 100644 index 00000000000..8dbf6adb710 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/ColdEyedSelkie.java @@ -0,0 +1,105 @@ +/* + * 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.eventide; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.IslandwalkAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class ColdEyedSelkie extends CardImpl { + + public ColdEyedSelkie(UUID ownerId) { + super(ownerId, 149, "Cold-Eyed Selkie", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{G/U}{G/U}"); + this.expansionSetCode = "EVE"; + this.subtype.add("Merfolk"); + this.subtype.add("Rogue"); + + this.color.setBlue(true); + this.color.setGreen(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Islandwalk + this.addAbility(new IslandwalkAbility()); + // Whenever Cold-Eyed Selkie deals combat damage to a player, you may draw that many cards. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ColdEyeSelkieEffect(), true, true)); + + } + + public ColdEyedSelkie(final ColdEyedSelkie card) { + super(card); + } + + @Override + public ColdEyedSelkie copy() { + return new ColdEyedSelkie(this); + } +} + +class ColdEyeSelkieEffect extends OneShotEffect { + + public ColdEyeSelkieEffect() { + super(Outcome.DrawCard); + this.staticText = "draw that many cards"; + } + + public ColdEyeSelkieEffect(final ColdEyeSelkieEffect effect) { + super(effect); + } + + @Override + public ColdEyeSelkieEffect copy() { + return new ColdEyeSelkieEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = (Integer) getValue("damage"); + if (amount > 0) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.drawCards(amount, game); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/eventide/EdgeOfTheDivinity.java b/Mage.Sets/src/mage/sets/eventide/EdgeOfTheDivinity.java new file mode 100644 index 00000000000..29b3e28d798 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/EdgeOfTheDivinity.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.eventide; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.EnchantAbility; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class EdgeOfTheDivinity extends CardImpl { + + public EdgeOfTheDivinity(UUID ownerId) { + super(ownerId, 87, "Edge of the Divinity", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{W/B}"); + this.expansionSetCode = "EVE"; + this.subtype.add("Aura"); + + this.color.setBlack(true); + this.color.setWhite(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is white, it gets +1/+2. + SimpleStaticAbility whiteAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 2), new EnchantedCreatureColorCondition(ObjectColor.WHITE), "As long as enchanted creature is white, it gets +1/+2")); + this.addAbility(whiteAbility); + // As long as enchanted creature is black, it gets +2/+1. + SimpleStaticAbility blackAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(2, 1), new EnchantedCreatureColorCondition(ObjectColor.BLACK), "As long as enchanted creature is black, it gets +2/+1")); + this.addAbility(blackAbility); + } + + public EdgeOfTheDivinity(final EdgeOfTheDivinity card) { + super(card); + } + + @Override + public EdgeOfTheDivinity copy() { + return new EdgeOfTheDivinity(this); + } +} diff --git a/Mage.Sets/src/mage/sets/eventide/FavorOfTheOverbeing.java b/Mage.Sets/src/mage/sets/eventide/FavorOfTheOverbeing.java new file mode 100644 index 00000000000..fb9bc329c90 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/FavorOfTheOverbeing.java @@ -0,0 +1,90 @@ +/* + * 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.eventide; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class FavorOfTheOverbeing extends CardImpl { + + public FavorOfTheOverbeing(UUID ownerId) { + super(ownerId, 151, "Favor of the Overbeing", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{G/U}"); + this.expansionSetCode = "EVE"; + this.subtype.add("Aura"); + + this.color.setBlue(true); + this.color.setGreen(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is green, it gets +1/+1 and has vigilance. + SimpleStaticAbility greenAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.GREEN), "As long as enchanted creature is green, it gets +1/+1")); + greenAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.GREEN), "and has vigilance")); + this.addAbility(greenAbility); + // As long as enchanted creature is blue, it gets +1/+1 and has flying. + SimpleStaticAbility blueAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.BLUE), "As long as enchanted creature is blue, it gets +1/+1")); + blueAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.BLUE), "and has flying")); + this.addAbility(blueAbility); + } + + public FavorOfTheOverbeing(final FavorOfTheOverbeing card) { + super(card); + } + + @Override + public FavorOfTheOverbeing copy() { + return new FavorOfTheOverbeing(this); + } +} diff --git a/Mage.Sets/src/mage/sets/eventide/GiftOfTheDeity.java b/Mage.Sets/src/mage/sets/eventide/GiftOfTheDeity.java new file mode 100644 index 00000000000..5d83ce804e5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/GiftOfTheDeity.java @@ -0,0 +1,89 @@ +/* + * 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.eventide; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.MustBlockAttachedEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class GiftOfTheDeity extends CardImpl { + + public GiftOfTheDeity(UUID ownerId) { + super(ownerId, 122, "Gift of the Deity", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{4}{B/G}"); + this.expansionSetCode = "EVE"; + this.subtype.add("Aura"); + + this.color.setGreen(true); + this.color.setBlack(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is black, it gets +1/+1 and has deathtouch. + SimpleStaticAbility blackAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.BLACK), "As long as enchanted creature is black, it gets +1/+1")); + blackAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(DeathtouchAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.BLACK), "and has deathtouch")); + this.addAbility(blackAbility); + // As long as enchanted creature is green, it gets +1/+1 and all creatures able to block it do so. + SimpleStaticAbility greenAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.GREEN), "As long as enchanted creature is green, it gets +1/+1")); + greenAbility.addEffect(new ConditionalContinousEffect(new MustBlockAttachedEffect(AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.GREEN), "and all creatures able to block it do so")); + this.addAbility(greenAbility); + } + + public GiftOfTheDeity(final GiftOfTheDeity card) { + super(card); + } + + @Override + public GiftOfTheDeity copy() { + return new GiftOfTheDeity(this); + } +} diff --git a/Mage.Sets/src/mage/sets/eventide/NoxiousHatchling.java b/Mage.Sets/src/mage/sets/eventide/NoxiousHatchling.java index 5870e58d1c2..687dc3608f4 100644 --- a/Mage.Sets/src/mage/sets/eventide/NoxiousHatchling.java +++ b/Mage.Sets/src/mage/sets/eventide/NoxiousHatchling.java @@ -28,16 +28,16 @@ package mage.sets.eventide; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SpellCastTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.WitherAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.counters.CounterType; import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ColorPredicate; @@ -64,9 +64,14 @@ public class NoxiousHatchling extends CardImpl { this.color.setBlack(true); this.power = new MageInt(6); this.toughness = new MageInt(6); - this.addAbility(new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(4)), false)); + + // Noxious Hatchling enters the battlefield with four -1/-1 counters on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(4)), true)); + // Wither (This deals damage to creatures in the form of -1/-1 counters.) this.addAbility(WitherAbility.getInstance()); + // Whenever you cast a black spell, remove a -1/-1 counter from Noxious Hatchling. this.addAbility(new SpellCastTriggeredAbility(new RemoveCounterSourceEffect(CounterType.M1M1.createInstance()), filterBlackSpell, false)); + // Whenever you cast a green spell, remove a -1/-1 counter from Noxious Hatchling. this.addAbility(new SpellCastTriggeredAbility(new RemoveCounterSourceEffect(CounterType.M1M1.createInstance()), filterGreenSpell, false)); } diff --git a/Mage.Sets/src/mage/sets/eventide/ScourgeOfTheNobilis.java b/Mage.Sets/src/mage/sets/eventide/ScourgeOfTheNobilis.java new file mode 100644 index 00000000000..ddd524ca43e --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/ScourgeOfTheNobilis.java @@ -0,0 +1,92 @@ +/* + * 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.eventide; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.LifelinkAbility; +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.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class ScourgeOfTheNobilis extends CardImpl { + + public ScourgeOfTheNobilis(UUID ownerId) { + super(ownerId, 146, "Scourge of the Nobilis", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{R/W}"); + this.expansionSetCode = "EVE"; + this.subtype.add("Aura"); + + this.color.setRed(true); + this.color.setWhite(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is red, it gets +1/+1 and has "{RW}: This creature gets +1/+0 until end of turn." + SimpleStaticAbility redAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.RED), "As long as enchanted creature is red, it gets +1/+1")); + redAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R/W}")), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.RED), "and has \"{R/W}: This creature gets +1/+0 until end of turn.\"")); + this.addAbility(redAbility); + // As long as enchanted creature is white, it gets +1/+1 and has lifelink. + SimpleStaticAbility whiteAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.WHITE), "As long as enchanted creature is white, it gets +1/+1")); + whiteAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(LifelinkAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.WHITE), "and has lifelink")); + this.addAbility(whiteAbility); + } + + public ScourgeOfTheNobilis(final ScourgeOfTheNobilis card) { + super(card); + } + + @Override + public ScourgeOfTheNobilis copy() { + return new ScourgeOfTheNobilis(this); + } +} diff --git a/Mage.Sets/src/mage/sets/eventide/SturdyHatchling.java b/Mage.Sets/src/mage/sets/eventide/SturdyHatchling.java index 57f5a515d29..6041e058c7e 100644 --- a/Mage.Sets/src/mage/sets/eventide/SturdyHatchling.java +++ b/Mage.Sets/src/mage/sets/eventide/SturdyHatchling.java @@ -28,12 +28,9 @@ package mage.sets.eventide; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -42,7 +39,9 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.ShroudAbility; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Rarity; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.FilterSpell; @@ -69,9 +68,14 @@ public class SturdyHatchling extends CardImpl { this.color.setGreen(true); this.power = new MageInt(6); this.toughness = new MageInt(6); - this.addAbility(new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(4)), false)); + + // Sturdy Hatchling enters the battlefield with four -1/-1 counters on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(4)))); + // {G/U}: Sturdy Hatchling gains shroud until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(ShroudAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{G/U}"))); + // Whenever you cast a green spell, remove a -1/-1 counter from Sturdy Hatchling. this.addAbility(new SpellCastTriggeredAbility(new RemoveCounterSourceEffect(CounterType.M1M1.createInstance(1)), filterGreenSpell, false)); + // Whenever you cast a blue spell, remove a -1/-1 counter from Sturdy Hatchling. this.addAbility(new SpellCastTriggeredAbility(new RemoveCounterSourceEffect(CounterType.M1M1.createInstance(1)), filterBlueSpell, false)); } diff --git a/Mage.Sets/src/mage/sets/eventide/VoraciousHatchling.java b/Mage.Sets/src/mage/sets/eventide/VoraciousHatchling.java index f5147b5bd61..b31f7d971ea 100644 --- a/Mage.Sets/src/mage/sets/eventide/VoraciousHatchling.java +++ b/Mage.Sets/src/mage/sets/eventide/VoraciousHatchling.java @@ -28,16 +28,16 @@ package mage.sets.eventide; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SpellCastTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.counters.CounterType; import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ColorPredicate; @@ -63,9 +63,14 @@ public class VoraciousHatchling extends CardImpl { this.color.setWhite(true); this.power = new MageInt(6); this.toughness = new MageInt(6); + + // Lifelink this.addAbility(LifelinkAbility.getInstance()); - this.addAbility(new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(4)))); + // Voracious Hatchling enters the battlefield with four -1/-1 counters on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(4)))); + // Whenever you cast a white spell, remove a -1/-1 counter from Voracious Hatchling. this.addAbility(new SpellCastTriggeredAbility(new RemoveCounterSourceEffect(CounterType.M1M1.createInstance(1)), filterWhiteSpell, false)); + // Whenever you cast a black spell, remove a -1/-1 counter from Voracious Hatchling. this.addAbility(new SpellCastTriggeredAbility(new RemoveCounterSourceEffect(CounterType.M1M1.createInstance(1)), filterBlackSpell, false)); } diff --git a/Mage.Sets/src/mage/sets/eventide/WormHarvest.java b/Mage.Sets/src/mage/sets/eventide/WormHarvest.java new file mode 100644 index 00000000000..53fdabcc2c9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eventide/WormHarvest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.eventide; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.RetraceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TimingRule; +import mage.filter.common.FilterLandCard; +import mage.game.permanent.token.Token; + +/** + * + * @author LevelX2 + */ +public class WormHarvest extends CardImpl { + + public WormHarvest(UUID ownerId) { + super(ownerId, 131, "Worm Harvest", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{B/G}{B/G}{B/G}"); + this.expansionSetCode = "EVE"; + + this.color.setGreen(true); + this.color.setBlack(true); + + // Put a 1/1 black and green Worm creature token onto the battlefield for each land card in your graveyard. + CardsInControllerGraveyardCount value = new CardsInControllerGraveyardCount(new FilterLandCard()); + this.getSpellAbility().addEffect(new CreateTokenEffect(new WormHarvestToken(), value)); + + // Retrace + this.addAbility(new RetraceAbility(new ManaCostsImpl("{2}{B/G}{B/G}{B/G}"), TimingRule.SORCERY)); + } + + public WormHarvest(final WormHarvest card) { + super(card); + } + + @Override + public WormHarvest copy() { + return new WormHarvest(this); + } +} + +class WormHarvestToken extends Token { + WormHarvestToken() { + super("Worm", "1/1 black and green Worm creature token"); + cardType.add(CardType.CREATURE); + color.setBlack(true); + color.setGreen(true); + subtype.add("Worm"); + power = new MageInt(1); + toughness = new MageInt(1); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/exodus/ErraticPortal.java b/Mage.Sets/src/mage/sets/exodus/ErraticPortal.java index 145f12b3641..92fae347c3a 100644 --- a/Mage.Sets/src/mage/sets/exodus/ErraticPortal.java +++ b/Mage.Sets/src/mage/sets/exodus/ErraticPortal.java @@ -100,7 +100,11 @@ class ErraticPortalEffect extends OneShotEffect { Player player = game.getPlayer(targetCreature.getControllerId()); if (player != null) { cost.clearPaid(); - if (!cost.pay(source, game, targetCreature.getControllerId(), targetCreature.getControllerId(), false)) { + final StringBuilder sb = new StringBuilder("Pay {1} otherwise ").append(targetCreature.getName()).append(" will be returned to its owner's hand)"); + if (player.chooseUse(Outcome.Benefit, sb.toString(), game)) { + cost.pay(source, game, targetCreature.getControllerId(), targetCreature.getControllerId(), true); + } + if (!cost.isPaid()) { return targetCreature.moveToZone(Zone.HAND, source.getSourceId(), game, true); } } diff --git a/Mage.Sets/src/mage/sets/fallenempires/Seasinger.java b/Mage.Sets/src/mage/sets/fallenempires/Seasinger.java index 71d027b96f9..650f0c59849 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/Seasinger.java +++ b/Mage.Sets/src/mage/sets/fallenempires/Seasinger.java @@ -35,8 +35,8 @@ import mage.abilities.Ability; import mage.abilities.StateTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SkipUntapOptionalAbility; -import mage.abilities.condition.Condition; import mage.abilities.condition.common.ControlsPermanentCondition; +import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.decorator.ConditionalContinousEffect; import mage.abilities.effects.common.SacrificeSourceEffect; @@ -89,7 +89,7 @@ public class Seasinger extends CardImpl { this.addAbility(new SkipUntapOptionalAbility()); // {tap}: Gain control of target creature whose controller controls an Island for as long as you control Seasinger and Seasinger remains tapped. - ConditionalContinousEffect effect = new ConditionalContinousEffect(new GainControlTargetEffect(Duration.Custom), new ControlsPermanentCondition(seasinger, ControlsPermanentCondition.CountType.EQUAL_TO, 1, TappedCondition.getInstance()), rule); + ConditionalContinousEffect effect = new ConditionalContinousEffect(new GainControlTargetEffect(Duration.Custom), new ControlsPermanentCondition(seasinger, ControlsPermanentCondition.CountType.EQUAL_TO, 1, SourceTappedCondition.getInstance()), rule); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); creatureWhoseControllerControlsIsland.add(new ControllerControlsIslandPredicate()); ability.addTarget(new TargetCreaturePermanent(creatureWhoseControllerControlsIsland)); @@ -148,21 +148,3 @@ class SeasingerTriggeredAbility extends StateTriggeredAbility { // Flash this.addAbility(FlashAbility.getInstance()); // Sunburst - this.addAbility(new SunburstAbility()); + this.addAbility(new SunburstAbility(this)); // Remove a charge counter from Baton of Courage: Target creature gets +1/+1 until end of turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(1, 1, Duration.EndOfTurn), new RemoveCountersSourceCost(CounterType.CHARGE.createInstance(1))); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/sets/fifthdawn/ClearwaterGoblet.java b/Mage.Sets/src/mage/sets/fifthdawn/ClearwaterGoblet.java index dad83e18d8e..a5006adeacf 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/ClearwaterGoblet.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/ClearwaterGoblet.java @@ -51,7 +51,7 @@ public class ClearwaterGoblet extends CardImpl { this.expansionSetCode = "5DN"; // Sunburst - this.addAbility(new SunburstAbility()); + this.addAbility(new SunburstAbility(this)); // At the beginning of your upkeep, you may gain life equal to the number of charge counters on Clearwater Goblet. this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new GainLifeEffect(new CountersCount(CounterType.CHARGE)), TargetController.YOU, true)); } diff --git a/Mage.Sets/src/mage/sets/fifthdawn/EngineeredExplosives.java b/Mage.Sets/src/mage/sets/fifthdawn/EngineeredExplosives.java index 31aa69f8d7d..059d1f76c6b 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/EngineeredExplosives.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/EngineeredExplosives.java @@ -58,7 +58,7 @@ public class EngineeredExplosives extends CardImpl { this.expansionSetCode = "5DN"; // Sunburst - this.addAbility(new SunburstAbility()); + this.addAbility(new SunburstAbility(this)); // {2}, Sacrifice Engineered Explosives: Destroy each nonland permanent with converted mana cost equal to the number of charge counters on Engineered Explosives. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new EngineeredExplosivesEffect(), new ManaCostsImpl("{2}")); ability.addCost(new SacrificeSourceCost()); diff --git a/Mage.Sets/src/mage/sets/fifthdawn/RudeAwakening.java b/Mage.Sets/src/mage/sets/fifthdawn/RudeAwakening.java new file mode 100644 index 00000000000..816be8afe56 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthdawn/RudeAwakening.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.fifthdawn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class RudeAwakening extends mage.sets.modernmasters.RudeAwakening { + + public RudeAwakening(UUID ownerId) { + super(ownerId); + this.cardNumber = 92; + this.expansionSetCode = "5DN"; + } + + public RudeAwakening(final RudeAwakening card) { + super(card); + } + + @Override + public RudeAwakening copy() { + return new RudeAwakening(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthdawn/SawtoothThresher.java b/Mage.Sets/src/mage/sets/fifthdawn/SawtoothThresher.java index ef57a368362..811e9a46002 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/SawtoothThresher.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/SawtoothThresher.java @@ -56,7 +56,7 @@ public class SawtoothThresher extends CardImpl { this.toughness = new MageInt(1); // Sunburst - this.addAbility(new SunburstAbility()); + this.addAbility(new SunburstAbility(this)); // Remove two +1/+1 counters from Sawtooth Thresher: Sawtooth Thresher gets +4/+4 until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(4, 4, Duration.EndOfTurn), new RemoveCountersSourceCost(CounterType.P1P1.createInstance(2)))); } diff --git a/Mage.Sets/src/mage/sets/fifthdawn/SkyreachManta.java b/Mage.Sets/src/mage/sets/fifthdawn/SkyreachManta.java index a5ebb277535..f4a36ca5513 100644 --- a/Mage.Sets/src/mage/sets/fifthdawn/SkyreachManta.java +++ b/Mage.Sets/src/mage/sets/fifthdawn/SkyreachManta.java @@ -49,7 +49,7 @@ public class SkyreachManta extends CardImpl { this.toughness = new MageInt(0); // Sunburst - this.addAbility(new SunburstAbility()); + this.addAbility(new SunburstAbility(this)); // Flying this.addAbility(FlyingAbility.getInstance()); } diff --git a/Mage.Sets/src/mage/sets/fifthdawn/VedalkenShackles.java b/Mage.Sets/src/mage/sets/fifthdawn/VedalkenShackles.java new file mode 100644 index 00000000000..b1419e58eff --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthdawn/VedalkenShackles.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.fifthdawn; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class VedalkenShackles extends mage.sets.modernmasters.VedalkenShackles { + + public VedalkenShackles(UUID ownerId) { + super(ownerId); + this.cardNumber = 164; + this.expansionSetCode = "5DN"; + this.rarity = Rarity.RARE; + } + + public VedalkenShackles(final VedalkenShackles card) { + super(card); + } + + @Override + public VedalkenShackles copy() { + return new VedalkenShackles(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/DeathRattle.java b/Mage.Sets/src/mage/sets/futuresight/DeathRattle.java new file mode 100644 index 00000000000..a7bda35110d --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/DeathRattle.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.futuresight; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class DeathRattle extends mage.sets.modernmasters.DeathRattle { + + public DeathRattle(UUID ownerId) { + super(ownerId); + this.cardNumber = 82; + this.expansionSetCode = "FUT"; + this.rarity = Rarity.COMMON; + } + + public DeathRattle(final DeathRattle card) { + super(card); + } + + @Override + public DeathRattle copy() { + return new DeathRattle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/DeepcavernImp.java b/Mage.Sets/src/mage/sets/futuresight/DeepcavernImp.java new file mode 100644 index 00000000000..aca794c8cb2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/DeepcavernImp.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.futuresight; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class DeepcavernImp extends mage.sets.modernmasters.DeepcavernImp { + + public DeepcavernImp(UUID ownerId) { + super(ownerId); + this.cardNumber = 83; + this.expansionSetCode = "FUT"; + } + + public DeepcavernImp(final DeepcavernImp card) { + super(card); + } + + @Override + public DeepcavernImp copy() { + return new DeepcavernImp(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/Epochrasite.java b/Mage.Sets/src/mage/sets/futuresight/Epochrasite.java new file mode 100644 index 00000000000..f2943e24d2e --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/Epochrasite.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.futuresight; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class Epochrasite extends mage.sets.modernmasters.Epochrasite { + + public Epochrasite(UUID ownerId) { + super(ownerId); + this.cardNumber = 162; + this.expansionSetCode = "FUT"; + this.rarity = Rarity.RARE; + } + + public Epochrasite(final Epochrasite card) { + super(card); + } + + @Override + public Epochrasite copy() { + return new Epochrasite(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/GrinningIgnus.java b/Mage.Sets/src/mage/sets/futuresight/GrinningIgnus.java new file mode 100644 index 00000000000..2d8c4e2cadc --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/GrinningIgnus.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.futuresight; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class GrinningIgnus extends mage.sets.modernmasters.GrinningIgnus { + + public GrinningIgnus(UUID ownerId) { + super(ownerId); + this.cardNumber = 116; + this.expansionSetCode = "FUT"; + this.rarity = Rarity.COMMON; + } + + public GrinningIgnus(final GrinningIgnus card) { + super(card); + } + + @Override + public GrinningIgnus copy() { + return new GrinningIgnus(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/Imperiosaur.java b/Mage.Sets/src/mage/sets/futuresight/Imperiosaur.java new file mode 100644 index 00000000000..864ce03ce15 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/Imperiosaur.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.futuresight; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class Imperiosaur extends mage.sets.modernmasters.Imperiosaur { + + public Imperiosaur(UUID ownerId) { + super(ownerId); + this.cardNumber = 145; + this.expansionSetCode = "FUT"; + this.rarity = Rarity.UNCOMMON; + } + + public Imperiosaur(final Imperiosaur card) { + super(card); + } + + @Override + public Imperiosaur copy() { + return new Imperiosaur(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/JhoiraOfTheGhitu.java b/Mage.Sets/src/mage/sets/futuresight/JhoiraOfTheGhitu.java new file mode 100644 index 00000000000..33438ee7e40 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/JhoiraOfTheGhitu.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.futuresight; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class JhoiraOfTheGhitu extends mage.sets.modernmasters.JhoiraOfTheGhitu { + + public JhoiraOfTheGhitu(UUID ownerId) { + super(ownerId); + this.cardNumber = 157; + this.expansionSetCode = "FUT"; + } + + public JhoiraOfTheGhitu(final JhoiraOfTheGhitu card) { + super(card); + } + + @Override + public JhoiraOfTheGhitu copy() { + return new JhoiraOfTheGhitu(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/LogicKnot.java b/Mage.Sets/src/mage/sets/futuresight/LogicKnot.java new file mode 100644 index 00000000000..4b5bb17b2d0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/LogicKnot.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.futuresight; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class LogicKnot extends mage.sets.modernmasters.LogicKnot { + + public LogicKnot(UUID ownerId) { + super(ownerId); + this.cardNumber = 52; + this.expansionSetCode = "FUT"; + } + + public LogicKnot(final LogicKnot card) { + super(card); + } + + @Override + public LogicKnot copy() { + return new LogicKnot(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/MoltenDisaster.java b/Mage.Sets/src/mage/sets/futuresight/MoltenDisaster.java new file mode 100644 index 00000000000..84a0ce4aaa3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/MoltenDisaster.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.futuresight; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class MoltenDisaster extends mage.sets.modernmasters.MoltenDisaster { + + public MoltenDisaster(UUID ownerId) { + super(ownerId); + this.cardNumber = 102; + this.expansionSetCode = "FUT"; + } + + public MoltenDisaster(final MoltenDisaster card) { + super(card); + } + + @Override + public MoltenDisaster copy() { + return new MoltenDisaster(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/PyromancersSwath.java b/Mage.Sets/src/mage/sets/futuresight/PyromancersSwath.java new file mode 100644 index 00000000000..a57caa04aaf --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/PyromancersSwath.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.futuresight; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class PyromancersSwath extends mage.sets.modernmasters.PyromancersSwath { + + public PyromancersSwath(UUID ownerId) { + super(ownerId); + this.cardNumber = 104; + this.expansionSetCode = "FUT"; + } + + public PyromancersSwath(final PyromancersSwath card) { + super(card); + } + + @Override + public PyromancersSwath copy() { + return new PyromancersSwath(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/RiftElemental.java b/Mage.Sets/src/mage/sets/futuresight/RiftElemental.java new file mode 100644 index 00000000000..ba67a6dacf1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/RiftElemental.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.futuresight; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class RiftElemental extends mage.sets.modernmasters.RiftElemental { + + public RiftElemental(UUID ownerId) { + super(ownerId); + this.cardNumber = 106; + this.expansionSetCode = "FUT"; + } + + public RiftElemental(final RiftElemental card) { + super(card); + } + + @Override + public RiftElemental copy() { + return new RiftElemental(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/Riftsweeper.java b/Mage.Sets/src/mage/sets/futuresight/Riftsweeper.java new file mode 100644 index 00000000000..45a5ed4621b --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/Riftsweeper.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.futuresight; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class Riftsweeper extends mage.sets.modernmasters.Riftsweeper { + + public Riftsweeper(UUID ownerId) { + super(ownerId); + this.cardNumber = 136; + this.expansionSetCode = "FUT"; + } + + public Riftsweeper(final Riftsweeper card) { + super(card); + } + + @Override + public Riftsweeper copy() { + return new Riftsweeper(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/TakePossession.java b/Mage.Sets/src/mage/sets/futuresight/TakePossession.java new file mode 100644 index 00000000000..a4d0915f37a --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/TakePossession.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.futuresight; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class TakePossession extends mage.sets.modernmasters.TakePossession { + + public TakePossession(UUID ownerId) { + super(ownerId); + this.cardNumber = 44; + this.expansionSetCode = "FUT"; + this.rarity = Rarity.RARE; + } + + public TakePossession(final TakePossession card) { + super(card); + } + + @Override + public TakePossession copy() { + return new TakePossession(this); + } +} diff --git a/Mage.Sets/src/mage/sets/futuresight/Tombstalker.java b/Mage.Sets/src/mage/sets/futuresight/Tombstalker.java new file mode 100644 index 00000000000..a36f78ec894 --- /dev/null +++ b/Mage.Sets/src/mage/sets/futuresight/Tombstalker.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.futuresight; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class Tombstalker extends mage.sets.modernmasters.Tombstalker { + + public Tombstalker(UUID ownerId) { + super(ownerId); + this.cardNumber = 91; + this.expansionSetCode = "FUT"; + } + + public Tombstalker(final Tombstalker card) { + super(card); + } + + @Override + public Tombstalker copy() { + return new Tombstalker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/gatecrash/ClanDefiance.java b/Mage.Sets/src/mage/sets/gatecrash/ClanDefiance.java index 70cbf444f9f..41739f433ff 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/ClanDefiance.java +++ b/Mage.Sets/src/mage/sets/gatecrash/ClanDefiance.java @@ -64,44 +64,23 @@ public class ClanDefiance extends CardImpl { this.color.setRed(true); this.color.setGreen(true); - // Choose one or more - Clan Defiance deals X damage to target creature with flying; Clan Defiance deals X damage to target creature without flying; and/or Clan Defiance deals X damage to target player. + // Choose one or more - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(3); + // Clan Defiance deals X damage to target creature with flying; this.getSpellAbility().addEffect(new DamageTargetEffect(new ManacostVariableValue())); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); - + // Clan Defiance deals X damage to target creature without flying; Mode mode1 = new Mode(); mode1.getEffects().add(new DamageTargetEffect(new ManacostVariableValue())); mode1.getTargets().add(new TargetCreaturePermanent(filter2)); this.getSpellAbility().addMode(mode1); - + // and/or Clan Defiance deals X damage to target player. Mode mode2 = new Mode(); mode2.getEffects().add(new DamageTargetEffect(new ManacostVariableValue())); mode2.getTargets().add(new TargetPlayer()); this.getSpellAbility().addMode(mode2); - - Mode mode3 = new Mode(); - mode3.getEffects().add(new DamageTargetEffect(new ManacostVariableValue(), true, "target creature with flying, then deals X damage to target creature without flying")); - mode3.getTargets().add(new TargetCreaturePermanent(filter)); - mode3.getTargets().add(new TargetCreaturePermanent(filter2)); - this.getSpellAbility().addMode(mode3); - - Mode mode4 = new Mode(); - mode4.getEffects().add(new DamageTargetEffect(new ManacostVariableValue(), true, "target creature with flying, then deals X damage to target player")); - mode4.getTargets().add(new TargetCreaturePermanent(filter)); - mode4.getTargets().add(new TargetPlayer()); - this.getSpellAbility().addMode(mode4); - - Mode mode5 = new Mode(); - mode5.getEffects().add(new DamageTargetEffect(new ManacostVariableValue(), true, "target creature without flying, then deals X damage to target player")); - mode5.getTargets().add(new TargetCreaturePermanent(filter2)); - mode5.getTargets().add(new TargetPlayer()); - this.getSpellAbility().addMode(mode5); - Mode mode6 = new Mode(); - mode6.getEffects().add(new DamageTargetEffect(new ManacostVariableValue(), true, "target creature with flying, then deals X damage to target creature without flying, then deals X damage to target player")); - mode6.getTargets().add(new TargetCreaturePermanent(filter)); - mode6.getTargets().add(new TargetCreaturePermanent(filter2)); - mode6.getTargets().add(new TargetPlayer()); - this.getSpellAbility().addMode(mode6); } public ClanDefiance(final ClanDefiance card) { diff --git a/Mage.Sets/src/mage/sets/gatecrash/GrislySpectacle.java b/Mage.Sets/src/mage/sets/gatecrash/GrislySpectacle.java index ac86f0194d2..a8efff42caf 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/GrislySpectacle.java +++ b/Mage.Sets/src/mage/sets/gatecrash/GrislySpectacle.java @@ -100,11 +100,11 @@ class GrislySpectacleEffect extends OneShotEffect { Player controller = game.getPlayer(creature.getControllerId()); if (controller != null) { int power = creature.getPower().getValue(); - if (creature.destroy(source.getSourceId(), game, false)) { - Effect effect = new PutLibraryIntoGraveTargetEffect(power); - effect.setTargetPointer(new FixedTarget(controller.getId())); - return effect.apply(game, source); - } + creature.destroy(source.getSourceId(), game, false); + // the mill effect works also if creature is indestructible or regenerated + Effect effect = new PutLibraryIntoGraveTargetEffect(power); + effect.setTargetPointer(new FixedTarget(controller.getId())); + return effect.apply(game, source); } } return false; diff --git a/Mage.Sets/src/mage/sets/gatecrash/PredatorsRapport.java b/Mage.Sets/src/mage/sets/gatecrash/PredatorsRapport.java index 7c00e84e1b3..c75af84fbf2 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/PredatorsRapport.java +++ b/Mage.Sets/src/mage/sets/gatecrash/PredatorsRapport.java @@ -28,13 +28,13 @@ package mage.sets.gatecrash; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; diff --git a/Mage.Sets/src/mage/sets/gatecrash/TruefirePaladin.java b/Mage.Sets/src/mage/sets/gatecrash/TruefirePaladin.java index 2d320a9ea64..ade6131e720 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/TruefirePaladin.java +++ b/Mage.Sets/src/mage/sets/gatecrash/TruefirePaladin.java @@ -68,7 +68,7 @@ public class TruefirePaladin extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(2,0, Duration.EndOfTurn), new ManaCostsImpl("{R}{W}"))); // {R}{W}: Truefire Paladin gets first strike until end of turn. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FirstStrikeAbility.getInstance()), new ManaCostsImpl("{R}{W}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{R}{W}"))); } diff --git a/Mage.Sets/src/mage/sets/iceage/Swamp1.java b/Mage.Sets/src/mage/sets/iceage/Swamp1.java index 0e127133355..4a7bca78159 100644 --- a/Mage.Sets/src/mage/sets/iceage/Swamp1.java +++ b/Mage.Sets/src/mage/sets/iceage/Swamp1.java @@ -36,7 +36,7 @@ import java.util.UUID; public class Swamp1 extends mage.cards.basiclands.Swamp { public Swamp1(UUID ownerId) { - super(ownerId, 351); + super(ownerId, 353); this.expansionSetCode = "ICE"; } diff --git a/Mage.Sets/src/mage/sets/iceage/Swamp2.java b/Mage.Sets/src/mage/sets/iceage/Swamp2.java index 6158384913f..9a0c2663498 100644 --- a/Mage.Sets/src/mage/sets/iceage/Swamp2.java +++ b/Mage.Sets/src/mage/sets/iceage/Swamp2.java @@ -36,7 +36,7 @@ import java.util.UUID; public class Swamp2 extends mage.cards.basiclands.Swamp { public Swamp2(UUID ownerId) { - super(ownerId, 352); + super(ownerId, 354); this.expansionSetCode = "ICE"; } diff --git a/Mage.Sets/src/mage/sets/iceage/Swamp3.java b/Mage.Sets/src/mage/sets/iceage/Swamp3.java index c515e8d56dd..0714bbe7893 100644 --- a/Mage.Sets/src/mage/sets/iceage/Swamp3.java +++ b/Mage.Sets/src/mage/sets/iceage/Swamp3.java @@ -36,7 +36,7 @@ import java.util.UUID; public class Swamp3 extends mage.cards.basiclands.Swamp { public Swamp3(UUID ownerId) { - super(ownerId, 353); + super(ownerId, 355); this.expansionSetCode = "ICE"; } diff --git a/Mage.Sets/src/mage/sets/innistrad/NightTerrors.java b/Mage.Sets/src/mage/sets/innistrad/NightTerrors.java index b5f9d43e239..159725c6e2f 100644 --- a/Mage.Sets/src/mage/sets/innistrad/NightTerrors.java +++ b/Mage.Sets/src/mage/sets/innistrad/NightTerrors.java @@ -28,14 +28,13 @@ package mage.sets.innistrad; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; 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.constants.Zone; import mage.filter.common.FilterNonlandCard; import mage.game.Game; @@ -98,7 +97,7 @@ class NightTerrorsEffect extends OneShotEffect { if (player.choose(Outcome.Exile, targetPlayer.getHand(), target, game)) { Card card = targetPlayer.getHand().get(target.getFirstTarget(), game); if (card != null) { - card.moveToExile(null, "", source.getId(), game); + card.moveToExile(null, "", source.getSourceId(), game); } } diff --git a/Mage.Sets/src/mage/sets/invasion/FertileGround.java b/Mage.Sets/src/mage/sets/invasion/FertileGround.java new file mode 100644 index 00000000000..a92ac371a27 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/FertileGround.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.invasion; + +import java.util.UUID; + +/** + * + * @author Plopman + */ +public class FertileGround extends mage.sets.urzassaga.FertileGround { + + public FertileGround(UUID ownerId) { + super(ownerId); + this.cardNumber = 188; + this.expansionSetCode = "INV"; + } + + public FertileGround(final FertileGround card) { + super(card); + } + + @Override + public FertileGround copy() { + return new FertileGround(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/VerdelothTheAncient.java b/Mage.Sets/src/mage/sets/invasion/VerdelothTheAncient.java new file mode 100644 index 00000000000..097592c3486 --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/VerdelothTheAncient.java @@ -0,0 +1,128 @@ +/* + * 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.invasion; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.MultikickerCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.continious.BoostAllEffect; +import mage.abilities.keyword.KickerAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.game.Game; +import mage.game.permanent.token.SaprolingToken; + +/** + * + * @author LevelX2 + */ +public class VerdelothTheAncient extends CardImpl { + + public VerdelothTheAncient(UUID ownerId) { + super(ownerId, 220, "Verdeloth the Ancient", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); + this.expansionSetCode = "INV"; + this.supertype.add("Legendary"); + this.subtype.add("Treefolk"); + + this.color.setGreen(true); + this.power = new MageInt(4); + this.toughness = new MageInt(7); + + // Kicker {X} + this.addAbility(new KickerAbility("{X}")); + // Saproling creatures and other Treefolk creatures get +1/+1. + FilterCreaturePermanent filter = new FilterCreaturePermanent("Saproling creatures and other Treefolk creatures"); + filter.add(Predicates.or( + Predicates.and(new SubtypePredicate("Treefolk"), Predicates.not(new PermanentIdPredicate(this.getId())), + new SubtypePredicate("Saproling")))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1,1, Duration.WhileOnBattlefield, filter, false))); + // When Verdeloth the Ancient enters the battlefield, if it was kicked, put X 1/1 green Saproling creature tokens onto the battlefield. + EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SaprolingToken(), new GetKickerXValue()), false); + this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.getInstance(), + "When {this} enters the battlefield, if it was kicked, put X 1/1 green Saproling creature tokens onto the battlefield.")); + } + + public VerdelothTheAncient(final VerdelothTheAncient card) { + super(card); + } + + @Override + public VerdelothTheAncient copy() { + return new VerdelothTheAncient(this); + } +} + +class GetKickerXValue implements DynamicValue { + + public GetKickerXValue() { + } + + @Override + public int calculate(Game game, Ability source) { + int count = 0; + Card card = game.getCard(source.getSourceId()); + if (card != null) { + for (Ability ability: card.getAbilities()) { + if (ability instanceof KickerAbility) { + count += ((KickerAbility) ability).getXManaValue(); + } + } + } + return count; + } + + @Override + public GetKickerXValue copy() { + return new GetKickerXValue(); + } + + @Override + public String toString() { + return "X"; + }; + + @Override + public String getMessage() { + return "X"; + }; +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/lorwyn/AustereCommand.java b/Mage.Sets/src/mage/sets/lorwyn/AustereCommand.java new file mode 100644 index 00000000000..2663bcd872d --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/AustereCommand.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class AustereCommand extends mage.sets.commander.AustereCommand { + + public AustereCommand(UUID ownerId) { + super(ownerId); + this.cardNumber = 3; + this.expansionSetCode = "LRW"; + } + + public AustereCommand(final AustereCommand card) { + super(card); + } + + @Override + public AustereCommand copy() { + return new AustereCommand(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/BlindSpotGiant.java b/Mage.Sets/src/mage/sets/lorwyn/BlindSpotGiant.java new file mode 100644 index 00000000000..10ca0055e4d --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/BlindSpotGiant.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class BlindSpotGiant extends mage.sets.modernmasters.BlindSpotGiant { + + public BlindSpotGiant(UUID ownerId) { + super(ownerId); + this.cardNumber = 153; + this.expansionSetCode = "LRW"; + } + + public BlindSpotGiant(final BlindSpotGiant card) { + super(card); + } + + @Override + public BlindSpotGiant copy() { + return new BlindSpotGiant(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/CrushUnderfoot.java b/Mage.Sets/src/mage/sets/lorwyn/CrushUnderfoot.java new file mode 100644 index 00000000000..dffe1e600cd --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/CrushUnderfoot.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.lorwyn; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class CrushUnderfoot extends mage.sets.modernmasters.CrushUnderfoot { + + public CrushUnderfoot(UUID ownerId) { + super(ownerId); + this.cardNumber = 162; + this.expansionSetCode = "LRW"; + this.rarity = Rarity.UNCOMMON; + } + + public CrushUnderfoot(final CrushUnderfoot card) { + super(card); + } + + @Override + public CrushUnderfoot copy() { + return new CrushUnderfoot(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/CrypticCommand.java b/Mage.Sets/src/mage/sets/lorwyn/CrypticCommand.java index eee8f86cacf..abef367a041 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/CrypticCommand.java +++ b/Mage.Sets/src/mage/sets/lorwyn/CrypticCommand.java @@ -45,7 +45,6 @@ import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.TargetPlayer; import mage.target.TargetSpell; import mage.target.common.TargetCreaturePermanent; @@ -61,41 +60,25 @@ public class CrypticCommand extends CardImpl { this.color.setBlue(true); - // Choose two - Counter target spell; or return target permanent to its owner's hand; or tap all creatures your opponents control; or draw a card. - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + // Choose two - + this.getSpellAbility().getModes().setMinModes(2); + this.getSpellAbility().getModes().setMaxModes(2); + // Counter target spell; + this.getSpellAbility().addEffect(new CounterTargetEffect()); this.getSpellAbility().addTarget(new TargetSpell()); - this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); - this.getSpellAbility().addEffect(new CounterSecondTargetEffect()); - - Mode mode1 = new Mode(); - mode1.getTargets().add(new TargetSpell()); - mode1.getEffects().add(new CounterTargetEffect()); - mode1.getEffects().add(new CrypticCommandEffect()); - this.getSpellAbility().addMode(mode1); - - Mode mode2 = new Mode(); - mode2.getTargets().add(new TargetSpell()); - mode2.getEffects().add(new CounterTargetEffect()); - mode2.getEffects().add(new DrawCardControllerEffect(1)); - this.getSpellAbility().addMode(mode2); - - Mode mode3 = new Mode(); - mode3.getTargets().add(new TargetCreaturePermanent()); - mode3.getEffects().add(new ReturnToHandTargetEffect()); - mode3.getEffects().add(new CrypticCommandEffect()); - this.getSpellAbility().addMode(mode3); - - Mode mode4 = new Mode(); - mode4.getTargets().add(new TargetCreaturePermanent()); - mode4.getEffects().add(new ReturnToHandTargetEffect()); - mode4.getEffects().add(new DrawCardControllerEffect(1)); - this.getSpellAbility().addMode(mode4); - - Mode mode5 = new Mode(); - mode5.getTargets().add(new TargetPlayer()); - mode5.getEffects().add(new CrypticCommandEffect()); - mode5.getEffects().add(new DrawCardControllerEffect(1)); - this.getSpellAbility().addMode(mode5); + // or return target permanent to its owner's hand; + Mode mode = new Mode(); + mode.getEffects().add(new ReturnToHandTargetEffect()); + mode.getTargets().add(new TargetCreaturePermanent()); + this.getSpellAbility().getModes().addMode(mode); + // or tap all creatures your opponents control; + mode = new Mode(); + mode.getEffects().add(new CrypticCommandEffect()); + this.getSpellAbility().getModes().addMode(mode); + // or draw a card. + mode = new Mode(); + mode.getEffects().add(new DrawCardControllerEffect(1)); + this.getSpellAbility().getModes().addMode(mode); } public CrypticCommand(final CrypticCommand card) { diff --git a/Mage.Sets/src/mage/sets/lorwyn/DreamspoilerWitches.java b/Mage.Sets/src/mage/sets/lorwyn/DreamspoilerWitches.java new file mode 100644 index 00000000000..3911aff08d5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/DreamspoilerWitches.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class DreamspoilerWitches extends mage.sets.modernmasters.DreamspoilerWitches { + + public DreamspoilerWitches(UUID ownerId) { + super(ownerId); + this.cardNumber = 108; + this.expansionSetCode = "LRW"; + } + + public DreamspoilerWitches(final DreamspoilerWitches card) { + super(card); + } + + @Override + public DreamspoilerWitches copy() { + return new DreamspoilerWitches(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/FertileGround.java b/Mage.Sets/src/mage/sets/lorwyn/FertileGround.java new file mode 100644 index 00000000000..9702a94bae7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/FertileGround.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author Plopman + */ +public class FertileGround extends mage.sets.urzassaga.FertileGround { + + public FertileGround(UUID ownerId) { + super(ownerId); + this.cardNumber = 211; + this.expansionSetCode = "LRW"; + } + + public FertileGround(final FertileGround card) { + super(card); + } + + @Override + public FertileGround copy() { + return new FertileGround(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/KithkinGreatheart.java b/Mage.Sets/src/mage/sets/lorwyn/KithkinGreatheart.java new file mode 100644 index 00000000000..1b038c613ca --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/KithkinGreatheart.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class KithkinGreatheart extends mage.sets.modernmasters.KithkinGreatheart { + + public KithkinGreatheart(UUID ownerId) { + super(ownerId); + this.cardNumber = 25; + this.expansionSetCode = "LRW"; + } + + public KithkinGreatheart(final KithkinGreatheart card) { + super(card); + } + + @Override + public KithkinGreatheart copy() { + return new KithkinGreatheart(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/MaskedAdmirers.java b/Mage.Sets/src/mage/sets/lorwyn/MaskedAdmirers.java new file mode 100644 index 00000000000..25ff88f6e9b --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/MaskedAdmirers.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.lorwyn; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class MaskedAdmirers extends mage.sets.modernmasters.MaskedAdmirers { + + public MaskedAdmirers(UUID ownerId) { + super(ownerId); + this.cardNumber = 230; + this.expansionSetCode = "LRW"; + this.rarity = Rarity.RARE; + } + + public MaskedAdmirers(final MaskedAdmirers card) { + super(card); + } + + @Override + public MaskedAdmirers copy() { + return new MaskedAdmirers(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/PrimalCommand.java b/Mage.Sets/src/mage/sets/lorwyn/PrimalCommand.java new file mode 100644 index 00000000000..9fda7dde884 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/PrimalCommand.java @@ -0,0 +1,131 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.lorwyn; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeTargetEffect; +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.TargetPlayer; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author LevelX2 + */ +public class PrimalCommand extends CardImpl { + + private static final FilterPermanent filterNonCreature = new FilterPermanent("noncreature permanent"); + static { + filterNonCreature.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } + + public PrimalCommand(UUID ownerId) { + super(ownerId, 233, "Primal Command", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); + this.expansionSetCode = "LRW"; + + this.color.setGreen(true); + + // Choose two - + this.getSpellAbility().getModes().setMinModes(2); + this.getSpellAbility().getModes().setMaxModes(2); + // Target player gains 7 life; + this.getSpellAbility().addEffect(new GainLifeTargetEffect(7)); + this.getSpellAbility().addTarget(new TargetPlayer(true)); + // or put target noncreature permanent on top of its owner's library; + Mode mode = new Mode(); + mode.getEffects().add(new PutOnLibraryTargetEffect(true)); + Target target = new TargetPermanent(filterNonCreature); + target.setRequired(true); + mode.getTargets().add(target); + this.getSpellAbility().getModes().addMode(mode); + // or target player shuffles his or her graveyard into his or her library; + mode = new Mode(); + mode.getEffects().add(new PrimalCommandShuffleGraveyardEffect()); + mode.getTargets().add(new TargetPlayer()); + this.getSpellAbility().getModes().addMode(mode); + // or search your library for a creature card, reveal it, put it into your hand, then shuffle your library. + mode = new Mode(); + mode.getEffects().add(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(new FilterCreatureCard()), true, true)); + this.getSpellAbility().getModes().addMode(mode); + + } + + public PrimalCommand(final PrimalCommand card) { + super(card); + } + + @Override + public PrimalCommand copy() { + return new PrimalCommand(this); + } +} + +class PrimalCommandShuffleGraveyardEffect extends OneShotEffect { + + public PrimalCommandShuffleGraveyardEffect() { + super(Outcome.Neutral); + this.staticText = "target player shuffles his or her graveyard into his or her library"; + } + + public PrimalCommandShuffleGraveyardEffect(final PrimalCommandShuffleGraveyardEffect effect) { + super(effect); + } + + @Override + public PrimalCommandShuffleGraveyardEffect copy() { + return new PrimalCommandShuffleGraveyardEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getFirstTarget()); + if (player != null) { + player.getLibrary().addAll(player.getGraveyard().getCards(game), game); + player.getGraveyard().clear(); + player.getLibrary().shuffle(); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/RunedStalactite.java b/Mage.Sets/src/mage/sets/lorwyn/RunedStalactite.java new file mode 100644 index 00000000000..9a3757e93db --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/RunedStalactite.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class RunedStalactite extends mage.sets.modernmasters.RunedStalactite { + + public RunedStalactite(UUID ownerId) { + super(ownerId); + this.cardNumber = 260; + this.expansionSetCode = "LRW"; + } + + public RunedStalactite(final RunedStalactite card) { + super(card); + } + + @Override + public RunedStalactite copy() { + return new RunedStalactite(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/ThievingSprite.java b/Mage.Sets/src/mage/sets/lorwyn/ThievingSprite.java new file mode 100644 index 00000000000..73323cfa515 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/ThievingSprite.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ThievingSprite extends mage.sets.modernmasters.ThievingSprite { + + public ThievingSprite(UUID ownerId) { + super(ownerId); + this.cardNumber = 143; + this.expansionSetCode = "LRW"; + } + + public ThievingSprite(final ThievingSprite card) { + super(card); + } + + @Override + public ThievingSprite copy() { + return new ThievingSprite(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/ThundercloudShaman.java b/Mage.Sets/src/mage/sets/lorwyn/ThundercloudShaman.java new file mode 100644 index 00000000000..b6617e88a6e --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/ThundercloudShaman.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ThundercloudShaman extends mage.sets.modernmasters.ThundercloudShaman { + + public ThundercloudShaman(UUID ownerId) { + super(ownerId); + this.cardNumber = 195; + this.expansionSetCode = "LRW"; + } + + public ThundercloudShaman(final ThundercloudShaman card) { + super(card); + } + + @Override + public ThundercloudShaman copy() { + return new ThundercloudShaman(this); + } +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/WarrenPilferers.java b/Mage.Sets/src/mage/sets/lorwyn/WarrenPilferers.java new file mode 100644 index 00000000000..a3c79d6c8e8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/WarrenPilferers.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class WarrenPilferers extends mage.sets.modernmasters.WarrenPilferers { + + public WarrenPilferers(UUID ownerId) { + super(ownerId); + this.cardNumber = 146; + this.expansionSetCode = "LRW"; + } + + public WarrenPilferers(final WarrenPilferers card) { + super(card); + } + + @Override + public WarrenPilferers copy() { + return new WarrenPilferers(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magic2014/AjanisChosen.java b/Mage.Sets/src/mage/sets/magic2014/AjanisChosen.java new file mode 100644 index 00000000000..f5093f9ff3a --- /dev/null +++ b/Mage.Sets/src/mage/sets/magic2014/AjanisChosen.java @@ -0,0 +1,135 @@ +/* + * 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.magic2014; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.Token; +import mage.players.Player; + +/** + * + * @author Plopman + */ +public class AjanisChosen extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(); + static { + filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); + } + + public AjanisChosen(UUID ownerId) { + super(ownerId, 2, "Ajani's Chosen", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); + this.expansionSetCode = "M14"; + this.subtype.add("Cat"); + this.subtype.add("Soldier"); + + this.color.setWhite(true); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever an enchantment enters the battlefield under your control, put a 2/2 white Cat creature token onto the battlefield. If that enchantment is an Aura, you may attach it to the token. + this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new AjanisChosenEffect(), filter, false, true, "Whenever an enchantment enters the battlefield under your control, put a 2/2 white Cat creature token onto the battlefield. If that enchantment is an Aura, you may attach it to the token")); + } + + public AjanisChosen(final AjanisChosen card) { + super(card); + } + + @Override + public AjanisChosen copy() { + return new AjanisChosen(this); + } +} + +class AjanisChosenEffect extends OneShotEffect { + + + public AjanisChosenEffect() { + super(Outcome.PutCreatureInPlay); + staticText = "put a 2/2 white Cat creature token onto the battlefield. If that enchantment is an Aura, you may attach it to the token"; + } + + public AjanisChosenEffect(final AjanisChosenEffect effect) { + super(effect); + } + + @Override + public AjanisChosenEffect copy() { + return new AjanisChosenEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Token token = new CatToken(); + if(token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId())){ + Player player = game.getPlayer(source.getControllerId()); + Permanent enchantement = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + Permanent tokenPermanent = game.getPermanent(token.getLastAddedToken()); + if(player != null && enchantement != null && tokenPermanent != null && enchantement.getSubtype().contains("Aura")) + { + Permanent oldCreature = game.getPermanent(enchantement.getAttachedTo()); + + if(oldCreature != null && enchantement.getSpellAbility().getTargets().get(0).canTarget(tokenPermanent.getId(), game) && player.chooseUse(Outcome.Neutral, "Attach " + enchantement.getName() + " to the token ?", game)) + { + if(oldCreature.removeAttachment(enchantement.getId(), game)){ + tokenPermanent.addAttachment(enchantement.getId(), game); + } + } + } + return true; + } + return false; + } + +} + + +class CatToken extends Token { + public CatToken() { + super("Cat", "2/2 white Cat creature token"); + cardType.add(CardType.CREATURE); + color = ObjectColor.WHITE; + subtype.add("Cat"); + power = new MageInt(2); + toughness = new MageInt(2); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/magic2014/ArchangelOfThune.java b/Mage.Sets/src/mage/sets/magic2014/ArchangelOfThune.java new file mode 100644 index 00000000000..09ccc8cd1b2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magic2014/ArchangelOfThune.java @@ -0,0 +1,107 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.magic2014; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author Plopman + */ +public class ArchangelOfThune extends CardImpl { + + public ArchangelOfThune(UUID ownerId) { + super(ownerId, 5, "Archangel of Thune", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + this.expansionSetCode = "M14"; + this.subtype.add("Angel"); + + this.color.setWhite(true); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + // Whenever you gain life, put a +1/+1 counter on each creature you control. + this.addAbility(new ArchangelOfThuneAbility()); + + } + + public ArchangelOfThune(final ArchangelOfThune card) { + super(card); + } + + @Override + public ArchangelOfThune copy() { + return new ArchangelOfThune(this); + } +} + +class ArchangelOfThuneAbility extends TriggeredAbilityImpl { + + public ArchangelOfThuneAbility() { + super(Zone.BATTLEFIELD, new AddCountersAllEffect(CounterType.P1P1.createInstance(), new FilterControlledCreaturePermanent()), false); + } + + public ArchangelOfThuneAbility(final ArchangelOfThuneAbility ability) { + super(ability); + } + + @Override + public ArchangelOfThuneAbility copy() { + return new ArchangelOfThuneAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.GAINED_LIFE && event.getPlayerId().equals(controllerId)) { + return true; + } + return false; + } + + @Override + public String getRule() { + return " Whenever you gain life, put a +1/+1 counter on each creature you control."; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/magic2014/SentinelSliver.java b/Mage.Sets/src/mage/sets/magic2014/SentinelSliver.java new file mode 100644 index 00000000000..1fb3292340a --- /dev/null +++ b/Mage.Sets/src/mage/sets/magic2014/SentinelSliver.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.magic2014; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continious.GainAbilityControlledEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; + +/** + * + * @author Plopman + */ +public class SentinelSliver extends CardImpl { + + public SentinelSliver(UUID ownerId) { + super(ownerId, 30, "Sentinel Sliver", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "M14"; + this.subtype.add("Sliver"); + + this.color.setWhite(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Sliver creatures you control have vigilance. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, new FilterControlledCreaturePermanent("Sliver", "Sliver creatures you control ")))); + } + + public SentinelSliver(final SentinelSliver card) { + super(card); + } + + @Override + public SentinelSliver copy() { + return new SentinelSliver(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magic2014/SeraphOfTheSword.java b/Mage.Sets/src/mage/sets/magic2014/SeraphOfTheSword.java new file mode 100644 index 00000000000..9aec676afbc --- /dev/null +++ b/Mage.Sets/src/mage/sets/magic2014/SeraphOfTheSword.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.magic2014; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.PreventAllDamageSourceEffect; +import mage.abilities.effects.common.PreventCombatDamageSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author Plopman + */ +public class SeraphOfTheSword extends CardImpl { + + public SeraphOfTheSword(UUID ownerId) { + super(ownerId, 31, "Seraph of the Sword", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}"); + this.expansionSetCode = "M14"; + this.subtype.add("Angel"); + + this.color.setWhite(true); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Prevent all combat damage that would be dealt to Seraph of the Sword. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PreventCombatDamageSourceEffect(Duration.WhileOnBattlefield))); + } + + public SeraphOfTheSword(final SeraphOfTheSword card) { + super(card); + } + + @Override + public SeraphOfTheSword copy() { + return new SeraphOfTheSword(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magic2014/SteelformSliver.java b/Mage.Sets/src/mage/sets/magic2014/SteelformSliver.java new file mode 100644 index 00000000000..36186afb6cb --- /dev/null +++ b/Mage.Sets/src/mage/sets/magic2014/SteelformSliver.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.magic2014; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continious.BoostAllEffect; +import mage.abilities.effects.common.continious.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; + +/** + * + * @author Plopman + */ +public class SteelformSliver extends CardImpl { + + public SteelformSliver(UUID ownerId) { + super(ownerId, 38, "Steelform Sliver", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "M14"; + this.subtype.add("Sliver"); + + this.color.setWhite(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Sliver creatures you control get +0/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(0, 1, Duration.WhileOnBattlefield, new FilterCreaturePermanent("Sliver", "Sliver creatures you control"), false))); + } + + public SteelformSliver(final SteelformSliver card) { + super(card); + } + + @Override + public SteelformSliver copy() { + return new SteelformSliver(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/SqueeGoblinNabob.java b/Mage.Sets/src/mage/sets/mercadianmasques/SqueeGoblinNabob.java new file mode 100644 index 00000000000..4a0cf763dbc --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/SqueeGoblinNabob.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.mercadianmasques; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class SqueeGoblinNabob extends mage.sets.tenth.SqueeGoblinNabob { + + public SqueeGoblinNabob(UUID ownerId) { + super(ownerId); + this.cardNumber = 214; + this.expansionSetCode = "MMQ"; + } + + public SqueeGoblinNabob(final SqueeGoblinNabob card) { + super(card); + } + + @Override + public SqueeGoblinNabob copy() { + return new SqueeGoblinNabob(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirage/EarlyHarvest.java b/Mage.Sets/src/mage/sets/mirage/EarlyHarvest.java new file mode 100644 index 00000000000..5192a939d0e --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirage/EarlyHarvest.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.mirage; + +import java.util.UUID; + +/** + * + * @author Plopman + */ +public class EarlyHarvest extends mage.sets.ninthedition.EarlyHarvest { + + public EarlyHarvest(UUID ownerId) { + super(ownerId); + this.cardNumber = 111; + this.expansionSetCode = "MIR"; + } + + public EarlyHarvest(final EarlyHarvest card) { + super(card); + } + + @Override + public EarlyHarvest copy() { + return new EarlyHarvest(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodin/BlindingBeam.java b/Mage.Sets/src/mage/sets/mirrodin/BlindingBeam.java new file mode 100644 index 00000000000..b762ddbc0c6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirrodin/BlindingBeam.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.mirrodin; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class BlindingBeam extends mage.sets.elspethvstezzeret.BlindingBeam { + + public BlindingBeam(UUID ownerId) { + super(ownerId); + this.cardNumber = 7; + this.expansionSetCode = "MRD"; + } + + public BlindingBeam(final BlindingBeam card) { + super(card); + } + + @Override + public BlindingBeam copy() { + return new BlindingBeam(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodin/ToothAndNail.java b/Mage.Sets/src/mage/sets/mirrodin/ToothAndNail.java new file mode 100644 index 00000000000..a50188250a1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mirrodin/ToothAndNail.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.mirrodin; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ToothAndNail extends mage.sets.modernmasters.ToothAndNail { + + public ToothAndNail(UUID ownerId) { + super(ownerId); + this.cardNumber = 134; + this.expansionSetCode = "MRD"; + } + + public ToothAndNail(final ToothAndNail card) { + super(card); + } + + @Override + public ToothAndNail copy() { + return new ToothAndNail(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/HellkiteIgniter.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/HellkiteIgniter.java index e545d5724bd..2ff26c50a2f 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/HellkiteIgniter.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/HellkiteIgniter.java @@ -29,9 +29,6 @@ package mage.sets.mirrodinbesieged; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -41,9 +38,13 @@ import mage.abilities.effects.common.continious.BoostSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.permanent.ControllerPredicate; /** * @@ -51,6 +52,11 @@ import mage.filter.common.FilterArtifactPermanent; */ public class HellkiteIgniter extends CardImpl { + private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("artifact you control"); + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + public HellkiteIgniter (UUID ownerId) { super(ownerId, 65, "Hellkite Igniter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); this.expansionSetCode = "MBS"; @@ -58,11 +64,14 @@ public class HellkiteIgniter extends CardImpl { this.color.setRed(true); this.power = new MageInt(5); this.toughness = new MageInt(5); + + // Flying, haste this.addAbility(FlyingAbility.getInstance()); this.addAbility(HasteAbility.getInstance()); + // {1}{R}: Hellkite Igniter gets +X/+0 until end of turn, where X is the number of artifacts you control. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect( - new PermanentsOnBattlefieldCount(new FilterArtifactPermanent()), + new PermanentsOnBattlefieldCount(filter), new StaticValue(0), Duration.EndOfTurn), new ManaCostsImpl("{1}{R}"))); diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/MirranSpy.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/MirranSpy.java index d998f8a1912..57d3e28dd7a 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/MirranSpy.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/MirranSpy.java @@ -28,12 +28,13 @@ package mage.sets.mirrodinbesieged; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.SpellCastTriggeredAbility; import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.filter.FilterSpell; import mage.target.common.TargetCreaturePermanent; @@ -53,6 +54,11 @@ public class MirranSpy extends CardImpl { this.color.setBlue(true); this.power = new MageInt(1); this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever you cast an artifact spell, you may untap target creature. SpellCastTriggeredAbility ability = new SpellCastTriggeredAbility(new UntapTargetEffect(), filter, true); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/modernmasters/AngelsGrace.java b/Mage.Sets/src/mage/sets/modernmasters/AngelsGrace.java new file mode 100644 index 00000000000..a9a4a58adea --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/AngelsGrace.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class AngelsGrace extends mage.sets.timespiral.AngelsGrace { + + public AngelsGrace(UUID ownerId) { + super(ownerId); + this.cardNumber = 4; + this.expansionSetCode = "MMA"; + } + + public AngelsGrace(final AngelsGrace card) { + super(card); + } + + @Override + public AngelsGrace copy() { + return new AngelsGrace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/ArcboundWanderer.java b/Mage.Sets/src/mage/sets/modernmasters/ArcboundWanderer.java new file mode 100644 index 00000000000..f4dd03beadf --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/ArcboundWanderer.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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.ModularAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class ArcboundWanderer extends CardImpl { + + public ArcboundWanderer(UUID ownerId) { + super(ownerId, 200, "Arcbound Wanderer", Rarity.COMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{6}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Golem"); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Modular-Sunburst + this.addAbility(new ModularAbility(this,0,true)); + + } + + public ArcboundWanderer(final ArcboundWanderer card) { + super(card); + } + + @Override + public ArcboundWanderer copy() { + return new ArcboundWanderer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/AuntiesSnitch.java b/Mage.Sets/src/mage/sets/modernmasters/AuntiesSnitch.java new file mode 100644 index 00000000000..d4c31390768 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/AuntiesSnitch.java @@ -0,0 +1,121 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.CantBlockAbility; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.abilities.keyword.ProwlAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class AuntiesSnitch extends CardImpl { + + public AuntiesSnitch(UUID ownerId) { + super(ownerId, 72, "Auntie's Snitch", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Goblin"); + this.subtype.add("Rogue"); + + this.color.setBlack(true); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Auntie's Snitch can't block. + this.addAbility(new CantBlockAbility()); + // Prowl {1}{B} + this.addAbility(new ProwlAbility(this, "{1}{B}")); + // Whenever a Goblin or Rogue you control deals combat damage to a player, if Auntie's Snitch is in your graveyard, you may return Auntie's Snitch to your hand. + this.addAbility(new AuntiesSnitchTriggeredAbility()); + } + + public AuntiesSnitch(final AuntiesSnitch card) { + super(card); + } + + @Override + public AuntiesSnitch copy() { + return new AuntiesSnitch(this); + } +} + +class AuntiesSnitchTriggeredAbility extends TriggeredAbilityImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Goblin or Rogue you control"); + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(Predicates.or(new SubtypePredicate("Goblin"), new SubtypePredicate("Rogue"))); + } + + public AuntiesSnitchTriggeredAbility() { + super(Zone.GRAVEYARD, new ReturnToHandSourceEffect(), true); + } + + public AuntiesSnitchTriggeredAbility(final AuntiesSnitchTriggeredAbility ability) { + super(ability); + } + + @Override + public AuntiesSnitchTriggeredAbility copy() { + return new AuntiesSnitchTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event instanceof DamagedPlayerEvent) { + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; + Permanent p = game.getPermanent(event.getSourceId()); + if (damageEvent.isCombatDamage() && p != null && filter.match(p, getSourceId(), getControllerId(), game)) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever a Goblin or Rogue you control deals combat damage to a player, if {this} is in your graveyard, you may return {this} to your hand."; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/BlindSpotGiant.java b/Mage.Sets/src/mage/sets/modernmasters/BlindSpotGiant.java new file mode 100644 index 00000000000..85656c2caae --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/BlindSpotGiant.java @@ -0,0 +1,119 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.RestrictionEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class BlindSpotGiant extends CardImpl { + + public BlindSpotGiant(UUID ownerId) { + super(ownerId, 105, "Blind-Spot Giant", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Giant"); + this.subtype.add("Warrior"); + + this.color.setRed(true); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Blind-Spot Giant can't attack or block unless you control another Giant. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BlindSpotGiantEffect())); + + } + + public BlindSpotGiant(final BlindSpotGiant card) { + super(card); + } + + @Override + public BlindSpotGiant copy() { + return new BlindSpotGiant(this); + } +} + +class BlindSpotGiantEffect extends RestrictionEffect { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Giant"); + static { + filter.add(new SubtypePredicate("Giant")); + filter.add(new AnotherPredicate()); + } + + public BlindSpotGiantEffect() { + super(Duration.WhileOnBattlefield); + staticText = "{this} can't attack or block unless you control another Giant"; + } + + public BlindSpotGiantEffect(final BlindSpotGiantEffect effect) { + super(effect); + } + + @Override + public BlindSpotGiantEffect copy() { + return new BlindSpotGiantEffect(this); + } + + @Override + public boolean canAttack(Game game) { + return false; + } + + @Override + public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) { + return false; + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + if (permanent.getId().equals(source.getSourceId())) { + if (game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) > 0) { + return false; + } + return true; + } // do not apply to other creatures. + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/BlindingBeam.java b/Mage.Sets/src/mage/sets/modernmasters/BlindingBeam.java new file mode 100644 index 00000000000..f6b2666b46f --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/BlindingBeam.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class BlindingBeam extends mage.sets.elspethvstezzeret.BlindingBeam { + + public BlindingBeam(UUID ownerId) { + super(ownerId); + this.cardNumber = 7; + this.expansionSetCode = "MMA"; + } + + public BlindingBeam(final BlindingBeam card) { + super(card); + } + + @Override + public BlindingBeam copy() { + return new BlindingBeam(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/CarefulConsideration.java b/Mage.Sets/src/mage/sets/modernmasters/CarefulConsideration.java new file mode 100644 index 00000000000..d3b7e7fb8d8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/CarefulConsideration.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class CarefulConsideration extends mage.sets.timespiral.CarefulConsideration { + + public CarefulConsideration(UUID ownerId) { + super(ownerId); + this.cardNumber = 37; + this.expansionSetCode = "MMA"; + } + + public CarefulConsideration(final CarefulConsideration card) { + super(card); + } + + @Override + public CarefulConsideration copy() { + return new CarefulConsideration(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/ColdEyedSelkie.java b/Mage.Sets/src/mage/sets/modernmasters/ColdEyedSelkie.java new file mode 100644 index 00000000000..6142ffb9c32 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/ColdEyedSelkie.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class ColdEyedSelkie extends mage.sets.eventide.ColdEyedSelkie { + + public ColdEyedSelkie(UUID ownerId) { + super(ownerId); + this.cardNumber = 186; + this.expansionSetCode = "MMA"; + } + + public ColdEyedSelkie(final ColdEyedSelkie card) { + super(card); + } + + @Override + public ColdEyedSelkie copy() { + return new ColdEyedSelkie(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/CrushUnderfoot.java b/Mage.Sets/src/mage/sets/modernmasters/CrushUnderfoot.java new file mode 100644 index 00000000000..314f5b404b9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/CrushUnderfoot.java @@ -0,0 +1,119 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class CrushUnderfoot extends CardImpl { + + public CrushUnderfoot(UUID ownerId) { + super(ownerId, 109, "Crush Underfoot", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{R}"); + this.expansionSetCode = "MMA"; + this.supertype.add("Tribal"); + this.subtype.add("Giant"); + + this.color.setRed(true); + + // Choose a Giant creature you control. It deals damage equal to its power to target creature. + this.getSpellAbility().addEffect(new CrushUnderfootEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature damage is dealt to"))); + + } + + public CrushUnderfoot(final CrushUnderfoot card) { + super(card); + } + + @Override + public CrushUnderfoot copy() { + return new CrushUnderfoot(this); + } +} + +class CrushUnderfootEffect extends OneShotEffect { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Giant you control"); + static { + filter.add(new SubtypePredicate("Giant")); + } + + public CrushUnderfootEffect() { + super(Outcome.Damage); + this.staticText = "Choose a Giant creature you control. It deals damage equal to its power to target creature"; + } + + public CrushUnderfootEffect(final CrushUnderfootEffect effect) { + super(effect); + } + + @Override + public CrushUnderfootEffect copy() { + return new CrushUnderfootEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + // Choose a Giant creature you control (not targeted, happens during effect resolving ) + Target target = new TargetControlledCreaturePermanent(1,1, filter,false); + if (target.canChoose(source.getSourceId(), controller.getId(), game) + && controller.chooseTarget(outcome, target, source, game)) { + Permanent giant = game.getPermanent(target.getFirstTarget()); + if (giant != null) { + game.informPlayers(new StringBuilder("Crush Underfoot: Choosen Giant is").append(giant.getName()).toString()); + Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (targetCreature != null) { + targetCreature.damage(giant.getPower().getValue(), source.getSourceId(), game, true, false); + return true; + } + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/DampenThought.java b/Mage.Sets/src/mage/sets/modernmasters/DampenThought.java new file mode 100644 index 00000000000..1d2afa8062b --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/DampenThought.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.modernmasters; + +import java.util.UUID; +import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect; +import mage.abilities.keyword.SpliceOntoArcaneAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.TargetPlayer; + +/** + * + * @author LevelX2 + */ +public class DampenThought extends CardImpl { + + public DampenThought(UUID ownerId) { + super(ownerId, 39, "Dampen Thought", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Arcane"); + + this.color.setBlue(true); + + // Target player puts the top four cards of his or her library into his or her graveyard. + this.getSpellAbility().addEffect(new PutLibraryIntoGraveTargetEffect(4)); + this.getSpellAbility().addTarget(new TargetPlayer(true)); + // Splice onto Arcane {1}{U} + this.addAbility(new SpliceOntoArcaneAbility("{1}{U}")); + } + + public DampenThought(final DampenThought card) { + super(card); + } + + @Override + public DampenThought copy() { + return new DampenThought(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/DeathRattle.java b/Mage.Sets/src/mage/sets/modernmasters/DeathRattle.java new file mode 100644 index 00000000000..4d78df7ea27 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/DeathRattle.java @@ -0,0 +1,76 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.DelveAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class DeathRattle extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + static { + filter.add(Predicates.not(new ColorPredicate(ObjectColor.GREEN))); + } + + public DeathRattle(UUID ownerId) { + super(ownerId, 78, "Death Rattle", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{5}{B}"); + this.expansionSetCode = "MMA"; + + this.color.setBlack(true); + + // Delve + this.addAbility(new DelveAbility()); + + // Destroy target nongreen creature. It can't be regenerated. + this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(true)); + + } + + public DeathRattle(final DeathRattle card) { + super(card); + } + + @Override + public DeathRattle copy() { + return new DeathRattle(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/DeepcavernImp.java b/Mage.Sets/src/mage/sets/modernmasters/DeepcavernImp.java new file mode 100644 index 00000000000..0fb1dd54ce7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/DeepcavernImp.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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.costs.common.DiscardCardCost; +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 LevelX2 + */ +public class DeepcavernImp extends CardImpl { + + public DeepcavernImp(UUID ownerId) { + super(ownerId, 79, "Deepcavern Imp", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Imp"); + this.subtype.add("Rebel"); + + this.color.setBlack(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Haste + this.addAbility(HasteAbility.getInstance()); + // Echo-Discard a card. + this.addAbility(new EchoAbility(new DiscardCardCost())); + } + + public DeepcavernImp(final DeepcavernImp card) { + super(card); + } + + @Override + public DeepcavernImp copy() { + return new DeepcavernImp(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/DemigodOfRevenge.java b/Mage.Sets/src/mage/sets/modernmasters/DemigodOfRevenge.java new file mode 100644 index 00000000000..d80cbcd0f73 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/DemigodOfRevenge.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class DemigodOfRevenge extends mage.sets.shadowmoor.DemigodOfRevenge { + + public DemigodOfRevenge(UUID ownerId) { + super(ownerId); + this.cardNumber = 187; + this.expansionSetCode = "MMA"; + } + + public DemigodOfRevenge(final DemigodOfRevenge card) { + super(card); + } + + @Override + public DemigodOfRevenge copy() { + return new DemigodOfRevenge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/DesperateRitual.java b/Mage.Sets/src/mage/sets/modernmasters/DesperateRitual.java new file mode 100644 index 00000000000..aa8e6837082 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/DesperateRitual.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.modernmasters; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.keyword.SpliceOntoArcaneAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class DesperateRitual extends CardImpl { + + public DesperateRitual(UUID ownerId) { + super(ownerId, 110, "Desperate Ritual", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{R}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Arcane"); + + this.color.setRed(true); + + // Add {R}{R}{R} to your mana pool. + this.getSpellAbility().addEffect(new BasicManaEffect(new Mana(3, 0, 0, 0, 0, 0, 0))); + // Splice onto Arcane {1}{R} + this.addAbility(new SpliceOntoArcaneAbility("{1}{R}")); + } + + public DesperateRitual(final DesperateRitual card) { + super(card); + } + + @Override + public DesperateRitual copy() { + return new DesperateRitual(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/DreamspoilerWitches.java b/Mage.Sets/src/mage/sets/modernmasters/DreamspoilerWitches.java new file mode 100644 index 00000000000..10f588cdf7f --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/DreamspoilerWitches.java @@ -0,0 +1,107 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.continious.BoostTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class DreamspoilerWitches extends CardImpl { + + public DreamspoilerWitches(UUID ownerId) { + super(ownerId, 81, "Dreamspoiler Witches", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Faerie"); + this.subtype.add("Wizard"); + + this.color.setBlack(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever you cast a spell during an opponent's turn, you may have target creature get -1/-1 until end of turn. + this.addAbility(new DreamspoilerWitchesTriggeredAbility()); + + } + + public DreamspoilerWitches(final DreamspoilerWitches card) { + super(card); + } + + @Override + public DreamspoilerWitches copy() { + return new DreamspoilerWitches(this); + } +} + +class DreamspoilerWitchesTriggeredAbility extends TriggeredAbilityImpl { + DreamspoilerWitchesTriggeredAbility() { + super(Zone.BATTLEFIELD, new BoostTargetEffect(-1,-1, Duration.EndOfTurn), true); + this.addTarget(new TargetCreaturePermanent(true)); + } + + DreamspoilerWitchesTriggeredAbility(final DreamspoilerWitchesTriggeredAbility ability) { + super(ability); + } + + @Override + public DreamspoilerWitchesTriggeredAbility copy() { + return new DreamspoilerWitchesTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SPELL_CAST + && event.getPlayerId().equals(this.controllerId) + && game.getOpponents(this.controllerId).contains(game.getActivePlayerId())) { + return true; + + } + return false; + } + + @Override + public String getRule() { + return "Whenever you cast a spell during an opponent's turn, " + super.getRule(); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/EarwigSquad.java b/Mage.Sets/src/mage/sets/modernmasters/EarwigSquad.java new file mode 100644 index 00000000000..837e9287c17 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/EarwigSquad.java @@ -0,0 +1,128 @@ +/* + * 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.modernmasters; + +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.ProwlCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardControllerEffect; +import mage.abilities.keyword.ProwlAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetOpponent; + +/** + * + * @author LevelX2 + */ +public class EarwigSquad extends CardImpl { + + public EarwigSquad(UUID ownerId) { + super(ownerId, 82, "Earwig Squad", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Goblin"); + this.subtype.add("Rogue"); + + this.color.setBlack(true); + this.power = new MageInt(5); + this.toughness = new MageInt(3); + + // Prowl {2}{B} + this.addAbility(new ProwlAbility(this, "{2}{B}")); + // When Earwig Squad enters the battlefield, if its prowl cost was paid, search target opponent's library for three cards and exile them. Then that player shuffles his or her library. + EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new EarwigSquadEffect(), false); + ability.addTarget(new TargetOpponent(true)); + this.addAbility(new ConditionalTriggeredAbility(ability, ProwlCondition.getInstance(), + "When {this} enters the battlefield, if its prowl cost was paid, search target opponent's library for three cards and exile them. Then that player shuffles his or her library.")); + + } + + public EarwigSquad(final EarwigSquad card) { + super(card); + } + + @Override + public EarwigSquad copy() { + return new EarwigSquad(this); + } +} + +class EarwigSquadEffect extends OneShotEffect { + + public EarwigSquadEffect() { + super(Outcome.Benefit); + staticText = "search target opponent's library for three cards and exile them. Then that player shuffles his or her library"; + } + + public EarwigSquadEffect(final EarwigSquadEffect effect) { + super(effect); + } + + @Override + public EarwigSquadEffect copy() { + return new EarwigSquadEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player opponent = game.getPlayer(source.getFirstTarget()); + Player player = game.getPlayer(source.getControllerId()); + if (player != null && opponent != null) { + Cards opponentLibrary = new CardsImpl(); + opponentLibrary.addAll(opponent.getLibrary().getCardList()); + + TargetCardInLibrary target = new TargetCardInLibrary(0, 3, new FilterCard("cards from opponents library to exile")); + if (player.choose(Outcome.Benefit, opponentLibrary, target, game)) { + List targets = target.getTargets(); + for (UUID targetId : targets) { + Card card = opponent.getLibrary().remove(targetId, game); + if (card != null) { + card.moveToExile(null, null, source.getId(), game); + } + } + } + opponent.shuffleLibrary(game); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/Epochrasite.java b/Mage.Sets/src/mage/sets/modernmasters/Epochrasite.java new file mode 100644 index 00000000000..d34353fdb5e --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/Epochrasite.java @@ -0,0 +1,87 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.common.CastFromHandCondition; +import mage.abilities.condition.common.InvertCondition; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.ExileSourceEffect; +import mage.abilities.effects.common.continious.GainAbilitySourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.SuspendAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.counters.CounterType; +import mage.watchers.common.CastFromHandWatcher; + +/** + * + * @author LevelX2 + */ +public class Epochrasite extends CardImpl { + + public Epochrasite(UUID ownerId) { + super(ownerId, 205, "Epochrasite", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Construct"); + + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + this.addWatcher(new CastFromHandWatcher()); + + // Epochrasite enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand. + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), + new InvertCondition(new CastFromHandCondition()), true, + "{this} enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand","")); + + // When Epochrasite dies, exile it with three time counters on it and it gains suspend. + Ability ability = new DiesTriggeredAbility(new ExileSourceEffect()); + ability.addEffect(new AddCountersSourceEffect(CounterType.TIME.createInstance(3), new StaticValue(0), false, true)); + ability.addEffect(new GainAbilitySourceEffect(new SuspendAbility(3, null, this), Duration.OneUse, true)); + this.addAbility(ability); + } + + public Epochrasite(final Epochrasite card) { + super(card); + } + + @Override + public Epochrasite copy() { + return new Epochrasite(this); + } +} + diff --git a/Mage.Sets/src/mage/sets/modernmasters/FuryCharm.java b/Mage.Sets/src/mage/sets/modernmasters/FuryCharm.java new file mode 100644 index 00000000000..3d8fea9f959 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/FuryCharm.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class FuryCharm extends mage.sets.planarchaos.FuryCharm { + + public FuryCharm(UUID ownerId) { + super(ownerId); + this.cardNumber = 114; + this.expansionSetCode = "MMA"; + } + + public FuryCharm(final FuryCharm card) { + super(card); + } + + @Override + public FuryCharm copy() { + return new FuryCharm(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/GlacialRay.java b/Mage.Sets/src/mage/sets/modernmasters/GlacialRay.java new file mode 100644 index 00000000000..73b0f4b3471 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/GlacialRay.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.modernmasters; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.SpliceOntoArcaneAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LevelX2 + */ +public class GlacialRay extends CardImpl { + + public GlacialRay(UUID ownerId) { + super(ownerId, 115, "Glacial Ray", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{R}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Arcane"); + + this.color.setRed(true); + + // Glacial Ray deals 2 damage to target creature or player. + this.getSpellAbility().addEffect(new DamageTargetEffect(2)); + this.getSpellAbility().addTarget(new TargetCreatureOrPlayer(true)); + // Splice onto Arcane {1}{R} + this.addAbility(new SpliceOntoArcaneAbility("{1}{R}")); + } + + public GlacialRay(final GlacialRay card) { + super(card); + } + + @Override + public GlacialRay copy() { + return new GlacialRay(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/GrinningIgnus.java b/Mage.Sets/src/mage/sets/modernmasters/GrinningIgnus.java new file mode 100644 index 00000000000..b4750ab5f61 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/GrinningIgnus.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.ReturnToHandSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.mana.ActivateAsSorceryManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class GrinningIgnus extends CardImpl { + + public GrinningIgnus(UUID ownerId) { + super(ownerId, 118, "Grinning Ignus", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Elemental"); + + this.color.setRed(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {R}, Return Grinning Ignus to its owner's hand: Add {2}{R} to your mana pool. Activate this ability only any time you could cast a sorcery. + Ability ability = new ActivateAsSorceryManaAbility(Zone.BATTLEFIELD, new Mana(1, 0, 0, 0, 0, 2, 0), new ManaCostsImpl("{R}")); + ability.addCost(new ReturnToHandSourceCost()); + this.addAbility(ability); + } + + public GrinningIgnus(final GrinningIgnus card) { + super(card); + } + + @Override + public GrinningIgnus copy() { + return new GrinningIgnus(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/HammerheimDeadeye.java b/Mage.Sets/src/mage/sets/modernmasters/HammerheimDeadeye.java new file mode 100644 index 00000000000..0191efbba38 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/HammerheimDeadeye.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.modernmasters; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class HammerheimDeadeye extends mage.sets.planarchaos.HammerheimDeadeye { + + public HammerheimDeadeye(UUID ownerId) { + super(ownerId); + this.cardNumber = 119; + this.expansionSetCode = "MMA"; + this.rarity = Rarity.COMMON; + } + + public HammerheimDeadeye(final HammerheimDeadeye card) { + super(card); + } + + @Override + public HammerheimDeadeye copy() { + return new HammerheimDeadeye(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/HorobisWhisper.java b/Mage.Sets/src/mage/sets/modernmasters/HorobisWhisper.java new file mode 100644 index 00000000000..a184763a994 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/HorobisWhisper.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.modernmasters; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class HorobisWhisper extends mage.sets.betrayersofkamigawa.HorobisWhisper { + + public HorobisWhisper(UUID ownerId) { + super(ownerId); + this.cardNumber = 88; + this.expansionSetCode = "MMA"; + this.rarity = Rarity.UNCOMMON; + } + + public HorobisWhisper(final HorobisWhisper card) { + super(card); + } + + @Override + public HorobisWhisper copy() { + return new HorobisWhisper(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/Imperiosaur.java b/Mage.Sets/src/mage/sets/modernmasters/Imperiosaur.java new file mode 100644 index 00000000000..328d6265684 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/Imperiosaur.java @@ -0,0 +1,96 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.StaticAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SupertypePredicate; + +/** + * + * @author LevelX2 + */ +public class Imperiosaur extends CardImpl { + + private static final FilterLandPermanent filter = new FilterLandPermanent(); + static { + filter.add(new SupertypePredicate("Basic")); + } + + public Imperiosaur(UUID ownerId) { + super(ownerId, 148, "Imperiosaur", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Lizard"); + + this.color.setGreen(true); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Spend only mana produced by basic lands to cast Imperiosaur. + this.addAbility(new ImperiosaurStaticAbility()); + this.getSpellAbility().getManaCostsToPay().setSourceFilter(filter); + this.getSpellAbility().getManaCosts().setSourceFilter(filter); + } + + public Imperiosaur(final Imperiosaur card) { + super(card); + } + + @Override + public Imperiosaur copy() { + return new Imperiosaur(this); + } +} + +class ImperiosaurStaticAbility extends StaticAbility { + + public ImperiosaurStaticAbility() { + super(Zone.STACK, null); + } + + public ImperiosaurStaticAbility(ImperiosaurStaticAbility ability) { + super(ability); + } + + @Override + public ImperiosaurStaticAbility copy() { + return new ImperiosaurStaticAbility(this); + } + + @Override + public String getRule() { + return "Spend only mana produced by basic lands to cast {this}."; + } + +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/JhoiraOfTheGhitu.java b/Mage.Sets/src/mage/sets/modernmasters/JhoiraOfTheGhitu.java new file mode 100644 index 00000000000..01302ad44dd --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/JhoiraOfTheGhitu.java @@ -0,0 +1,156 @@ +/* + * 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.modernmasters; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Abilities; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.ExileFromHandCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.SuspendAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterNonlandCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInHand; + +/** + * + * @author LevelX2 + */ +public class JhoiraOfTheGhitu extends CardImpl { + + public JhoiraOfTheGhitu(UUID ownerId) { + super(ownerId, 177, "Jhoira of the Ghitu", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); + this.expansionSetCode = "MMA"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Wizard"); + + this.color.setRed(true); + this.color.setBlue(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {2}, Exile a nonland card from your hand: Put four time counters on the exiled card. If it doesn't have suspend, it gains suspend. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new JhoiraOfTheGhituSuspendEffect(), new GenericManaCost(2)); + ability.addCost(new ExileFromHandCost(new TargetCardInHand(new FilterNonlandCard("a nonland card from your hand")))); + this.addAbility(ability); + + } + + public JhoiraOfTheGhitu(final JhoiraOfTheGhitu card) { + super(card); + } + + @Override + public JhoiraOfTheGhitu copy() { + return new JhoiraOfTheGhitu(this); + } +} + +class JhoiraOfTheGhituSuspendEffect extends OneShotEffect { + + public JhoiraOfTheGhituSuspendEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "Put four time counters on the exiled card. If it doesn't have suspend, it gains suspend (At the beginning of your upkeep, remove a time counter from that card. When the last is removed, cast it without paying its mana cost. If it's a creature, it has haste.)"; + } + + public JhoiraOfTheGhituSuspendEffect(final JhoiraOfTheGhituSuspendEffect effect) { + super(effect); + } + + @Override + public JhoiraOfTheGhituSuspendEffect copy() { + return new JhoiraOfTheGhituSuspendEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + List cards = new ArrayList(); + for (Cost cost: source.getCosts()) { + if (cost instanceof ExileFromHandCost) { + cards = ((ExileFromHandCost) cost).getCards(); + } + } + if (cards != null && !cards.isEmpty()) { + Card card = game.getCard(cards.get(0).getId()); + boolean hasSuspend = false; + for (Ability ability :card.getAbilities()) { + if (ability instanceof SuspendAbility) { + hasSuspend = true; + break; + } + } + + UUID exileId = (UUID) game.getState().getValue("SuspendExileId" + source.getControllerId().toString()); + if (exileId == null) { + exileId = UUID.randomUUID(); + game.getState().setValue("SuspendExileId" + source.getControllerId().toString(), exileId); + } + if (card.moveToExile(exileId, new StringBuilder("Suspended cards of ").append(controller.getName()).toString() , source.getSourceId(), game)) { + card.addCounters(CounterType.TIME.createInstance(4), game); + if (!hasSuspend) { + // add suspend ability + // TODO: Find a better solution for giving suspend to a card. + // If the exiled card leaves exile by another way, the abilites won't be removed from the card + Abilities oldAbilities = card.getAbilities().copy(); + SuspendAbility suspendAbility = new SuspendAbility(4, null, card); + card.addAbility(suspendAbility); + + for (Ability ability :card.getAbilities()) { + if (!oldAbilities.contains(ability)) { + ability.setControllerId(source.getControllerId()); + game.getState().addAbility(ability, card.getId(), card); + } + } + + } + game.informPlayers(new StringBuilder(controller.getName()).append(" suspends (").append(4).append(") ").append(card.getName()).toString()); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/KithkinGreatheart.java b/Mage.Sets/src/mage/sets/modernmasters/KithkinGreatheart.java new file mode 100644 index 00000000000..b270517da07 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/KithkinGreatheart.java @@ -0,0 +1,88 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.ControlsPermanentCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.abilities.effects.common.continious.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; + +/** + * + * @author LevelX2 + */ +public class KithkinGreatheart extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Giant"); + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + filter.add(new SubtypePredicate("Giant")); + } + + public KithkinGreatheart(UUID ownerId) { + super(ownerId, 21, "Kithkin Greatheart", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Kithkin"); + this.subtype.add("Soldier"); + + this.color.setWhite(true); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // As long as you control a Giant, Kithkin Greatheart gets +1/+1 and has first strike. + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect( + new BoostSourceEffect(1,1, Duration.WhileOnBattlefield), + new ControlsPermanentCondition(filter), + "As long as you control a Giant, Kithkin Greatheart gets +1/+1 and has first strike")); + ability.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance())); + this.addAbility(ability); + } + + public KithkinGreatheart(final KithkinGreatheart card) { + super(card); + } + + @Override + public KithkinGreatheart copy() { + return new KithkinGreatheart(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/KodamasReach.java b/Mage.Sets/src/mage/sets/modernmasters/KodamasReach.java new file mode 100644 index 00000000000..085b2a953e9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/KodamasReach.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class KodamasReach extends mage.sets.commander.KodamasReach { + + public KodamasReach(UUID ownerId) { + super(ownerId); + this.cardNumber = 151; + this.expansionSetCode = "MMA"; + } + + public KodamasReach(final KodamasReach card) { + super(card); + } + + @Override + public KodamasReach copy() { + return new KodamasReach(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/LatchkeyFaerie.java b/Mage.Sets/src/mage/sets/modernmasters/LatchkeyFaerie.java new file mode 100644 index 00000000000..14dd89fc3ff --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/LatchkeyFaerie.java @@ -0,0 +1,77 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.ProwlCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.DrawCardControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.ProwlAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class LatchkeyFaerie extends CardImpl { + + public LatchkeyFaerie(UUID ownerId) { + super(ownerId, 50, "Latchkey Faerie", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{U}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Faerie"); + this.subtype.add("Rogue"); + + this.color.setBlue(true); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Prowl {2}{U} + this.addAbility(new ProwlAbility(this, "{2}{U}")); + // When Latchkey Faerie enters the battlefield, if its prowl cost was paid, draw a card. + EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DrawCardControllerEffect(1), false); + this.addAbility(new ConditionalTriggeredAbility(ability, ProwlCondition.getInstance(), + "When {this} enters the battlefield, if its prowl cost was paid, draw a card.")); + + } + + public LatchkeyFaerie(final LatchkeyFaerie card) { + super(card); + } + + @Override + public LatchkeyFaerie copy() { + return new LatchkeyFaerie(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/LogicKnot.java b/Mage.Sets/src/mage/sets/modernmasters/LogicKnot.java new file mode 100644 index 00000000000..1670de315dc --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/LogicKnot.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.modernmasters; + +import java.util.UUID; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.common.CounterUnlessPaysEffect; +import mage.abilities.keyword.DelveAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.TargetSpell; + +/** + * + * @author LevelX2 + */ +public class LogicKnot extends CardImpl { + + public LogicKnot(UUID ownerId) { + super(ownerId, 51, "Logic Knot", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{X}{U}{U}"); + this.expansionSetCode = "MMA"; + + this.color.setBlue(true); + + // Delve + this.addAbility(new DelveAbility()); + + // Counter target spell unless its controller pays {X}. + this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new ManacostVariableValue())); + this.getSpellAbility().addTarget(new TargetSpell()); + } + + public LogicKnot(final LogicKnot card) { + super(card); + } + + @Override + public LogicKnot copy() { + return new LogicKnot(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/MaskedAdmirers.java b/Mage.Sets/src/mage/sets/modernmasters/MaskedAdmirers.java new file mode 100644 index 00000000000..b57b228388d --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/MaskedAdmirers.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SpellCastTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.DrawCardControllerEffect; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.CardTypePredicate; + +/** + * + * @author LevelX2 + */ +public class MaskedAdmirers extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("a creature spell"); + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + } + + public MaskedAdmirers(UUID ownerId) { + super(ownerId, 154, "Masked Admirers", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Elf"); + this.subtype.add("Shaman"); + + this.color.setGreen(true); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When Masked Admirers enters the battlefield, draw a card. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardControllerEffect(1), false)); + // Whenever you cast a creature spell, you may pay {G}{G}. If you do, return Masked Admirers from your graveyard to your hand. + OneShotEffect effect = new ReturnToHandSourceEffect(); + effect.setText("return {this} from your graveyard to your hand"); + this.addAbility(new SpellCastTriggeredAbility( + Zone.GRAVEYARD, new DoIfCostPaid(effect, new ManaCostsImpl("{G}{G}")), filter, false, false)); + } + + public MaskedAdmirers(final MaskedAdmirers card) { + super(card); + } + + @Override + public MaskedAdmirers copy() { + return new MaskedAdmirers(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/MoltenDisaster.java b/Mage.Sets/src/mage/sets/modernmasters/MoltenDisaster.java new file mode 100644 index 00000000000..715f485c371 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/MoltenDisaster.java @@ -0,0 +1,152 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.GainAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.KickerAbility; +import mage.abilities.keyword.SplitSecondAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class MoltenDisaster extends CardImpl { + + public MoltenDisaster(UUID ownerId) { + super(ownerId, 123, "Molten Disaster", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{R}{R}"); + this.expansionSetCode = "MMA"; + + this.color.setRed(true); + + // If Molten Disaster was kicked, it has split second. + Ability ability = new ConditionalTriggeredAbility(new MoltenDisasterTriggeredAbility(), KickedCondition.getInstance(), ""); + ability.setRuleAtTheTop(true); + this.addAbility(ability); + // Kicker {R} + this.addAbility(new KickerAbility("{R}")); + // Molten Disaster deals X damage to each creature without flying and each player. + this.getSpellAbility().addEffect(new MoltenDisasterEffect()); + } + + public MoltenDisaster(final MoltenDisaster card) { + super(card); + } + + @Override + public MoltenDisaster copy() { + return new MoltenDisaster(this); + } +} + +class MoltenDisasterTriggeredAbility extends TriggeredAbilityImpl { + + public MoltenDisasterTriggeredAbility() { + super(Zone.HAND, new GainAbilitySourceEffect(SplitSecondAbility.getInstance(), Duration.WhileOnStack), false); + } + + public MoltenDisasterTriggeredAbility(final MoltenDisasterTriggeredAbility ability) { + super(ability); + } + + @Override + public MoltenDisasterTriggeredAbility copy() { + return new MoltenDisasterTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType().equals(GameEvent.EventType.CAST_SPELL) && event.getSourceId().equals(this.getSourceId())) { + return true; + } + return false; + } + + @Override + public String getRule() { + return "If Molten Disaster was kicked, it has split second (As long as this spell is on the stack, players can't cast spells or activate abilities that aren't mana abilities.)"; + } +} + +class MoltenDisasterEffect extends OneShotEffect { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); + } + + public MoltenDisasterEffect() { + super(Outcome.Damage); + staticText = "{this} deals X damage to each creature without flying and each player"; + } + + public MoltenDisasterEffect(final MoltenDisasterEffect effect) { + super(effect); + } + + @Override + public MoltenDisasterEffect copy() { + return new MoltenDisasterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = source.getManaCostsToPay().getX(); + for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { + permanent.damage(amount, source.getId(), game, true, false); + } + for (UUID playerId: game.getPlayer(source.getControllerId()).getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null) { + player.damage(amount, source.getSourceId(), game, false, true); + } + } + return true; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/modernmasters/OonaQueenOfTheFae.java b/Mage.Sets/src/mage/sets/modernmasters/OonaQueenOfTheFae.java new file mode 100644 index 00000000000..a9e95fb5027 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/OonaQueenOfTheFae.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class OonaQueenOfTheFae extends mage.sets.shadowmoor.OonaQueenOfTheFae { + + public OonaQueenOfTheFae(UUID ownerId) { + super(ownerId); + this.cardNumber = 193; + this.expansionSetCode = "MMA"; + } + + public OonaQueenOfTheFae(final OonaQueenOfTheFae card) { + super(card); + } + + @Override + public OonaQueenOfTheFae copy() { + return new OonaQueenOfTheFae(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/PardicDragon.java b/Mage.Sets/src/mage/sets/modernmasters/PardicDragon.java new file mode 100644 index 00000000000..327b7e2e013 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/PardicDragon.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.modernmasters; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class PardicDragon extends mage.sets.timespiral.PardicDragon { + + public PardicDragon(UUID ownerId) { + super(ownerId); + this.cardNumber = 124; + this.expansionSetCode = "MMA"; + this.rarity = Rarity.UNCOMMON; + } + + public PardicDragon(final PardicDragon card) { + super(card); + } + + @Override + public PardicDragon copy() { + return new PardicDragon(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/PetalsOfInsight.java b/Mage.Sets/src/mage/sets/modernmasters/PetalsOfInsight.java index 27c3974522a..0eb92b10ff9 100644 --- a/Mage.Sets/src/mage/sets/modernmasters/PetalsOfInsight.java +++ b/Mage.Sets/src/mage/sets/modernmasters/PetalsOfInsight.java @@ -28,16 +28,17 @@ package mage.sets.modernmasters; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.PostResolveEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.Cards; import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; import mage.players.Player; @@ -58,6 +59,7 @@ public class PetalsOfInsight extends CardImpl { // Look at the top three cards of your library. You may put those cards on the bottom of your library in any order. If you do, return Petals of Insight to its owner's hand. Otherwise, draw three cards. this.getSpellAbility().addEffect(new PetalsOfInsightEffect()); + this.getSpellAbility().addEffect(new PetalsOfInsightReturnEffect()); } public PetalsOfInsight(final PetalsOfInsight card) { @@ -74,7 +76,7 @@ class PetalsOfInsightEffect extends OneShotEffect { public PetalsOfInsightEffect() { super(Outcome.Benefit); - this.staticText = "Look at the top three cards of your library. You may put those cards on the bottom of your library in any order. If you do, return Petals of Insight to its owner's hand. Otherwise, draw three cards"; + this.staticText = "Look at the top three cards of your library. You may put those cards on the bottom of your library in any order"; } public PetalsOfInsightEffect(final PetalsOfInsightEffect effect) { @@ -118,6 +120,7 @@ class PetalsOfInsightEffect extends OneShotEffect { Card card = cards.get(cards.iterator().next(), game); card.moveToZone(Zone.LIBRARY, source.getId(), game, false); } + game.getState().setValue(source.getSourceId().toString(), Boolean.TRUE); } else { for (UUID cardId: cards) { Card card = game.getCard(cardId); @@ -125,9 +128,43 @@ class PetalsOfInsightEffect extends OneShotEffect { card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); } } - player.drawCards(3, game, null); - return true; + game.getState().setValue(source.getSourceId().toString(), Boolean.FALSE); } - return false; + return true; + } +} + +class PetalsOfInsightReturnEffect extends PostResolveEffect { + + public PetalsOfInsightReturnEffect() { + staticText = "If you do, return Petals of Insight to its owner's hand. Otherwise, draw three cards"; + } + + public PetalsOfInsightReturnEffect(final PetalsOfInsightReturnEffect effect) { + super(effect); + } + + @Override + public PetalsOfInsightReturnEffect copy() { + return new PetalsOfInsightReturnEffect(this); + } + + @Override + public void postResolve(Card card, Ability source, UUID controllerId, Game game) { + Player controller = game.getPlayer(controllerId); + if (controller != null) { + Boolean returnToHand = (Boolean) game.getState().getValue(source.getSourceId().toString()); + if (returnToHand == null) { + returnToHand = Boolean.FALSE; + } + if (returnToHand) { + card.moveToZone(Zone.HAND, source.getId(), game, false); + } + else { + card.moveToZone(Zone.GRAVEYARD, source.getId(), game, false); + controller.drawCards(3, game); + } + } + } } diff --git a/Mage.Sets/src/mage/sets/modernmasters/Phthisis.java b/Mage.Sets/src/mage/sets/modernmasters/Phthisis.java new file mode 100644 index 00000000000..98d12ebded6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/Phthisis.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class Phthisis extends mage.sets.timespiral.Phthisis { + + public Phthisis(UUID ownerId) { + super(ownerId); + this.cardNumber = 93; + this.expansionSetCode = "MMA"; + } + + public Phthisis(final Phthisis card) { + super(card); + } + + @Override + public Phthisis copy() { + return new Phthisis(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/PyromancersSwath.java b/Mage.Sets/src/mage/sets/modernmasters/PyromancersSwath.java new file mode 100644 index 00000000000..a1d1805084e --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/PyromancersSwath.java @@ -0,0 +1,121 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.OnEventTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.DiscardHandControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; + +/** + * + * @author LevelX2 + */ +public class PyromancersSwath extends CardImpl { + + public PyromancersSwath(UUID ownerId) { + super(ownerId, 125, "Pyromancer's Swath", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + this.expansionSetCode = "MMA"; + + this.color.setRed(true); + + // If an instant or sorcery source you control would deal damage to a creature or player, it deals that much damage plus 2 to that creature or player instead. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PyromancersSwathReplacementEffect())); + + // At the beginning of each end step, discard your hand. + this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, + "beginning of each end step", false, new DiscardHandControllerEffect())); + + } + + public PyromancersSwath(final PyromancersSwath card) { + super(card); + } + + @Override + public PyromancersSwath copy() { + return new PyromancersSwath(this); + } +} + +class PyromancersSwathReplacementEffect extends ReplacementEffectImpl { + + PyromancersSwathReplacementEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "If an instant or sorcery source you control would deal damage to a creature or player, it deals that much damage plus 2 to that creature or player instead"; + } + + PyromancersSwathReplacementEffect(final PyromancersSwathReplacementEffect effect) { + super(effect); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER) + || event.getType().equals(GameEvent.EventType.DAMAGE_CREATURE)) { + MageObject object = game.getObject(event.getSourceId()); + if (object != null && object instanceof Spell) { + if (((Spell) object).getControllerId().equals(source.getControllerId()) + && (object.getCardType().contains(CardType.INSTANT) + || object.getCardType().contains(CardType.SORCERY))){ + return true; + } + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + event.setAmount(event.getAmount() + 2); + return false; + } + + @Override + public PyromancersSwathReplacementEffect copy() { + return new PyromancersSwathReplacementEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/RiftElemental.java b/Mage.Sets/src/mage/sets/modernmasters/RiftElemental.java new file mode 100644 index 00000000000..d4deb0375ab --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/RiftElemental.java @@ -0,0 +1,207 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.ActivatedAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.costs.common.RemoveCounterCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.abilities.keyword.SuspendAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +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.counters.Counter; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.filter.predicate.other.OwnerPredicate; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInExile; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class RiftElemental extends CardImpl { + + private static final FilterCard filter = new FilterCard("suspended card you own"); + static { + filter.add(new CounterPredicate(CounterType.TIME)); + filter.add(new AbilityPredicate(SuspendAbility.class)); + filter.add(new OwnerPredicate(TargetController.YOU)); + } + + public RiftElemental(UUID ownerId) { + super(ownerId, 127, "Rift Elemental", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{R}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Elemental"); + + this.color.setRed(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {1}{R}, Remove a time counter from a permanent you control or suspended card you own: Rift Elemental gets +2/+0 until end of turn. + Choice targetChoice = new ChoiceImpl(); + targetChoice.setMessage("Choose what to target"); + targetChoice.getChoices().add("Permanent"); + targetChoice.getChoices().add("Suspended Card"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(2,0,Duration.EndOfTurn), new ManaCostsImpl("{1}{R}")); + ability.addChoice(targetChoice); + ability.addCost(new RemoveCounterFromCardCost(new TargetCardInExile(1,1,filter, null, true), CounterType.TIME)); + this.addAbility(ability); + } + + @Override + public void adjustCosts(Ability ability, Game game) { + if (ability instanceof ActivatedAbility && !ability.getChoices().isEmpty()) { + ability.getCosts().clear(); + Choice targetChoice = ability.getChoices().get(0); + if (targetChoice.getChoice().equals("Permanent")) { + ability.addCost(new RemoveCounterCost(new TargetControlledCreaturePermanent(), CounterType.TIME)); + } + if (targetChoice.getChoice().equals("Suspended Card")) { + ability.addCost(new RemoveCounterFromCardCost(new TargetCardInExile(1,1,filter, null, true), CounterType.TIME)); + } + } + } + + public RiftElemental(final RiftElemental card) { + super(card); + } + + @Override + public RiftElemental copy() { + return new RiftElemental(this); + } +} + +class RemoveCounterFromCardCost extends CostImpl { + + private TargetCard target; + private String name; + private CounterType counterTypeToRemove; + + public RemoveCounterFromCardCost(TargetCard target) { + this(target, null); + } + + public RemoveCounterFromCardCost(TargetCard target, CounterType counterTypeToRemove) { + this.target = target; + this.counterTypeToRemove = counterTypeToRemove; + text = setText(); + } + + public RemoveCounterFromCardCost(final RemoveCounterFromCardCost cost) { + super(cost); + this.target = cost.target.copy(); + this.name = cost.name; + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { + paid = false; + Player controller = game.getPlayer(controllerId); + if (target.choose(Outcome.UnboostCreature, controllerId, sourceId, game)) { + for (UUID targetId: (List)target.getTargets()) { + Card card = game.getCard(targetId); + if (card != null) { + if (card.getCounters().size() > 0 && (counterTypeToRemove == null || card.getCounters().containsKey(counterTypeToRemove))) { + String counterName = null; + if (counterTypeToRemove != null) { + counterName = counterTypeToRemove.getName(); + } else { + if (card.getCounters().size() > 1 && counterTypeToRemove == null) { + Choice choice = new ChoiceImpl(true); + Set choices = new HashSet(); + for (Counter counter : card.getCounters().values()) { + if (card.getCounters().getCount(counter.getName()) > 0) { + choices.add(counter.getName()); + } + } + choice.setChoices(choices); + choice.setMessage("Choose a counter to remove from " + card.getName()); + controller.choose(Outcome.UnboostCreature, choice, game); + counterName = choice.getChoice(); + } else { + for (Counter counter : card.getCounters().values()) { + if (counter.getCount() > 0) { + counterName = counter.getName(); + } + } + } + } + if (counterName != null) { + card.removeCounters(counterName, 1, game); + if (card.getCounters().getCount(counterName) == 0 ){ + card.getCounters().removeCounter(counterName); + } + this.paid = true; + game.informPlayers(new StringBuilder(controller.getName()).append(" removes a ").append(counterName).append(" counter from ").append(card.getName()).toString()); + } + } + } + } + } + target.clearChosen(); + return paid; + } + + @Override + public boolean canPay(UUID sourceId, UUID controllerId, Game game) { + return target.canChoose(controllerId, game); + } + + private String setText() { + return "Remove a time counter from a permanent you control or suspended card you own"; + } + + @Override + public RemoveCounterFromCardCost copy() { + return new RemoveCounterFromCardCost(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/Riftsweeper.java b/Mage.Sets/src/mage/sets/modernmasters/Riftsweeper.java new file mode 100644 index 00000000000..3f23cce82a6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/Riftsweeper.java @@ -0,0 +1,115 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.HauntAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +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.other.FaceDownPredicate; +import mage.game.Game; +import mage.target.common.TargetCardInExile; + +/** + * + * @author LevelX2 + */ +public class Riftsweeper extends CardImpl { + + private static final FilterCard filter = new FilterCard("face-up exiled card"); + static { + filter.add(Predicates.not(new FaceDownPredicate())); + } + + public Riftsweeper(UUID ownerId) { + super(ownerId, 159, "Riftsweeper", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{G}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Elf"); + this.subtype.add("Shaman"); + + this.color.setGreen(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Riftsweeper enters the battlefield, choose target face-up exiled card. Its owner shuffles it into his or her library. + Ability ability = new EntersBattlefieldTriggeredAbility(new RiftsweeperEffect(), false); + ability.addTarget(new TargetCardInExile(1, 1, filter, null, true)); + this.addAbility(ability); + } + + public Riftsweeper(final Riftsweeper card) { + super(card); + } + + @Override + public Riftsweeper copy() { + return new Riftsweeper(this); + } +} + +class RiftsweeperEffect extends OneShotEffect { + + public RiftsweeperEffect() { + super(Outcome.Benefit); + this.staticText = "choose target face-up exiled card. Its owner shuffles it into his or her library"; + } + + public RiftsweeperEffect(final RiftsweeperEffect effect) { + super(effect); + } + + @Override + public RiftsweeperEffect copy() { + return new RiftsweeperEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(targetPointer.getFirst(game, source)); + if (card != null) { + // remove exiting suspend counters + card.getCounters().clear(); + // move to exile + card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); + game.getState().getPlayer(card.getOwnerId()).getLibrary().shuffle(); + game.informPlayers(new StringBuilder("Riftsweeper: Choosen card was ").append(card.getName()).toString()); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/RudeAwakening.java b/Mage.Sets/src/mage/sets/modernmasters/RudeAwakening.java new file mode 100644 index 00000000000..bda59eebe31 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/RudeAwakening.java @@ -0,0 +1,88 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Mode; +import mage.abilities.effects.common.UntapAllLandsControllerEffect; +import mage.abilities.effects.common.continious.BecomesCreatureAllEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledLandPermanent; +import mage.game.permanent.token.Token; + + +/** + * + * @author LevelX2 + */ +public class RudeAwakening extends CardImpl { + + public RudeAwakening(UUID ownerId) { + super(ownerId, 160, "Rude Awakening", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{G}"); + this.expansionSetCode = "MMA"; + + this.color.setGreen(true); + + // Choose one - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // Untap all lands you control; + this.getSpellAbility().addEffect(new UntapAllLandsControllerEffect()); + // or until end of turn, lands you control become 2/2 creatures that are still lands. + Mode mode = new Mode(); + mode.getEffects().add(new BecomesCreatureAllEffect(new RudeAwakeningToken(), "lands", new FilterControlledLandPermanent("lands you control"), Duration.EndOfTurn)); + this.getSpellAbility().getModes().addMode(mode); + + // Entwine {2}{G} + this.addAbility(new EntwineAbility("{2}{G}")); + } + + public RudeAwakening(final RudeAwakening card) { + super(card); + } + + @Override + public RudeAwakening copy() { + return new RudeAwakening(this); + } +} + +class RudeAwakeningToken extends Token { + public RudeAwakeningToken() { + super("", "2/2 creature"); + cardType.add(CardType.CREATURE); + power = new MageInt(2); + toughness = new MageInt(2); + } + +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/RunedStalactite.java b/Mage.Sets/src/mage/sets/modernmasters/RunedStalactite.java new file mode 100644 index 00000000000..6a08de7e6bf --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/RunedStalactite.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.modernmasters; + +import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continious.BoostEquippedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.ChangelingAbility; +import mage.abilities.keyword.EquipAbility; +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.Zone; + +/** + * + * @author LevelX2 + */ +public class RunedStalactite extends CardImpl { + + public RunedStalactite(UUID ownerId) { + super(ownerId, 214, "Runed Stalactite", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Equipment"); + + // Equipped creature gets +1/+1 and is every creature type. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1,1))); + Effect effect = new GainAbilityAttachedEffect(ChangelingAbility.getInstance(), AttachmentType.EQUIPMENT, Duration.WhileOnBattlefield); + effect.setText("Equipped creature is every creature type (Changeling)"); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + // Equip {2} + this.addAbility(new EquipAbility(Outcome.BoostCreature, new ManaCostsImpl("{2}"))); + } + + public RunedStalactite(final RunedStalactite card) { + super(card); + } + + @Override + public RunedStalactite copy() { + return new RunedStalactite(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/SqueeGoblinNabob.java b/Mage.Sets/src/mage/sets/modernmasters/SqueeGoblinNabob.java new file mode 100644 index 00000000000..6ba36633d8c --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/SqueeGoblinNabob.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class SqueeGoblinNabob extends mage.sets.tenth.SqueeGoblinNabob { + + public SqueeGoblinNabob(UUID ownerId) { + super(ownerId); + this.cardNumber = 130; + this.expansionSetCode = "MMA"; + } + + public SqueeGoblinNabob(final SqueeGoblinNabob card) { + super(card); + } + + @Override + public SqueeGoblinNabob copy() { + return new SqueeGoblinNabob(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/StirThePride.java b/Mage.Sets/src/mage/sets/modernmasters/StirThePride.java new file mode 100644 index 00000000000..ce6196b28af --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/StirThePride.java @@ -0,0 +1,155 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.BoostControlledEffect; +import mage.abilities.effects.common.continious.GainAbilityControlledEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class StirThePride extends CardImpl { + + public StirThePride(UUID ownerId) { + super(ownerId, 30, "Stir the Pride", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{4}{W}"); + this.expansionSetCode = "MMA"; + + this.color.setWhite(true); + + // Choose one - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // Creatures you control get +2/+2 until end of turn; + this.getSpellAbility().addEffect(new BoostControlledEffect(2,2, Duration.EndOfTurn)); + // or until end of turn, creatures you control gain "Whenever this creature deals damage, you gain that much life." + Mode mode = new Mode(); + Effect effect = new GainAbilityControlledEffect(new StirThePrideTriggeredAbility(), Duration.EndOfTurn); + effect.setText("until end of turn, creatures you control gain \"Whenever this creature deals damage, you gain that much life.\""); + mode.getEffects().add(effect); + this.getSpellAbility().getModes().addMode(mode); + + // Entwine {1}{W} + this.addAbility(new EntwineAbility("{1}{W}")); + + } + + public StirThePride(final StirThePride card) { + super(card); + } + + @Override + public StirThePride copy() { + return new StirThePride(this); + } +} + +class StirThePrideTriggeredAbility extends TriggeredAbilityImpl { + + public StirThePrideTriggeredAbility() { + super(Zone.BATTLEFIELD, new StirThePrideGainLifeEffect(), false); + } + + public StirThePrideTriggeredAbility(final StirThePrideTriggeredAbility ability) { + super(ability); + } + + @Override + public StirThePrideTriggeredAbility copy() { + return new StirThePrideTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType().equals(EventType.DAMAGED_CREATURE) + || event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER) + || event.getType().equals(GameEvent.EventType.DAMAGED_PLANESWALKER)) { + if (event.getSourceId().equals(this.getSourceId())) { + for (Effect effect : this.getEffects()) { + effect.setValue("damage", event.getAmount()); + } + return true; + } + + } + return false; + } + + @Override + public String getRule() { + return "Whenever {this} deals damage, " + super.getRule(); + } + +} + +class StirThePrideGainLifeEffect extends OneShotEffect { + + public StirThePrideGainLifeEffect() { + super(Outcome.GainLife); + this.staticText = "you gain that much life"; + } + + public StirThePrideGainLifeEffect(final StirThePrideGainLifeEffect effect) { + super(effect); + } + + @Override + public StirThePrideGainLifeEffect copy() { + return new StirThePrideGainLifeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = (Integer) getValue("damage"); + if (amount > 0) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.gainLife(amount, game); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/SuddenShock.java b/Mage.Sets/src/mage/sets/modernmasters/SuddenShock.java new file mode 100644 index 00000000000..98e2c948213 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/SuddenShock.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class SuddenShock extends mage.sets.timespiral.SuddenShock { + + public SuddenShock(UUID ownerId) { + super(ownerId); + this.cardNumber = 133; + this.expansionSetCode = "MMA"; + } + + public SuddenShock(final SuddenShock card) { + super(card); + } + + @Override + public SuddenShock copy() { + return new SuddenShock(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/TakePossession.java b/Mage.Sets/src/mage/sets/modernmasters/TakePossession.java new file mode 100644 index 00000000000..6dc266b9ca3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/TakePossession.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.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continious.ControlEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.SplitSecondAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; + +/** + * + * @author LevelX2 + */ +public class TakePossession extends CardImpl { + + public TakePossession(UUID ownerId) { + super(ownerId, 66, "Take Possession", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{5}{U}{U}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Aura"); + + this.color.setBlue(true); + + // Split second + this.addAbility(SplitSecondAbility.getInstance()); + // Enchant permanent + TargetPermanent auraTarget = new TargetPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.GainControl)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // You control enchanted permanent. + Effect effect = new ControlEnchantedEffect(); + effect.setText("You control enchanted permanent"); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + + } + + public TakePossession(final TakePossession card) { + super(card); + } + + @Override + public TakePossession copy() { + return new TakePossession(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/TestOfFaith.java b/Mage.Sets/src/mage/sets/modernmasters/TestOfFaith.java new file mode 100644 index 00000000000..8547c2564cc --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/TestOfFaith.java @@ -0,0 +1,138 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.PreventionEffectImpl; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class TestOfFaith extends CardImpl { + + public TestOfFaith(UUID ownerId) { + super(ownerId, 33, "Test of Faith", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{W}"); + this.expansionSetCode = "MMA"; + + this.color.setWhite(true); + + // Prevent the next 3 damage that would be dealt to target creature this turn, and put a +1/+1 counter on that creature for each 1 damage prevented this way. + this.getSpellAbility().addEffect(new TestOfFaithPreventDamageTargetEffect(Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(true)); + + } + + public TestOfFaith(final TestOfFaith card) { + super(card); + } + + @Override + public TestOfFaith copy() { + return new TestOfFaith(this); + } +} + +class TestOfFaithPreventDamageTargetEffect extends PreventionEffectImpl { + + private int amount = 3; + + public TestOfFaithPreventDamageTargetEffect(Duration duration) { + super(duration); + staticText = "Prevent the next 3 damage that would be dealt to target creature this turn, and put a +1/+1 counter on that creature for each 1 damage prevented this way"; + } + + public TestOfFaithPreventDamageTargetEffect(final TestOfFaithPreventDamageTargetEffect effect) { + super(effect); + this.amount = effect.amount; + } + + @Override + public TestOfFaithPreventDamageTargetEffect copy() { + return new TestOfFaithPreventDamageTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), event.getAmount(), false); + if (!game.replaceEvent(preventEvent)) { + int prevented = 0; + if (event.getAmount() >= this.amount) { + int damage = amount; + event.setAmount(event.getAmount() - amount); + this.used = true; + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), damage)); + prevented = damage; + } else { + int damage = event.getAmount(); + event.setAmount(0); + amount -= damage; + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getId(), source.getControllerId(), damage)); + prevented = damage; + } + + // add counters now + if (prevented > 0) { + Permanent targetPermanent = game.getPermanent(source.getTargets().getFirstTarget()); + if (targetPermanent != null) { + targetPermanent.addCounters(CounterType.P1P1.createInstance(prevented), game); + game.informPlayers(new StringBuilder("Test of Faith: Prevented ").append(prevented).append(" damage ").toString()); + game.informPlayers("Test of Faith: Adding " + prevented + " +1/+1 counters to " + targetPermanent.getName()); + } + } + return true; + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (!this.used && super.applies(event, source, game)) { + if (source.getTargets().getFirstTarget().equals(event.getTargetId())) { + return true; + } + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/ThievingSprite.java b/Mage.Sets/src/mage/sets/modernmasters/ThievingSprite.java new file mode 100644 index 00000000000..280f0d16d32 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/ThievingSprite.java @@ -0,0 +1,150 @@ +/* + * 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.modernmasters; + +import java.util.List; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlyingAbility; +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.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.TargetPlayer; + +/** + * + * @author LevelX2 + */ +public class ThievingSprite extends CardImpl { + + public ThievingSprite(UUID ownerId) { + super(ownerId, 101, "Thieving Sprite", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Faerie"); + this.subtype.add("Rogue"); + + this.color.setBlack(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // When Thieving Sprite enters the battlefield, target player reveals X cards from his or her hand, where X is the number of Faeries you control. You choose one of those cards. That player discards that card. + Ability ability = new EntersBattlefieldTriggeredAbility(new ThievingSpriteEffect(), false); + TargetPlayer target = new TargetPlayer(); + target.setRequired(true); + ability.addTarget(target); + this.addAbility(ability); + + } + + public ThievingSprite(final ThievingSprite card) { + super(card); + } + + @Override + public ThievingSprite copy() { + return new ThievingSprite(this); + } +} + +class ThievingSpriteEffect extends OneShotEffect { + + public ThievingSpriteEffect() { + super(Outcome.Discard); + this.staticText = "target player reveals X cards from his or her hand, where X is the number of Faeries you control. You choose one of those cards. That player discards that card"; + } + + public ThievingSpriteEffect(final ThievingSpriteEffect effect) { + super(effect); + } + + @Override + public ThievingSpriteEffect copy() { + return new ThievingSpriteEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); + if (targetPlayer == null || controller == null) { + return false; + } + + FilterControlledPermanent filter = new FilterControlledPermanent(); + filter.add(new SubtypePredicate("Faerie")); + int numberOfFaeries = game.getBattlefield().countAll(filter, controller.getId(), game); + + Cards cardsInHand = new CardsImpl(Zone.PICK); + cardsInHand.addAll(targetPlayer.getHand()); + int count = Math.min(cardsInHand.size(), numberOfFaeries); + + TargetCard target = new TargetCard(count, Zone.PICK, new FilterCard()); + target.setRequired(true); + Cards revealedCards = new CardsImpl(); + + if (targetPlayer.choose(Outcome.Discard, cardsInHand, target, game)) { + List targets = target.getTargets(); + for (UUID targetId : targets) { + Card card = game.getCard(targetId); + if (card != null) { + revealedCards.add(card); + } + } + } + + TargetCard targetInHand = new TargetCard(Zone.PICK, new FilterCard("card to discard")); + targetInHand.setRequired(true); + + if (!revealedCards.isEmpty()) { + targetPlayer.revealCards("Thieving Sprite", revealedCards, game); + controller.choose(Outcome.Discard, revealedCards, targetInHand, game); + Card card = revealedCards.get(targetInHand.getFirstTarget(), game); + if (card != null) { + targetPlayer.discard(card, source, game); + game.informPlayers(new StringBuilder("Thieving Sprite: ").append(targetPlayer.getName()).append(" discarded ").append(card.getName()).toString()); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/ThundercloudShaman.java b/Mage.Sets/src/mage/sets/modernmasters/ThundercloudShaman.java new file mode 100644 index 00000000000..788a75f1ff5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/ThundercloudShaman.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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.ControllerPredicate; + +/** + * + * @author LevelX2 + */ +public class ThundercloudShaman extends CardImpl { + + private static final FilterCreaturePermanent filterGiants = new FilterCreaturePermanent("equal to the number of Giants you control"); + private static final FilterCreaturePermanent filterNonGiants = new FilterCreaturePermanent("non-Giant creature"); + static { + filterGiants.add(new ControllerPredicate(TargetController.YOU)); + filterGiants.add(new SubtypePredicate("Giant")); + filterNonGiants.add(Predicates.not(new SubtypePredicate("Giant"))); + } + + public ThundercloudShaman(UUID ownerId) { + super(ownerId, 135, "Thundercloud Shaman", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Giant"); + this.subtype.add("Shaman"); + + this.color.setRed(true); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // When Thundercloud Shaman enters the battlefield, it deals damage equal to the number of Giants you control to each non-Giant creature. + Effect effect = new DamageAllEffect(new PermanentsOnBattlefieldCount(filterGiants),filterNonGiants); + effect.setText("it deals damage equal to the number of Giants you control to each non-Giant creature"); + this.addAbility(new EntersBattlefieldTriggeredAbility(effect, false)); + } + + public ThundercloudShaman(final ThundercloudShaman card) { + super(card); + } + + @Override + public ThundercloudShaman copy() { + return new ThundercloudShaman(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/TidehollowSculler.java b/Mage.Sets/src/mage/sets/modernmasters/TidehollowSculler.java new file mode 100644 index 00000000000..0e0ad4d5055 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/TidehollowSculler.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class TidehollowSculler extends mage.sets.shardsofalara.TidehollowSculler { + + public TidehollowSculler(UUID ownerId) { + super(ownerId); + this.cardNumber = 184; + this.expansionSetCode = "MMA"; + } + + public TidehollowSculler(final TidehollowSculler card) { + super(card); + } + + @Override + public TidehollowSculler copy() { + return new TidehollowSculler(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/Tombstalker.java b/Mage.Sets/src/mage/sets/modernmasters/Tombstalker.java new file mode 100644 index 00000000000..339b15d08c2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/Tombstalker.java @@ -0,0 +1,70 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.keyword.DelveAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class Tombstalker extends CardImpl { + + public Tombstalker(UUID ownerId) { + super(ownerId, 102, "Tombstalker", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{6}{B}{B}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Demon"); + + this.color.setBlack(true); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Delve + Ability ability = new DelveAbility(); + ability.setRuleAtTheTop(false); + this.addAbility(ability); + } + + public Tombstalker(final Tombstalker card) { + super(card); + } + + @Override + public Tombstalker copy() { + return new Tombstalker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.java b/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.java new file mode 100644 index 00000000000..62d5f76bbbb --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/ToothAndNail.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.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetCardInLibrary; + +/** + * + * @author LevelX2 + */ +public class ToothAndNail extends CardImpl { + + public ToothAndNail(UUID ownerId) { + super(ownerId, 170, "Tooth and Nail", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{5}{G}{G}"); + this.expansionSetCode = "MMA"; + + this.color.setGreen(true); + + // Choose one - + // Search your library for up to two creature cards, reveal them, put them into your hand, then shuffle your library; + this.getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 2, new FilterCreatureCard()))); + // or put up to two creature cards from your hand onto the battlefield. + Mode mode = new Mode(); + mode.getEffects().add(new ToothAndNailPutCreatureOnBattlefieldEffect()); + this.getSpellAbility().getModes().addMode(mode); + + // Entwine {2} + this.addAbility(new EntwineAbility("{2}")); + } + + public ToothAndNail(final ToothAndNail card) { + super(card); + } + + @Override + public ToothAndNail copy() { + return new ToothAndNail(this); + } +} + +class ToothAndNailPutCreatureOnBattlefieldEffect extends OneShotEffect { + + public ToothAndNailPutCreatureOnBattlefieldEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Put up to two creature cards from your hand onto the battlefield"; + } + + public ToothAndNailPutCreatureOnBattlefieldEffect(final ToothAndNailPutCreatureOnBattlefieldEffect effect) { + super(effect); + } + + @Override + public ToothAndNailPutCreatureOnBattlefieldEffect copy() { + return new ToothAndNailPutCreatureOnBattlefieldEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + + TargetCardInHand target = new TargetCardInHand(0, 2, new FilterCreatureCard("creature cards")); + if (player.choose(Outcome.PutCreatureInPlay, target, source.getSourceId(), game)) { + for (UUID targetId: target.getTargets()) { + Card card = game.getCard(targetId); + if (card != null) { + card.putOntoBattlefield(game, Zone.HAND, source.getId(), source.getControllerId()); + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/TorrentOfStone.java b/Mage.Sets/src/mage/sets/modernmasters/TorrentOfStone.java new file mode 100644 index 00000000000..bc8ba0e686c --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/TorrentOfStone.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class TorrentOfStone extends mage.sets.betrayersofkamigawa.TorrentOfStone { + + public TorrentOfStone(UUID ownerId) { + super(ownerId); + this.cardNumber = 137; + this.expansionSetCode = "MMA"; + } + + public TorrentOfStone(final TorrentOfStone card) { + super(card); + } + + @Override + public TorrentOfStone copy() { + return new TorrentOfStone(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/TrompTheDomains.java b/Mage.Sets/src/mage/sets/modernmasters/TrompTheDomains.java new file mode 100644 index 00000000000..8746082ff4c --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/TrompTheDomains.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class TrompTheDomains extends mage.sets.timespiral.TrompTheDomains { + + public TrompTheDomains(UUID ownerId) { + super(ownerId); + this.cardNumber = 171; + this.expansionSetCode = "MMA"; + } + + public TrompTheDomains(final TrompTheDomains card) { + super(card); + } + + @Override + public TrompTheDomains copy() { + return new TrompTheDomains(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/TrygonPredator.java b/Mage.Sets/src/mage/sets/modernmasters/TrygonPredator.java new file mode 100644 index 00000000000..29ec4f62b1d --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/TrygonPredator.java @@ -0,0 +1,121 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.players.Player; +import mage.target.TargetPermanent; + +/** + * + * @author LevelX2 + */ +public class TrygonPredator extends CardImpl { + + public TrygonPredator(UUID ownerId) { + super(ownerId, 185, "Trygon Predator", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{G}{U}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Beast"); + + this.color.setBlue(true); + this.color.setGreen(true); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Whenever Trygon Predator deals combat damage to a player, you may destroy target artifact or enchantment that player controls. + this.addAbility(new TrygonPredatorTriggeredAbility()); + } + + public TrygonPredator(final TrygonPredator card) { + super(card); + } + + @Override + public TrygonPredator copy() { + return new TrygonPredator(this); + } +} + +class TrygonPredatorTriggeredAbility extends TriggeredAbilityImpl { + + public TrygonPredatorTriggeredAbility() { + super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true); + } + + public TrygonPredatorTriggeredAbility(final TrygonPredatorTriggeredAbility ability) { + super(ability); + } + + @Override + public TrygonPredatorTriggeredAbility copy() { + return new TrygonPredatorTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == EventType.DAMAGED_PLAYER && event.getSourceId().equals(this.sourceId) + && ((DamagedPlayerEvent) event).isCombatDamage()) { + Player player = game.getPlayer(event.getTargetId()); + if (player != null) { + FilterPermanent filter = new FilterPermanent("an artifact or enchantment controlled by " + player.getName()); + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.ENCHANTMENT))); + filter.add(new ControllerIdPredicate(event.getTargetId())); + + this.getTargets().clear(); + this.addTarget(new TargetPermanent(filter)); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, you may destroy target artifact or enchantment that player controls."; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/VedalkenShackles.java b/Mage.Sets/src/mage/sets/modernmasters/VedalkenShackles.java new file mode 100644 index 00000000000..7584f8d9eae --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/VedalkenShackles.java @@ -0,0 +1,113 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SkipUntapOptionalAbility; +import mage.abilities.condition.common.SourceTappedCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.continious.GainControlTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.ObjectPlayer; +import mage.filter.predicate.ObjectPlayerPredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class VedalkenShackles extends CardImpl { + + private static final FilterCreaturePermanent controllableCreatures = new FilterCreaturePermanent("creature with power less than or equal to the number of Islands you control"); + static { + controllableCreatures.add(new PowerIslandPredicate()); + } + + + public VedalkenShackles(UUID ownerId) { + super(ownerId, 218, "Vedalken Shackles", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{3}"); + this.expansionSetCode = "MMA"; + + // You may choose not to untap Vedalken Shackles during your untap step. + this.addAbility(new SkipUntapOptionalAbility()); + + // {2}, {tap}: Gain control of target creature with power less than or equal to the number of Islands you control for as long as Vedalken Shackles remains tapped. + ConditionalContinousEffect effect = new ConditionalContinousEffect( + new GainControlTargetEffect(Duration.Custom), SourceTappedCondition.getInstance(), + "Gain control of target creature with power less than or equal to the number of Islands you control for as long as {this} remains tapped"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent(controllableCreatures)); + this.addAbility(ability); + } + + public VedalkenShackles(final VedalkenShackles card) { + super(card); + } + + @Override + public VedalkenShackles copy() { + return new VedalkenShackles(this); + } +} + +class PowerIslandPredicate implements ObjectPlayerPredicate> { + + public static final FilterLandPermanent filter = new FilterLandPermanent("Island"); + static { + filter.add(new SubtypePredicate("Island")); + } + + @Override + public boolean apply(ObjectPlayer input, Game game) { + Permanent permanent = input.getObject(); + if (permanent != null) { + int islands = game.getBattlefield().countAll(filter, input.getPlayerId(), game); + if (permanent.getPower().getValue() <= islands) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return "creature with power less than or equal to the number of Islands you control"; + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/VerdelothTheAncient.java b/Mage.Sets/src/mage/sets/modernmasters/VerdelothTheAncient.java new file mode 100644 index 00000000000..7fcc11e8189 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/VerdelothTheAncient.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.modernmasters; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class VerdelothTheAncient extends mage.sets.invasion.VerdelothTheAncient { + + public VerdelothTheAncient(UUID ownerId) { + super(ownerId); + this.cardNumber = 172; + this.expansionSetCode = "MMA"; + } + + public VerdelothTheAncient(final VerdelothTheAncient card) { + super(card); + } + + @Override + public VerdelothTheAncient copy() { + return new VerdelothTheAncient(this); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/WarrenPilferers.java b/Mage.Sets/src/mage/sets/modernmasters/WarrenPilferers.java new file mode 100644 index 00000000000..c03290587cf --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/WarrenPilferers.java @@ -0,0 +1,113 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.GainAbilitySourceEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author LevelX2 + */ +public class WarrenPilferers extends CardImpl { + + public WarrenPilferers(UUID ownerId) { + super(ownerId, 103, "Warren Pilferers", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{B}"); + this.expansionSetCode = "MMA"; + this.subtype.add("Goblin"); + this.subtype.add("Rogue"); + + this.color.setBlack(true); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Warren Pilferers enters the battlefield, return target creature card from your graveyard to your hand. If that card is a Goblin card, Warren Pilferers gains haste until end of turn. + Ability ability = new EntersBattlefieldTriggeredAbility(new WarrenPilferersReturnEffect(), false); + ability.addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard("creature card from your graveyard"))); + this.addAbility(ability); + } + + public WarrenPilferers(final WarrenPilferers card) { + super(card); + } + + @Override + public WarrenPilferers copy() { + return new WarrenPilferers(this); + } +} + +class WarrenPilferersReturnEffect extends OneShotEffect { + + public WarrenPilferersReturnEffect() { + super(Outcome.ReturnToHand); + staticText = "return target creature card from your graveyard to your hand. If that card is a Goblin card, Warren Pilferers gains haste until end of turn"; + } + + public WarrenPilferersReturnEffect(final WarrenPilferersReturnEffect effect) { + super(effect); + } + + @Override + public WarrenPilferersReturnEffect copy() { + return new WarrenPilferersReturnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Card card = game.getCard(source.getFirstTarget()); + if (card != null) { + card.moveToZone(Zone.HAND, source.getSourceId(), game, false); + if (card.getSubtype().contains("Goblin")) { + game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), source); + } + return true; + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/WarrenWeirding.java b/Mage.Sets/src/mage/sets/modernmasters/WarrenWeirding.java new file mode 100644 index 00000000000..3f3a6111c82 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/WarrenWeirding.java @@ -0,0 +1,143 @@ +/* + * 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.modernmasters; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenTargetEffect; +import mage.abilities.effects.common.continious.GainAbilitySourceEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.Token; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetControlledPermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class WarrenWeirding extends CardImpl { + + public WarrenWeirding(UUID ownerId) { + super(ownerId, 104, "Warren Weirding", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{B}"); + this.expansionSetCode = "MMA"; + this.supertype.add("Tribal"); + this.subtype.add("Goblin"); + + this.color.setBlack(true); + + // Target player sacrifices a creature. If a Goblin is sacrificed this way, that player puts two 1/1 black Goblin Rogue creature tokens onto the battlefield, and those tokens gain haste until end of turn. + this.getSpellAbility().addEffect(new WarrenWeirdingEffect()); + this.getSpellAbility().addTarget(new TargetPlayer()); + } + + public WarrenWeirding(final WarrenWeirding card) { + super(card); + } + + @Override + public WarrenWeirding copy() { + return new WarrenWeirding(this); + } +} + +class WarrenWeirdingEffect extends OneShotEffect { + + WarrenWeirdingEffect ( ) { + super(Outcome.Sacrifice); + staticText = "Target player sacrifices a creature. If a Goblin is sacrificed this way, that player puts two 1/1 black Goblin Rogue creature tokens onto the battlefield, and those tokens gain haste until end of turn"; + } + + WarrenWeirdingEffect ( WarrenWeirdingEffect effect ) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + + FilterControlledPermanent filter = new FilterControlledPermanent("creature"); + filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(new ControllerIdPredicate(player.getId())); + TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, false); + target.setRequired(true); + + //A spell or ability could have removed the only legal target this player + //had, if thats the case this ability should fizzle. + if (target.canChoose(player.getId(), game)) { + player.choose(Outcome.Sacrifice, target, source.getSourceId(), game); + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent != null && permanent.getSubtype().contains("Goblin")) { + permanent.sacrifice(source.getSourceId(), game); + Effect effect = new CreateTokenTargetEffect(new WarrenWeirdingBlackGoblinRogueToken(), 2); + effect.setTargetPointer(new FixedTarget(player.getId())); + effect.apply(game, source); + } + return true; + } + return false; + } + + @Override + public WarrenWeirdingEffect copy() { + return new WarrenWeirdingEffect(this); + } + +} + +class WarrenWeirdingBlackGoblinRogueToken extends Token { + WarrenWeirdingBlackGoblinRogueToken() { + super("Goblin Rogue", "1/1 black Goblin Rogue creature tokens, and those tokens gain haste until end of turn"); + cardType.add(CardType.CREATURE); + color.setBlack(true); + subtype.add("Goblin"); + subtype.add("Rogue"); + power.setValue(1); + toughness.setValue(1); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); + ability.setRuleVisible(false); + this.addAbility(ability); + } +} diff --git a/Mage.Sets/src/mage/sets/modernmasters/WormHarvest.java b/Mage.Sets/src/mage/sets/modernmasters/WormHarvest.java new file mode 100644 index 00000000000..e158a312d52 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters/WormHarvest.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.modernmasters; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class WormHarvest extends mage.sets.eventide.WormHarvest { + + public WormHarvest(UUID ownerId) { + super(ownerId); + this.cardNumber = 195; + this.expansionSetCode = "MMA"; + this.rarity = Rarity.UNCOMMON; + } + + public WormHarvest(final WormHarvest card) { + super(card); + } + + @Override + public WormHarvest copy() { + return new WormHarvest(this); + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/AuntiesSnitch.java b/Mage.Sets/src/mage/sets/morningtide/AuntiesSnitch.java new file mode 100644 index 00000000000..619eb63da4b --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/AuntiesSnitch.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.morningtide; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class AuntiesSnitch extends mage.sets.modernmasters.AuntiesSnitch { + + public AuntiesSnitch(UUID ownerId) { + super(ownerId); + this.cardNumber = 57; + this.expansionSetCode = "MOR"; + this.rarity = Rarity.RARE; + } + + public AuntiesSnitch(final AuntiesSnitch card) { + super(card); + } + + @Override + public AuntiesSnitch copy() { + return new AuntiesSnitch(this); + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/CountrysideCrusher.java b/Mage.Sets/src/mage/sets/morningtide/CountrysideCrusher.java index 0b0580501b2..984db6fdc91 100644 --- a/Mage.Sets/src/mage/sets/morningtide/CountrysideCrusher.java +++ b/Mage.Sets/src/mage/sets/morningtide/CountrysideCrusher.java @@ -40,6 +40,7 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.Card; import mage.cards.CardImpl; +import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.Outcome; import mage.constants.TargetController; @@ -106,15 +107,17 @@ class CountrysideCrusherEffect extends OneShotEffect { permanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); } if (player != null && permanent != null) { + Cards cards = new CardsImpl(); while (player.getLibrary().size() > 0) { Card card = player.getLibrary().getFromTop(game); - player.revealCards(permanent.getName(), new CardsImpl(card), game); + cards.add(card); if (card.getCardType().contains(CardType.LAND)) { card.moveToZone(Zone.GRAVEYARD, source.getSourceId(), game, true); } else { break; } } + player.revealCards(permanent.getName(), cards, game); return true; } return false; diff --git a/Mage.Sets/src/mage/sets/morningtide/EarwigSquad.java b/Mage.Sets/src/mage/sets/morningtide/EarwigSquad.java new file mode 100644 index 00000000000..ebdc6e0be78 --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/EarwigSquad.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.morningtide; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class EarwigSquad extends mage.sets.modernmasters.EarwigSquad { + + public EarwigSquad(UUID ownerId) { + super(ownerId); + this.cardNumber = 60; + this.expansionSetCode = "MOR"; + } + + public EarwigSquad(final EarwigSquad card) { + super(card); + } + + @Override + public EarwigSquad copy() { + return new EarwigSquad(this); + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/LatchkeyFaerie.java b/Mage.Sets/src/mage/sets/morningtide/LatchkeyFaerie.java new file mode 100644 index 00000000000..93dbb9c7482 --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/LatchkeyFaerie.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.morningtide; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class LatchkeyFaerie extends mage.sets.modernmasters.LatchkeyFaerie { + + public LatchkeyFaerie(UUID ownerId) { + super(ownerId); + this.cardNumber = 39; + this.expansionSetCode = "MOR"; + } + + public LatchkeyFaerie(final LatchkeyFaerie card) { + super(card); + } + + @Override + public LatchkeyFaerie copy() { + return new LatchkeyFaerie(this); + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/NogginWhack.java b/Mage.Sets/src/mage/sets/morningtide/NogginWhack.java new file mode 100644 index 00000000000..c8a5be67391 --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/NogginWhack.java @@ -0,0 +1,143 @@ +/* + * 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.morningtide; + +import java.util.List; +import java.util.List; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.ProwlAbility; +import mage.cards.Card; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.TargetPlayer; + +/** + * + * @author LevelX2 + */ +public class NogginWhack extends CardImpl { + + public NogginWhack(UUID ownerId) { + super(ownerId, 70, "Noggin Whack", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{B}{B}"); + this.expansionSetCode = "MOR"; + this.supertype.add("Tribal"); + this.subtype.add("Rogue"); + + this.color.setBlack(true); + + // Prowl {1}{B} + this.addAbility(new ProwlAbility(this, "{1}{B}")); + // Target player reveals three cards from his or her hand. You choose two of them. That player discards those cards. + this.getSpellAbility().addEffect(new NogginWhackEffect()); + this.getSpellAbility().addTarget(new TargetPlayer(true)); + + } + + public NogginWhack(final NogginWhack card) { + super(card); + } + + @Override + public NogginWhack copy() { + return new NogginWhack(this); + } +} + +class NogginWhackEffect extends OneShotEffect { + + public NogginWhackEffect() { + super(Outcome.Benefit); + this.staticText = "Target player reveals three cards from his or her hand. You choose two of them. That player discards those cards"; + } + + public NogginWhackEffect(final NogginWhackEffect effect) { + super(effect); + } + + @Override + public NogginWhackEffect copy() { + return new NogginWhackEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + Card sourceCard = game.getCard(source.getSourceId()); + if (controller != null && targetPlayer != null && sourceCard != null) { + Cards cardsInHand = new CardsImpl(); + cardsInHand.addAll(targetPlayer.getHand()); + + int count = Math.min(cardsInHand.size(), 3); + + TargetCard target = new TargetCard(count, Zone.HAND, new FilterCard()); + target.setRequired(true); + Cards revealedCards = new CardsImpl(); + + if (targetPlayer.chooseTarget(Outcome.Discard, cardsInHand, target, source, game)) { + List targets = target.getTargets(); + for (UUID targetId : targets) { + Card card = game.getCard(targetId); + if (card != null) { + revealedCards.add(card); + } + } + } + + int cardsToDiscard = Math.min(revealedCards.size(), 2); + TargetCard targetInHand = new TargetCard(cardsToDiscard, cardsToDiscard, Zone.HAND, new FilterCard("card to discard")); + targetInHand.setRequired(true); + + if (!revealedCards.isEmpty()) { + targetPlayer.revealCards("Noggin Whack", revealedCards, game); + controller.chooseTarget(Outcome.Exile, revealedCards, targetInHand, source, game); + for (UUID cardId : (List) targetInHand.getTargets()) { + Card card = game.getCard(cardId); + if (card != null) { + card.moveToZone(Zone.GRAVEYARD, source.getSourceId(), game, true); + game.informPlayers(new StringBuilder(sourceCard.getName()).append(": Discarded card ").append(card.getName()).toString()); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/morningtide/WalkerOfTheGrove.java b/Mage.Sets/src/mage/sets/morningtide/WalkerOfTheGrove.java index 4fb0692805e..1f542adb0df 100644 --- a/Mage.Sets/src/mage/sets/morningtide/WalkerOfTheGrove.java +++ b/Mage.Sets/src/mage/sets/morningtide/WalkerOfTheGrove.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.EvokeAbility; import mage.cards.CardImpl; @@ -53,7 +53,7 @@ public class WalkerOfTheGrove extends CardImpl { this.toughness = new MageInt(7); // When Walker of the Grove leaves the battlefield, put a 4/4 green Elemental creature token onto the battlefield. - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WalkerOfTheGroveToken(),1))); + this.addAbility(new LeavesBattlefieldTriggeredAbility(new CreateTokenEffect(new WalkerOfTheGroveToken(),1),false)); // Evoke {4}{G} this.addAbility(new EvokeAbility(this, "{4}{G}")); } diff --git a/Mage.Sets/src/mage/sets/morningtide/WarrenWeirding.java b/Mage.Sets/src/mage/sets/morningtide/WarrenWeirding.java new file mode 100644 index 00000000000..1dfcfa4a3b1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/morningtide/WarrenWeirding.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.morningtide; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class WarrenWeirding extends mage.sets.modernmasters.WarrenWeirding { + + public WarrenWeirding(UUID ownerId) { + super(ownerId); + this.cardNumber = 82; + this.expansionSetCode = "MOR"; + this.rarity = Rarity.UNCOMMON; + } + + public WarrenWeirding(final WarrenWeirding card) { + super(card); + } + + @Override + public WarrenWeirding copy() { + return new WarrenWeirding(this); + } +} diff --git a/Mage.Sets/src/mage/sets/nemesis/BlindingAngel.java b/Mage.Sets/src/mage/sets/nemesis/BlindingAngel.java index 039550ef59b..0d2309162e7 100644 --- a/Mage.Sets/src/mage/sets/nemesis/BlindingAngel.java +++ b/Mage.Sets/src/mage/sets/nemesis/BlindingAngel.java @@ -36,11 +36,13 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.constants.TurnPhase; import mage.game.Game; import mage.game.turn.TurnMod; +import mage.players.Player; /** * @@ -80,15 +82,15 @@ class SkipNextCombatEffect extends OneShotEffect { staticText = "that player skips his or her next combat phase"; } - public SkipNextCombatEffect(SkipNextCombatEffect effect) { + public SkipNextCombatEffect(final SkipNextCombatEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { - UUID targetId = source.getFirstTarget(); - if (targetId != null) { - game.getState().getTurnMods().add(new TurnMod(targetId, TurnPhase.COMBAT, null, true)); + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null) { + game.getState().getTurnMods().add(new TurnMod(player.getId(), TurnPhase.COMBAT, null, true)); return true; } return false; @@ -96,6 +98,6 @@ class SkipNextCombatEffect extends OneShotEffect { @Override public SkipNextCombatEffect copy() { - return new SkipNextCombatEffect(); + return new SkipNextCombatEffect(this); } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/newphyrexia/ConversionChamber.java b/Mage.Sets/src/mage/sets/newphyrexia/ConversionChamber.java index 409145b31e0..af1ad6abbca 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/ConversionChamber.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/ConversionChamber.java @@ -29,23 +29,22 @@ package mage.sets.newphyrexia; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.common.ExileFromGraveCost; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterArtifactCard; import mage.game.permanent.token.GolemToken; -import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetCardInGraveyard; /** * @@ -56,10 +55,13 @@ public class ConversionChamber extends CardImpl { public ConversionChamber (UUID ownerId) { super(ownerId, 133, "Conversion Chamber", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{3}"); this.expansionSetCode = "NPH"; - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), new GenericManaCost(2)); + // {2}, {T}: Exile target artifact card from a graveyard. Put a charge counter on Conversion Chamber. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new GenericManaCost(2)); + ability.addEffect(new AddCountersSourceEffect(CounterType.CHARGE.createInstance())); + ability.addTarget(new TargetCardInGraveyard(new FilterArtifactCard("artifact card from a graveyard"))); ability.addCost(new TapSourceCost()); - ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(new FilterArtifactCard("artifact card from a graveyard")))); this.addAbility(ability); + // {2}, {T}, Remove a charge counter from Conversion Chamber: Put a 3/3 colorless Golem artifact creature token onto the battlefield. ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new GolemToken()), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); ability.addCost(new RemoveCountersSourceCost(CounterType.CHARGE.createInstance())); diff --git a/Mage.Sets/src/mage/sets/newphyrexia/LifesFinale.java b/Mage.Sets/src/mage/sets/newphyrexia/LifesFinale.java index 7792c363caf..20e3dad0276 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/LifesFinale.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/LifesFinale.java @@ -112,9 +112,9 @@ class LifesFinaleEffect extends OneShotEffect { } } } + opponent.shuffleLibrary(game); + return true; } - - opponent.shuffleLibrary(game); - return true; + return false; } } diff --git a/Mage.Sets/src/mage/sets/newphyrexia/MyrSuperion.java b/Mage.Sets/src/mage/sets/newphyrexia/MyrSuperion.java index 31868181a05..fddf8737532 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/MyrSuperion.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/MyrSuperion.java @@ -28,10 +28,12 @@ package mage.sets.newphyrexia; import java.util.UUID; +import mage.MageInt; +import mage.abilities.StaticAbility; +import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.MageInt; -import mage.cards.CardImpl; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; /** @@ -51,6 +53,7 @@ public class MyrSuperion extends CardImpl { this.toughness = new MageInt(6); // Spend only mana produced by creatures to cast Myr Superion. + this.addAbility(new MyrSuperionStaticAbility()); this.getSpellAbility().getManaCostsToPay().setSourceFilter(filter); this.getSpellAbility().getManaCosts().setSourceFilter(filter); } @@ -64,3 +67,25 @@ public class MyrSuperion extends CardImpl { return new MyrSuperion(this); } } + +class MyrSuperionStaticAbility extends StaticAbility { + + public MyrSuperionStaticAbility() { + super(Zone.STACK, null); + } + + public MyrSuperionStaticAbility(MyrSuperionStaticAbility ability) { + super(ability); + } + + @Override + public MyrSuperionStaticAbility copy() { + return new MyrSuperionStaticAbility(this); + } + + @Override + public String getRule() { + return "Spend only mana produced by creatures to cast {this}."; + } + +} diff --git a/Mage.Sets/src/mage/sets/newphyrexia/OgreMenial.java b/Mage.Sets/src/mage/sets/newphyrexia/OgreMenial.java index 28d90a28670..dc9e5b7a8b7 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/OgreMenial.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/OgreMenial.java @@ -28,15 +28,16 @@ package mage.sets.newphyrexia; 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.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.abilities.keyword.InfectAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; /** * @@ -52,7 +53,10 @@ public class OgreMenial extends CardImpl { this.color.setRed(true); this.power = new MageInt(0); this.toughness = new MageInt(4); + // Infect (This creature deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters.) + this.addAbility(InfectAbility.getInstance()); + // {R}: Ogre Menial gets +1/+0 until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}"))); } diff --git a/Mage.Sets/src/mage/sets/ninthedition/EarlyHarvest.java b/Mage.Sets/src/mage/sets/ninthedition/EarlyHarvest.java new file mode 100644 index 00000000000..00c5b8ab080 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ninthedition/EarlyHarvest.java @@ -0,0 +1,98 @@ +/* + * 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; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterLandPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; + +/** + * + * @author Plopman + */ +public class EarlyHarvest extends CardImpl { + + public EarlyHarvest(UUID ownerId) { + super(ownerId, 235, "Early Harvest", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{1}{G}{G}"); + this.expansionSetCode = "9ED"; + + this.color.setGreen(true); + + // Target player untaps all basic lands he or she controls. + this.getSpellAbility().addEffect(new UntapAllLandsTargetEffect()); + this.getSpellAbility().addTarget(new TargetPlayer()); + } + + public EarlyHarvest(final EarlyHarvest card) { + super(card); + } + + @Override + public EarlyHarvest copy() { + return new EarlyHarvest(this); + } +} + +class UntapAllLandsTargetEffect extends OneShotEffect { + + public UntapAllLandsTargetEffect() { + super(Outcome.Untap); + staticText = "Target player untaps all basic lands he or she controls"; + } + + public UntapAllLandsTargetEffect(final UntapAllLandsTargetEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source)); + if (player != null) { + for (Permanent land: game.getBattlefield().getAllActivePermanents(new FilterLandPermanent(), player.getId(), game)) { + land.untap(game); + } + return true; + } + return false; + } + + @Override + public UntapAllLandsTargetEffect copy() { + return new UntapAllLandsTargetEffect(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/odyssey/CarefulStudy.java b/Mage.Sets/src/mage/sets/odyssey/CarefulStudy.java index a4300e5440d..35a59312707 100644 --- a/Mage.Sets/src/mage/sets/odyssey/CarefulStudy.java +++ b/Mage.Sets/src/mage/sets/odyssey/CarefulStudy.java @@ -27,13 +27,11 @@ */ package mage.sets.odyssey; +import java.util.UUID; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.effects.common.DiscardControllerEffect; -import mage.abilities.effects.common.DrawCardControllerEffect; -import mage.cards.CardImpl; - -import java.util.UUID; /** * @author magenoxx_at_gmail.com @@ -47,8 +45,7 @@ public class CarefulStudy extends CardImpl { this.color.setBlue(true); // Draw two cards, then discard two cards. - this.getSpellAbility().addEffect(new DrawCardControllerEffect(2)); - this.getSpellAbility().addEffect(new DiscardControllerEffect(2)); + this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(2,2)); } public CarefulStudy(final CarefulStudy card) { diff --git a/Mage.Sets/src/mage/sets/planarchaos/FuryCharm.java b/Mage.Sets/src/mage/sets/planarchaos/FuryCharm.java new file mode 100644 index 00000000000..facc65b4451 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/FuryCharm.java @@ -0,0 +1,163 @@ +/* + * 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.Mode; +import mage.abilities.SpellAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.continious.BoostTargetEffect; +import mage.abilities.effects.common.continious.GainAbilityTargetEffect; +import mage.abilities.keyword.SuspendAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.Target; +import mage.target.common.TargetArtifactPermanent; +import mage.target.common.TargetCardInExile; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class FuryCharm extends CardImpl { + + private static final FilterCard filter = new FilterCard("suspended card"); + static { + filter.add(new CounterPredicate(CounterType.TIME)); + filter.add(new AbilityPredicate(SuspendAbility.class)); + } + + public FuryCharm(UUID ownerId) { + super(ownerId, 100, "Fury Charm", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{R}"); + this.expansionSetCode = "PLC"; + + this.color.setRed(true); + + // Choose one - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // Destroy target artifact; + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetArtifactPermanent()); + // or target creature gets +1/+1 and gains trample until end of turn; + Mode mode = new Mode(); + mode.getEffects().add(new BoostTargetEffect(1,1, Duration.EndOfTurn)); + mode.getEffects().add(new GainAbilityTargetEffect(TrampleAbility.getInstance(),Duration.EndOfTurn)); + mode.getTargets().add(new TargetCreaturePermanent()); + this.getSpellAbility().getModes().addMode(mode); + // or remove two time counters from target permanent or suspended card. + mode = new Mode(); + Choice targetChoice = new ChoiceImpl(); + targetChoice.setMessage("Choose what to target"); + targetChoice.getChoices().add("Permanent"); + targetChoice.getChoices().add("Suspended Card"); + mode.getChoices().add(targetChoice); + mode.getEffects().add(new FuryCharmRemoveCounterEffect()); + this.getSpellAbility().getModes().addMode(mode); + + + + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability instanceof SpellAbility) { + for(Effect effect :ability.getEffects()) { + if (effect instanceof FuryCharmRemoveCounterEffect) { + Choice targetChoice = ability.getChoices().get(0); + if (targetChoice.getChoice().equals("Permanent")) { + ability.addTarget(new TargetCreaturePermanent(true)); + } + if (targetChoice.getChoice().equals("Suspended Card")) { + Target target = new TargetCardInExile(1,1, filter, null, true); + target.setRequired(true); + ability.addTarget(target); + } + } + } + } + } + + public FuryCharm(final FuryCharm card) { + super(card); + } + + @Override + public FuryCharm copy() { + return new FuryCharm(this); + } +} + +class FuryCharmRemoveCounterEffect extends OneShotEffect { + + public FuryCharmRemoveCounterEffect() { + super(Outcome.Benefit); + this.staticText = "remove two time counters from target permanent or suspended card"; + } + + public FuryCharmRemoveCounterEffect(final FuryCharmRemoveCounterEffect effect) { + super(effect); + } + + @Override + public FuryCharmRemoveCounterEffect copy() { + return new FuryCharmRemoveCounterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (permanent != null) { + permanent.getCounters().removeCounter(CounterType.TIME, 2); + return true; + } + Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); + if (card != null) { + card.getCounters().removeCounter(CounterType.TIME, 2); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/HammerheimDeadeye.java b/Mage.Sets/src/mage/sets/planarchaos/HammerheimDeadeye.java new file mode 100644 index 00000000000..986f064450b --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/HammerheimDeadeye.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.EchoAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.Target; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class HammerheimDeadeye extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with flying"); + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public HammerheimDeadeye(UUID ownerId) { + super(ownerId, 101, "Hammerheim Deadeye", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{R}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Giant"); + this.subtype.add("Warrior"); + + this.color.setRed(true); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Echo {5}{R} + this.addAbility(new EchoAbility("{5}{R}")); + // When Hammerheim Deadeye enters the battlefield, destroy target creature with flying. + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); + Target target = new TargetCreaturePermanent(filter); + target.setRequired(true); + ability.addTarget(target); + this.addAbility(ability); + } + + public HammerheimDeadeye(final HammerheimDeadeye card) { + super(card); + } + + @Override + public HammerheimDeadeye copy() { + return new HammerheimDeadeye(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/RathiTrapper.java b/Mage.Sets/src/mage/sets/planarchaos/RathiTrapper.java index 7a55cb292ea..954a91b4900 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/RathiTrapper.java +++ b/Mage.Sets/src/mage/sets/planarchaos/RathiTrapper.java @@ -34,6 +34,7 @@ import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; @@ -58,6 +59,7 @@ public class RathiTrapper extends CardImpl { // {B}, {tap}: Tap target creature. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new ManaCostsImpl("{B}")); + ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/planechase/EtchedOracle.java b/Mage.Sets/src/mage/sets/planechase/EtchedOracle.java index c8344b5bf98..13fc76cb009 100644 --- a/Mage.Sets/src/mage/sets/planechase/EtchedOracle.java +++ b/Mage.Sets/src/mage/sets/planechase/EtchedOracle.java @@ -56,8 +56,8 @@ public class EtchedOracle extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(0); - // Sunburst - this.addAbility(new SunburstAbility()); + // Sunburst (This enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.) + this.addAbility(new SunburstAbility(this)); // {1}, Remove four +1/+1 counters from Etched Oracle: Target player draws three cards. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardTargetEffect(3), new ManaCostsImpl("{1}")); ability.addCost(new RemoveCountersSourceCost(CounterType.P1P1.createInstance(4))); diff --git a/Mage.Sets/src/mage/sets/planechase/FertileGround.java b/Mage.Sets/src/mage/sets/planechase/FertileGround.java new file mode 100644 index 00000000000..5668ee980ee --- /dev/null +++ b/Mage.Sets/src/mage/sets/planechase/FertileGround.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.planechase; + +import java.util.UUID; + +/** + * + * @author Plopman + */ +public class FertileGround extends mage.sets.urzassaga.FertileGround { + + public FertileGround(UUID ownerId) { + super(ownerId); + this.cardNumber = 71; + this.expansionSetCode = "HOP"; + } + + public FertileGround(final FertileGround card) { + super(card); + } + + @Override + public FertileGround copy() { + return new FertileGround(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planechase/PentadPrism.java b/Mage.Sets/src/mage/sets/planechase/PentadPrism.java index 2ec25226bcc..488a322cbb2 100644 --- a/Mage.Sets/src/mage/sets/planechase/PentadPrism.java +++ b/Mage.Sets/src/mage/sets/planechase/PentadPrism.java @@ -47,7 +47,7 @@ public class PentadPrism extends CardImpl { this.expansionSetCode = "HOP"; // Sunburst - this.addAbility(new SunburstAbility()); + this.addAbility(new SunburstAbility(this)); // Remove a charge counter from Pentad Prism: Add one mana of any color to your mana pool. this.addAbility(new AnyColorManaAbility(new RemoveCountersSourceCost(CounterType.CHARGE.createInstance(1)))); } diff --git a/Mage.Sets/src/mage/sets/planechase/SuntouchedMyr.java b/Mage.Sets/src/mage/sets/planechase/SuntouchedMyr.java index 6ca3efebcd8..5de6e02a4b3 100644 --- a/Mage.Sets/src/mage/sets/planechase/SuntouchedMyr.java +++ b/Mage.Sets/src/mage/sets/planechase/SuntouchedMyr.java @@ -48,7 +48,7 @@ public class SuntouchedMyr extends CardImpl { this.toughness = new MageInt(0); // Sunburst - this.addAbility(new SunburstAbility()); + this.addAbility(new SunburstAbility(this)); } public SuntouchedMyr(final SuntouchedMyr card) { diff --git a/Mage.Sets/src/mage/sets/planechase/ThirstForKnowledge.java b/Mage.Sets/src/mage/sets/planechase/ThirstForKnowledge.java index cc029e3339f..58307e8acb9 100644 --- a/Mage.Sets/src/mage/sets/planechase/ThirstForKnowledge.java +++ b/Mage.Sets/src/mage/sets/planechase/ThirstForKnowledge.java @@ -94,18 +94,17 @@ class ThirstforKnowledgeEffect extends OneShotEffect { filter.add(new CardTypePredicate(CardType.ARTIFACT)); if (you != null && you.getHand().count(filter, game) > 0 - && you.chooseUse(Outcome.Discard, "Do you want to discard an artifact? If you do not, you must discard 2 cards", game)) { + && you.chooseUse(Outcome.Discard, "Do you want to discard an artifact? If you don't, you must discard 2 cards", game)) { Cost cost = new DiscardTargetCost(new TargetCardInHand(filter)); - if (cost.canPay(you.getId(), you.getId(), game)) { - if (!cost.pay(source, game, you.getId(), you.getId(), false)) { - you.discard(2, source, game); + if (cost.canPay(source.getSourceId(), you.getId(), game)) { + if (cost.pay(source, game, source.getSourceId(), you.getId(), false)) { + return true; } - return true; } } - if (you != null - && you.getHand().count(filter, game) == 0) { + if (you != null) { you.discard(2, source, game); + return true; } return false; } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java b/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java index 0d65d73f69b..d1e7d5ad015 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/AngelOfSerenity.java @@ -28,11 +28,6 @@ package mage.sets.returntoravnica; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; @@ -41,6 +36,10 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; @@ -52,6 +51,7 @@ import mage.game.permanent.Permanent; import mage.target.Target; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCreaturePermanent; +import mage.util.CardUtil; /** * @@ -156,7 +156,7 @@ class AngelOfSerenityEnterEffect extends OneShotEffect { // or draw two cards, then discard two cards. mode = new Mode(); - mode.getEffects().add(new DrawCardControllerEffect(2)); - mode.getEffects().add(new DiscardControllerEffect(2)); + mode.getEffects().add(new DrawDiscardControllerEffect(2, 2)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/Thoughtflare.java b/Mage.Sets/src/mage/sets/returntoravnica/Thoughtflare.java index 54c4160b783..73e05f69a00 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/Thoughtflare.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/Thoughtflare.java @@ -28,10 +28,9 @@ package mage.sets.returntoravnica; import java.util.UUID; +import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.effects.common.DiscardControllerEffect; -import mage.abilities.effects.common.DrawCardControllerEffect; import mage.cards.CardImpl; /** @@ -47,8 +46,7 @@ public class Thoughtflare extends CardImpl { this.color.setRed(true); // Draw four cards, then discard two cards. - this.getSpellAbility().addEffect(new DrawCardControllerEffect(4)); - this.getSpellAbility().addEffect(new DiscardControllerEffect(2)); + this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(4, 2)); } public Thoughtflare(final Thoughtflare card) { diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/DeathDenied.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/DeathDenied.java index 13d82da31d3..3a3a0b578d3 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/DeathDenied.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/DeathDenied.java @@ -66,7 +66,7 @@ public class DeathDenied extends CardImpl { if (ability instanceof SpellAbility) { ability.getTargets().clear(); int xValue = ability.getManaCostsToPay().getX(); - Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard(new StringBuilder(xValue).append(xValue != 1?" creatures":"creature").toString())); + Target target = new TargetCardInYourGraveyard(xValue, new FilterCreatureCard(new StringBuilder(xValue).append(xValue != 1?" creature cards":"creature card").append(" from your graveyard").toString())); ability.addTarget(target); } } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/GenesisWave.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/GenesisWave.java index 1eadb801427..fff7c40f60e 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/GenesisWave.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/GenesisWave.java @@ -106,7 +106,7 @@ class GenesisWaveEffect extends OneShotEffect { Card card = cards.get(target1.getFirstTarget(), game); if (card != null) { cards.remove(card); - card.putOntoBattlefield(game, Zone.HAND, source.getSourceId(), source.getControllerId()); + card.putOntoBattlefield(game, Zone.PICK, source.getSourceId(), source.getControllerId()); } target1.clearChosen(); } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/KothOfTheHammer.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/KothOfTheHammer.java index 16d2ed2d2fc..1192ed8a0b0 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/KothOfTheHammer.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/KothOfTheHammer.java @@ -28,12 +28,6 @@ package mage.sets.scarsofmirrodin; -import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.*; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.Mana; import mage.abilities.Ability; @@ -51,6 +45,7 @@ import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continious.BecomesCreatureTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; +import mage.constants.*; import mage.counters.CounterType; import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; @@ -62,6 +57,8 @@ import mage.game.permanent.token.Token; import mage.target.common.TargetCreatureOrPlayer; import mage.target.common.TargetLandPermanent; +import java.util.UUID; + /** * * @author Loki, North @@ -95,7 +92,7 @@ public class KothOfTheHammer extends CardImpl { // -2: Add {R} to your mana pool for each Mountain you control. this.addAbility(new LoyaltyAbility(new DynamicManaEffect(Mana.RedMana, new PermanentsOnBattlefieldCount(filterCount)), -2)); - // -5: You get an emblem with "Mountains you control have ‘{T}: This land deals 1 damage to target creature or player.' + // -5: You get an emblem with "Mountains you control have '{T}: This land deals 1 damage to target creature or player.' this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new KothOfTheHammerEmblem()), -5)); } diff --git a/Mage.Sets/src/mage/sets/seventhedition/EarlyHarvest.java b/Mage.Sets/src/mage/sets/seventhedition/EarlyHarvest.java new file mode 100644 index 00000000000..61a9948cb44 --- /dev/null +++ b/Mage.Sets/src/mage/sets/seventhedition/EarlyHarvest.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.seventhedition; + +import java.util.UUID; + +/** + * + * @author Plopman + */ +public class EarlyHarvest extends mage.sets.ninthedition.EarlyHarvest { + + public EarlyHarvest(UUID ownerId) { + super(ownerId); + this.cardNumber = 237; + this.expansionSetCode = "7ED"; + } + + public EarlyHarvest(final EarlyHarvest card) { + super(card); + } + + @Override + public EarlyHarvest copy() { + return new EarlyHarvest(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/DemigodOfRevenge.java b/Mage.Sets/src/mage/sets/shadowmoor/DemigodOfRevenge.java new file mode 100644 index 00000000000..4f24697e34f --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/DemigodOfRevenge.java @@ -0,0 +1,145 @@ +/* + * 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.shadowmoor; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class DemigodOfRevenge extends CardImpl { + + public DemigodOfRevenge(UUID ownerId) { + super(ownerId, 183, "Demigod of Revenge", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{B/R}{B/R}{B/R}{B/R}{B/R}"); + this.expansionSetCode = "SHM"; + this.subtype.add("Spirit"); + this.subtype.add("Avatar"); + + this.color.setRed(true); + this.color.setBlack(true); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Haste + this.addAbility(HasteAbility.getInstance()); + // When you cast Demigod of Revenge, return all cards named Demigod of Revenge from your graveyard to the battlefield. + this.addAbility(new DemigodOfRevengeTriggeredAbility()); + } + + public DemigodOfRevenge(final DemigodOfRevenge card) { + super(card); + } + + @Override + public DemigodOfRevenge copy() { + return new DemigodOfRevenge(this); + } +} + +class DemigodOfRevengeTriggeredAbility extends TriggeredAbilityImpl { + + public DemigodOfRevengeTriggeredAbility() { + super(Zone.STACK, new DemigodOfRevengeReturnEffect(), false); + } + + public DemigodOfRevengeTriggeredAbility(final DemigodOfRevengeTriggeredAbility ability) { + super(ability); + } + + @Override + public DemigodOfRevengeTriggeredAbility copy() { + return new DemigodOfRevengeTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType().equals(GameEvent.EventType.SPELL_CAST) && event.getSourceId().equals(this.getSourceId())) { + return true; + } + return false; + } + + @Override + public String getRule() { + return "When you cast Demigod of Revenge, " + super.getRule(); + } +} + +class DemigodOfRevengeReturnEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard(); + static { + filter.add(new NamePredicate("Demigod of Revenge")); + } + + public DemigodOfRevengeReturnEffect() { + super(Outcome.PutCreatureInPlay); + staticText = "return all cards named Demigod of Revenge from your graveyard to the battlefield"; + } + + public DemigodOfRevengeReturnEffect(final DemigodOfRevengeReturnEffect effect) { + super(effect); + } + + @Override + public DemigodOfRevengeReturnEffect copy() { + return new DemigodOfRevengeReturnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + for (Card creature : player.getGraveyard().getCards(filter, game)) { + creature.putOntoBattlefield(game, Zone.GRAVEYARD, source.getId(), source.getControllerId()); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/FistsOfTheDemigod.java b/Mage.Sets/src/mage/sets/shadowmoor/FistsOfTheDemigod.java new file mode 100644 index 00000000000..0598b992789 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/FistsOfTheDemigod.java @@ -0,0 +1,89 @@ +/* + * 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.shadowmoor; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.WitherAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class FistsOfTheDemigod extends CardImpl { + + public FistsOfTheDemigod(UUID ownerId) { + super(ownerId, 187, "Fists of the Demigod", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{B/R}"); + this.expansionSetCode = "SHM"; + this.subtype.add("Aura"); + + this.color.setRed(true); + this.color.setBlack(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is black, it gets +1/+1 and has wither. + SimpleStaticAbility blackAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.BLACK), "As long as enchanted creature is black, it gets +1/+1")); + blackAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(WitherAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.BLACK), "and has wither")); + this.addAbility(blackAbility); + // As long as enchanted creature is red, it gets +1/+1 and has first strike. + SimpleStaticAbility redAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.RED), "As long as enchanted creature is red, it gets +1/+1")); + redAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.RED), "and has first strike")); + this.addAbility(redAbility); + } + + public FistsOfTheDemigod(final FistsOfTheDemigod card) { + super(card); + } + + @Override + public FistsOfTheDemigod copy() { + return new FistsOfTheDemigod(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/HelmOfTheGhastlord.java b/Mage.Sets/src/mage/sets/shadowmoor/HelmOfTheGhastlord.java new file mode 100644 index 00000000000..f0e24efdb8d --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/HelmOfTheGhastlord.java @@ -0,0 +1,90 @@ +/* + * 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.shadowmoor; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DiscardTargetEffect; +import mage.abilities.effects.common.DrawCardControllerEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class HelmOfTheGhastlord extends CardImpl { + + public HelmOfTheGhastlord(UUID ownerId) { + super(ownerId, 166, "Helm of the Ghastlord", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{3}{U/B}"); + this.expansionSetCode = "SHM"; + this.subtype.add("Aura"); + + this.color.setBlue(true); + this.color.setBlack(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is blue, it gets +1/+1 and has "Whenever this creature deals damage to an opponent, draw a card." + SimpleStaticAbility blueAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.BLUE), "As long as enchanted creature is blue, it gets +1/+1")); + blueAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardControllerEffect(1),false), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.BLUE), "and has \"Whenever this creature deals damage to an opponent, draw a card.\"")); + this.addAbility(blueAbility); + // As long as enchanted creature is black, it gets +1/+1 and has "Whenever this creature deals damage to an opponent, that player discards a card." + SimpleStaticAbility blackAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.BLACK), "As long as enchanted creature is black, it gets +1/+1")); + blackAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1), false, true), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.BLACK), "and has \"Whenever this creature deals damage to an opponent, that player discards a card.\"")); + this.addAbility(blackAbility); + } + + public HelmOfTheGhastlord(final HelmOfTheGhastlord card) { + super(card); + } + + @Override + public HelmOfTheGhastlord copy() { + return new HelmOfTheGhastlord(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/LeechriddenSwamp.java b/Mage.Sets/src/mage/sets/shadowmoor/LeechriddenSwamp.java index b9272bbc36f..725ce23cf42 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/LeechriddenSwamp.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/LeechriddenSwamp.java @@ -69,6 +69,7 @@ public class LeechriddenSwamp extends CardImpl { // {B}, {tap}: Each opponent loses 1 life. Activate this ability only if you control two or more black permanents. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LeechriddenSwampLoseLifeEffect(), new ManaCostsImpl("{B}")); + ability.addCost(new TapSourceCost()); ability.addCost(new ControlTwoOrMoreBlackPermanentsCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/shadowmoor/OonaQueenOfTheFae.java b/Mage.Sets/src/mage/sets/shadowmoor/OonaQueenOfTheFae.java new file mode 100644 index 00000000000..99c85b34d5a --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/OonaQueenOfTheFae.java @@ -0,0 +1,145 @@ +/* + * 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.shadowmoor; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.token.Token; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author LevelX2 + */ +public class OonaQueenOfTheFae extends CardImpl { + + public OonaQueenOfTheFae(UUID ownerId) { + super(ownerId, 172, "Oona, Queen of the Fae", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{U/B}{U/B}{U/B}"); + this.expansionSetCode = "SHM"; + this.supertype.add("Legendary"); + this.subtype.add("Faerie"); + this.subtype.add("Wizard"); + + this.color.setBlue(true); + this.color.setBlack(true); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // {X}{UB}: Choose a color. Target opponent exiles the top X cards of his or her library. For each card of the chosen color exiled this way, put a 1/1 blue and black Faerie Rogue creature token with flying onto the battlefield. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new OonaQueenOfTheFaeEffect(), new ManaCostsImpl("{X}{U/B}")); + ability.addTarget(new TargetOpponent(true)); + this.addAbility(ability); + } + + public OonaQueenOfTheFae(final OonaQueenOfTheFae card) { + super(card); + } + + @Override + public OonaQueenOfTheFae copy() { + return new OonaQueenOfTheFae(this); + } +} + +class OonaQueenOfTheFaeEffect extends OneShotEffect { + + public OonaQueenOfTheFaeEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Choose a color. Target opponent exiles the top X cards of his or her library. For each card of the chosen color exiled this way, put a 1/1 blue and black Faerie Rogue creature token with flying onto the battlefield"; + } + + public OonaQueenOfTheFaeEffect(final OonaQueenOfTheFaeEffect effect) { + super(effect); + } + + @Override + public OonaQueenOfTheFaeEffect copy() { + return new OonaQueenOfTheFaeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (controller == null || opponent == null) { + return false; + } + ChoiceColor choice = new ChoiceColor(); + controller.choose(outcome, choice, game); + if (choice.getColor() != null) { + int cardsWithColor = 0; + int cardsToExile = Math.min(opponent.getLibrary().size(), source.getManaCostsToPay().getX()); + for(int i = 0; i < cardsToExile; i++) { + Card card = opponent.getLibrary().removeFromTop(game); + if (card != null) { + if (card.getColor().contains(choice.getColor())) { + cardsWithColor++; + } + card.moveToExile(null, null, source.getSourceId(), game); + } + } + if (cardsWithColor > 0) { + new CreateTokenEffect(new OonaQueenFaerieToken(), cardsWithColor).apply(game, source); + } + game.informPlayers(new StringBuilder("Oona: ").append(cardsWithColor).append(" Token").append(cardsWithColor != 1?"s":"").append(" created").toString()); + return true; + } + return false; + } +} + +class OonaQueenFaerieToken extends Token { + OonaQueenFaerieToken() { + super("Faerie Rogue", "1/1 blue and black Faerie Rogue creature token with flying"); + cardType.add(CardType.CREATURE); + color.setBlue(true); + color.setBlack(true); + subtype.add("Faerie"); + subtype.add("Rogue"); + power = new MageInt(1); + toughness = new MageInt(1); + this.addAbility(FlyingAbility.getInstance()); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/PrisonTerm.java b/Mage.Sets/src/mage/sets/shadowmoor/PrisonTerm.java index dd51faa4559..8240f8917c7 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/PrisonTerm.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/PrisonTerm.java @@ -110,12 +110,14 @@ class PrisonTermEffect extends OneShotEffect { Player you = game.getPlayer(source.getControllerId()); Permanent opponentCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); Permanent prisonTerm = game.getPermanent(source.getSourceId()); - if (you != null - && opponentCreature != null - && prisonTerm != null - && opponentCreature.getCardType().contains(CardType.CREATURE)) { - game.getState().setValue("attachTo:" + prisonTerm.getId(), opponentCreature); - return opponentCreature.addAttachment(prisonTerm.getId(), game); + if (you != null && opponentCreature != null && prisonTerm != null) { + Permanent oldCreature = game.getPermanent(prisonTerm.getAttachedTo()); + if (oldCreature == null) { + return false; + } + if (oldCreature.removeAttachment(prisonTerm.getId(), game)) { + return opponentCreature.addAttachment(prisonTerm.getId(), game); + } } return false; } @@ -124,4 +126,4 @@ class PrisonTermEffect extends OneShotEffect { public PrisonTermEffect copy() { return new PrisonTermEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/RunesOfTheDeus.java b/Mage.Sets/src/mage/sets/shadowmoor/RunesOfTheDeus.java new file mode 100644 index 00000000000..fd088d802a8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/RunesOfTheDeus.java @@ -0,0 +1,89 @@ +/* + * 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.shadowmoor; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class RunesOfTheDeus extends CardImpl { + + public RunesOfTheDeus(UUID ownerId) { + super(ownerId, 215, "Runes of the Deus", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{4}{R/G}"); + this.expansionSetCode = "SHM"; + this.subtype.add("Aura"); + + this.color.setRed(true); + this.color.setGreen(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is red, it gets +1/+1 and has double strike. + SimpleStaticAbility redAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.RED), "As long as enchanted creature is red, it gets +1/+1")); + redAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(DoubleStrikeAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.RED), "and has double strike")); + this.addAbility(redAbility); + // As long as enchanted creature is green, it gets +1/+1 and has trample. + SimpleStaticAbility greenAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.GREEN), "As long as enchanted creature is green, it gets +1/+1")); + greenAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.GREEN), "and has trample")); + this.addAbility(greenAbility); + } + + public RunesOfTheDeus(final RunesOfTheDeus card) { + super(card); + } + + @Override + public RunesOfTheDeus copy() { + return new RunesOfTheDeus(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/ShieldOfTheOversoul.java b/Mage.Sets/src/mage/sets/shadowmoor/ShieldOfTheOversoul.java new file mode 100644 index 00000000000..2cc3a43b4d7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/ShieldOfTheOversoul.java @@ -0,0 +1,89 @@ +/* + * 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.shadowmoor; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class ShieldOfTheOversoul extends CardImpl { + + public ShieldOfTheOversoul(UUID ownerId) { + super(ownerId, 242, "Shield of the Oversoul", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{G/W}"); + this.expansionSetCode = "SHM"; + this.subtype.add("Aura"); + + this.color.setGreen(true); + this.color.setWhite(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is green, it gets +1/+1 and is indestructible. + SimpleStaticAbility greenAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.GREEN), "As long as enchanted creature is green, it gets +1/+1")); + greenAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(IndestructibleAbility.getInstance() ,AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.GREEN), "and is indestructible")); + this.addAbility(greenAbility); + // As long as enchanted creature is white, it gets +1/+1 and has flying. + SimpleStaticAbility whiteAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.WHITE), "As long as enchanted creature is white, it gets +1/+1")); + whiteAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.WHITE), "and has flying")); + this.addAbility(whiteAbility); + } + + public ShieldOfTheOversoul(final ShieldOfTheOversoul card) { + super(card); + } + + @Override + public ShieldOfTheOversoul copy() { + return new ShieldOfTheOversoul(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/SteelOfTheGodhead.java b/Mage.Sets/src/mage/sets/shadowmoor/SteelOfTheGodhead.java new file mode 100644 index 00000000000..13036e522bc --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowmoor/SteelOfTheGodhead.java @@ -0,0 +1,89 @@ +/* + * 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.shadowmoor; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedCreatureColorCondition; +import mage.abilities.decorator.ConditionalContinousEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.keyword.UnblockableAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Plopman + */ +public class SteelOfTheGodhead extends CardImpl { + + public SteelOfTheGodhead(UUID ownerId) { + super(ownerId, 150, "Steel of the Godhead", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{W/U}"); + this.expansionSetCode = "SHM"; + this.subtype.add("Aura"); + + this.color.setBlue(true); + this.color.setWhite(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // As long as enchanted creature is white, it gets +1/+1 and has lifelink. + SimpleStaticAbility whiteAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.WHITE), "As long as enchanted creature is white, it gets +1/+1")); + whiteAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(LifelinkAbility.getInstance(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.WHITE), "and has lifelink")); + this.addAbility(whiteAbility); + // As long as enchanted creature is blue, it gets +1/+1 and is unblockable. + SimpleStaticAbility blueAbility = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinousEffect(new BoostEnchantedEffect(1, 1), new EnchantedCreatureColorCondition(ObjectColor.BLUE), "As long as enchanted creature is blue, it gets +1/+1")); + blueAbility.addEffect(new ConditionalContinousEffect(new GainAbilityAttachedEffect(new UnblockableAbility(), AttachmentType.AURA), new EnchantedCreatureColorCondition(ObjectColor.BLUE), "and is unblockable")); + this.addAbility(blueAbility); + } + + public SteelOfTheGodhead(final SteelOfTheGodhead card) { + super(card); + } + + @Override + public SteelOfTheGodhead copy() { + return new SteelOfTheGodhead(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shardsofalara/BranchingBolt.java b/Mage.Sets/src/mage/sets/shardsofalara/BranchingBolt.java index 78275104c5f..49d3b615043 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/BranchingBolt.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/BranchingBolt.java @@ -65,7 +65,10 @@ public class BranchingBolt extends CardImpl { this.color.setRed(true); this.color.setGreen(true); - // Choose one or both - Branching Bolt deals 3 damage to target creature with flying; + // Choose one or both - + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(2); + // Branching Bolt deals 3 damage to target creature with flying; this.getSpellAbility().addEffect(new DamageTargetEffect(3)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterFlying)); // or Branching Bolt deals 3 damage to target creature without flying. @@ -73,12 +76,6 @@ public class BranchingBolt extends CardImpl { mode.getEffects().add(new DamageTargetEffect(3)); mode.getTargets().add(new TargetCreaturePermanent(filterNotFlying)); this.getSpellAbility().addMode(mode); - // both - mode = new Mode(); - mode.getEffects().add(new DamageTargetEffect(3)); - mode.getTargets().add(new TargetCreaturePermanent(filterFlying)); - mode.getTargets().add(new TargetCreaturePermanent(filterNotFlying)); - this.getSpellAbility().addMode(mode); } public BranchingBolt(final BranchingBolt card) { diff --git a/Mage.Sets/src/mage/sets/shardsofalara/RelicOfProgenitus.java b/Mage.Sets/src/mage/sets/shardsofalara/RelicOfProgenitus.java index b0d02eb39c9..7334686a4ce 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/RelicOfProgenitus.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/RelicOfProgenitus.java @@ -36,6 +36,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardControllerEffect; import mage.cards.Card; @@ -62,7 +63,8 @@ public class RelicOfProgenitus extends CardImpl { firstAbility.addTarget(new TargetPlayer()); this.addAbility(firstAbility); // {1}, Exile Relic of Progenitus: Exile all cards from all graveyards. Draw a card. - Ability secondAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RelicOfProgenitusEffect2(), new SacrificeSourceCost()); + Ability secondAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RelicOfProgenitusEffect2(),new GenericManaCost(1)); + secondAbility.addCost(new SacrificeSourceCost()); secondAbility.addEffect(new DrawCardControllerEffect(1)); this.addAbility(secondAbility); diff --git a/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java b/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java new file mode 100644 index 00000000000..a700a0d2f19 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java @@ -0,0 +1,155 @@ +/* + * 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.shardsofalara; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.LeavesBattlefieldTriggeredAbility; +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.constants.Zone; +import mage.filter.common.FilterNonlandCard; +import mage.game.ExileZone; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetOpponent; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class TidehollowSculler extends CardImpl { + + public TidehollowSculler(UUID ownerId) { + super(ownerId, 202, "Tidehollow Sculler", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{W}{B}"); + this.expansionSetCode = "ALA"; + this.subtype.add("Zombie"); + + this.color.setBlack(true); + this.color.setWhite(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Tidehollow Sculler enters the battlefield, target opponent reveals his or her hand and you choose a nonland card from it. Exile that card. + Ability ability = new EntersBattlefieldTriggeredAbility(new TidehollowScullerExileEffect(), false); + ability.addTarget(new TargetOpponent(true)); + this.addAbility(ability); + + + // When Tidehollow Sculler leaves the battlefield, return the exiled card to its owner's hand. + this.addAbility(new LeavesBattlefieldTriggeredAbility(new TidehollowScullerLeaveEffect(), false )); + } + + public TidehollowSculler(final TidehollowSculler card) { + super(card); + } + + @Override + public TidehollowSculler copy() { + return new TidehollowSculler(this); + } +} + +class TidehollowScullerExileEffect extends OneShotEffect { + + public TidehollowScullerExileEffect() { + super(Outcome.Exile); + this.staticText = "target opponent reveals his or her hand and you choose a nonland card from it. Exile that card"; + } + + public TidehollowScullerExileEffect(final TidehollowScullerExileEffect effect) { + super(effect); + } + + @Override + public TidehollowScullerExileEffect copy() { + return new TidehollowScullerExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + if (player != null && targetPlayer != null) { + targetPlayer.revealCards("Tidehollow Sculler", targetPlayer.getHand(), game); + + TargetCard target = new TargetCard(Zone.PICK, new FilterNonlandCard("nonland card to exile")); + target.setRequired(true); + if (player.choose(Outcome.Exile, targetPlayer.getHand(), target, game)) { + Card card = targetPlayer.getHand().get(target.getFirstTarget(), game); + if (card != null) { + card.moveToExile(CardUtil.getCardExileZoneId(game, source), "Tidehollow Sculler", source.getSourceId(), game); + } + } + + return true; + } + return false; + } + + +} + +class TidehollowScullerLeaveEffect extends OneShotEffect { + + public TidehollowScullerLeaveEffect() { + super(Outcome.ReturnToHand); + this.staticText = "return the exiled card to its owner's hand"; + } + + public TidehollowScullerLeaveEffect(final TidehollowScullerLeaveEffect effect) { + super(effect); + } + + @Override + public TidehollowScullerLeaveEffect copy() { + return new TidehollowScullerLeaveEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + ExileZone exZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); + if (exZone != null) { + for (Card card : exZone.getCards(game)) { + if (card != null) { + card.moveToZone(Zone.HAND, source.getId(), game, false); + } + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/sixthedition/EarlyHarvest.java b/Mage.Sets/src/mage/sets/sixthedition/EarlyHarvest.java new file mode 100644 index 00000000000..a6da55f486e --- /dev/null +++ b/Mage.Sets/src/mage/sets/sixthedition/EarlyHarvest.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.sixthedition; + +import java.util.UUID; + +/** + * + * @author Plopman + */ +public class EarlyHarvest extends mage.sets.ninthedition.EarlyHarvest { + + public EarlyHarvest(UUID ownerId) { + super(ownerId); + this.cardNumber = 222; + this.expansionSetCode = "6ED"; + } + + public EarlyHarvest(final EarlyHarvest card) { + super(card); + } + + @Override + public EarlyHarvest copy() { + return new EarlyHarvest(this); + } +} diff --git a/Mage.Sets/src/mage/sets/tempest/EmmessiTome.java b/Mage.Sets/src/mage/sets/tempest/EmmessiTome.java new file mode 100644 index 00000000000..0584dbca8a9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tempest/EmmessiTome.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.tempest; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class EmmessiTome extends CardImpl { + + public EmmessiTome(UUID ownerId) { + super(ownerId, 274, "Emmessi Tome", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "TMP"; + + // {5}, {tap}: Draw two cards, then discard a card. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawDiscardControllerEffect(2,1), new ManaCostsImpl("{5}")); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public EmmessiTome(final EmmessiTome card) { + super(card); + } + + @Override + public EmmessiTome copy() { + return new EmmessiTome(this); + } +} diff --git a/Mage.Sets/src/mage/sets/tenth/Sift.java b/Mage.Sets/src/mage/sets/tenth/Sift.java index 86655ccb4f3..5a6f4fa78fb 100644 --- a/Mage.Sets/src/mage/sets/tenth/Sift.java +++ b/Mage.Sets/src/mage/sets/tenth/Sift.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.constants.CardType; import mage.constants.Rarity; import mage.abilities.effects.common.DiscardControllerEffect; -import mage.abilities.effects.common.DrawCardControllerEffect; +import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.cards.CardImpl; /** @@ -47,8 +47,7 @@ public class Sift extends CardImpl { this.color.setBlue(true); // Draw three cards, then discard a card. - this.getSpellAbility().addEffect(new DrawCardControllerEffect(3)); - this.getSpellAbility().addEffect(new DiscardControllerEffect(1)); + this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(3,1)); } public Sift(final Sift card) { diff --git a/Mage.Sets/src/mage/sets/tenth/SqueeGoblinNabob.java b/Mage.Sets/src/mage/sets/tenth/SqueeGoblinNabob.java new file mode 100644 index 00000000000..69651d5dbf1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tenth/SqueeGoblinNabob.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.tenth; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author LevelX2 + */ +public class SqueeGoblinNabob extends CardImpl { + + public SqueeGoblinNabob(UUID ownerId) { + super(ownerId, 239, "Squee, Goblin Nabob", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "10E"; + this.supertype.add("Legendary"); + this.subtype.add("Goblin"); + + this.color.setRed(true); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // At the beginning of your upkeep, you may return Squee, Goblin Nabob from your graveyard to your hand. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, new ReturnToHandSourceEffect(), TargetController.YOU, true)); + } + + public SqueeGoblinNabob(final SqueeGoblinNabob card) { + super(card); + } + + @Override + public SqueeGoblinNabob copy() { + return new SqueeGoblinNabob(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timeshifted/VerdelothTheAncient.java b/Mage.Sets/src/mage/sets/timeshifted/VerdelothTheAncient.java new file mode 100644 index 00000000000..60183eb6528 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timeshifted/VerdelothTheAncient.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.timeshifted; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class VerdelothTheAncient extends mage.sets.invasion.VerdelothTheAncient { + + public VerdelothTheAncient(UUID ownerId) { + super(ownerId); + this.cardNumber = 88; + this.expansionSetCode = "TSB"; + this.rarity = Rarity.SPECIAL; + } + + public VerdelothTheAncient(final VerdelothTheAncient card) { + super(card); + } + + @Override + public VerdelothTheAncient copy() { + return new VerdelothTheAncient(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/AngelsGrace.java b/Mage.Sets/src/mage/sets/timespiral/AngelsGrace.java new file mode 100644 index 00000000000..3600a04a191 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/AngelsGrace.java @@ -0,0 +1,150 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timespiral; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.keyword.SplitSecondAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class AngelsGrace extends CardImpl { + + public AngelsGrace(UUID ownerId) { + super(ownerId, 3, "Angel's Grace", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{W}"); + this.expansionSetCode = "TSP"; + + this.color.setWhite(true); + + // Split second + this.addAbility(SplitSecondAbility.getInstance()); + + // You can't lose the game this turn and your opponents can't win the game this turn. Until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead. + this.getSpellAbility().addEffect(new AngelsGraceEffect()); + this.getSpellAbility().addEffect(new AngelsGraceReplacementEffect()); + } + + public AngelsGrace(final AngelsGrace card) { + super(card); + } + + @Override + public AngelsGrace copy() { + return new AngelsGrace(this); + } +} + +class AngelsGraceEffect extends ReplacementEffectImpl { + + public AngelsGraceEffect() { + super(Duration.EndOfTurn, Outcome.Benefit); + staticText = "You can't lose the game this turn and your opponents can't win the game this turn"; + } + + public AngelsGraceEffect(final AngelsGraceEffect effect) { + super(effect); + } + + @Override + public AngelsGraceEffect copy() { + return new AngelsGraceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if ((event.getType() == EventType.WINS && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) || + (event.getType() == EventType.LOSES && event.getPlayerId().equals(source.getControllerId()))) { + return true; + } + return false; + } + +} + +class AngelsGraceReplacementEffect extends ReplacementEffectImpl { + + public AngelsGraceReplacementEffect() { + super(Duration.EndOfTurn, Outcome.Benefit); + staticText = "Until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead"; + } + + public AngelsGraceReplacementEffect(final AngelsGraceReplacementEffect effect) { + super(effect); + } + + @Override + public AngelsGraceReplacementEffect copy() { + return new AngelsGraceReplacementEffect(this); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType().equals(GameEvent.EventType.DAMAGE_CAUSES_LIFE_LOSS) + && event.getPlayerId().equals(source.getControllerId())) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null + && (controller.getLife() - event.getAmount()) < 1 ) { + event.setAmount(controller.getLife() - 1); + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/timespiral/CarefulConsideration.java b/Mage.Sets/src/mage/sets/timespiral/CarefulConsideration.java new file mode 100644 index 00000000000..9450964a645 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/CarefulConsideration.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.timespiral; + +import java.util.UUID; +import mage.abilities.condition.common.MyMainPhaseCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DrawDiscardTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.TargetPlayer; + +/** + * + * @author LevelX2 + */ +public class CarefulConsideration extends CardImpl { + + public CarefulConsideration(UUID ownerId) { + super(ownerId, 52, "Careful Consideration", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{U}{U}"); + this.expansionSetCode = "TSP"; + + this.color.setBlue(true); + + // Target player draws four cards, then discards three cards. If you cast this spell during your main phase, instead that player draws four cards, then discards two cards. + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new DrawDiscardTargetEffect(4,2), + new DrawDiscardTargetEffect(4,3), + MyMainPhaseCondition.getInstance(), + "Target player draws four cards, then discards three cards. If you cast this spell during your main phase, instead that player draws four cards, then discards two cards")); + this.getSpellAbility().addTarget(new TargetPlayer(true)); + } + + public CarefulConsideration(final CarefulConsideration card) { + super(card); + } + + @Override + public CarefulConsideration copy() { + return new CarefulConsideration(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/GreaterGargadon.java b/Mage.Sets/src/mage/sets/timespiral/GreaterGargadon.java index b02a8c7f3db..cdf65622ee6 100644 --- a/Mage.Sets/src/mage/sets/timespiral/GreaterGargadon.java +++ b/Mage.Sets/src/mage/sets/timespiral/GreaterGargadon.java @@ -114,6 +114,6 @@ class GreaterGargadonAbility extends ActivatedAbilityImpl { // Echo {1}{R} this.addAbility(new EchoAbility("{1}{R}")); // When Mogg War Marshal enters the battlefield or dies, put a 1/1 red Goblin creature token onto the battlefield. - Ability enterAbility = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new GoblinToken(), 1), false); - this.addAbility(enterAbility); - Ability diesAbility = new DiesTriggeredAbility(new CreateTokenEffect(new GoblinToken(), 1), false); - this.addAbility(diesAbility); + this.addAbility(new MoggWarMarshallTriggeredAbility()); } public MoggWarMarshal(final MoggWarMarshal card) { @@ -73,3 +73,39 @@ public class MoggWarMarshal extends CardImpl { return new MoggWarMarshal(this); } } + +class MoggWarMarshallTriggeredAbility extends TriggeredAbilityImpl { + + public MoggWarMarshallTriggeredAbility() { + super(Zone.BATTLEFIELD, new CreateTokenEffect(new GoblinToken(), 1), false); + } + + public MoggWarMarshallTriggeredAbility(final MoggWarMarshallTriggeredAbility ability) { + super(ability); + } + + @Override + public MoggWarMarshallTriggeredAbility copy() { + return new MoggWarMarshallTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD + && event.getTargetId().equals(getSourceId())) { + return true; + } + if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { + ZoneChangeEvent zEvent = (ZoneChangeEvent)event; + if (zEvent.getFromZone().equals(Zone.BATTLEFIELD) && zEvent.getToZone().equals(Zone.GRAVEYARD)) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "When Mogg War Marshal enters the battlefield or dies, " + super.getRule(); + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/PardicDragon.java b/Mage.Sets/src/mage/sets/timespiral/PardicDragon.java new file mode 100644 index 00000000000..40838cbe2fa --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/PardicDragon.java @@ -0,0 +1,124 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timespiral; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.OpponentCastsSpellTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.common.SuspendedCondition; +import mage.abilities.costs.mana.ColoredManaCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.SuspendAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class PardicDragon extends CardImpl { + + public PardicDragon(UUID ownerId) { + super(ownerId, 173, "Pardic Dragon", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); + this.expansionSetCode = "TSP"; + this.subtype.add("Dragon"); + + this.color.setRed(true); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // {R}: Pardic Dragon gets +1/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ColoredManaCost(ColoredManaSymbol.R))); + // Suspend 2-{R}{R} + this.addAbility(new SuspendAbility(2, new ManaCostsImpl("{R}{R}"), this, true)); + // Whenever an opponent casts a spell, if Pardic Dragon is suspended, that player may put a time counter on Pardic Dragon. + this.addAbility(new ConditionalTriggeredAbility( + new OpponentCastsSpellTriggeredAbility(Zone.EXILED, new PardicDragonEffect(), new FilterCard(), false), + SuspendedCondition.getInstance(), + "Whenever an opponent casts a spell, if {this} is suspended, that player may put a time counter on Pardic Dragon." + )); + + } + + public PardicDragon(final PardicDragon card) { + super(card); + } + + @Override + public PardicDragon copy() { + return new PardicDragon(this); + } +} + +class PardicDragonEffect extends OneShotEffect { + + public PardicDragonEffect() { + super(Outcome.Benefit); + this.staticText = "that player may put a time counter on Pardic Dragon"; + } + + public PardicDragonEffect(final PardicDragonEffect effect) { + super(effect); + } + + @Override + public PardicDragonEffect copy() { + return new PardicDragonEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + Card sourceCard = game.getCard(source.getSourceId()); + if (opponent != null && sourceCard != null) { + if (opponent.chooseUse(outcome, new StringBuilder("Put a time counter on ").append(sourceCard.getName()).append("?").toString(), game)) { + sourceCard.addCounters(CounterType.TIME.createInstance(), game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/Phthisis.java b/Mage.Sets/src/mage/sets/timespiral/Phthisis.java new file mode 100644 index 00000000000..deedf7444a9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/Phthisis.java @@ -0,0 +1,105 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timespiral; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.SuspendAbility; +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; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class Phthisis extends CardImpl { + + public Phthisis(UUID ownerId) { + super(ownerId, 122, "Phthisis", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{B}{B}{B}{B}"); + this.expansionSetCode = "TSP"; + + this.color.setBlack(true); + + // Destroy target creature. Its controller loses life equal to its power plus its toughness. + this.getSpellAbility().addEffect(new PhthisisEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(true)); + + // Suspend 5-{1}{B} + this.addAbility(new SuspendAbility(5, new ManaCostsImpl("{1}{B}"), this)); + } + + public Phthisis(final Phthisis card) { + super(card); + } + + @Override + public Phthisis copy() { + return new Phthisis(this); + } +} + +class PhthisisEffect extends OneShotEffect { + + public PhthisisEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "Destroy target creature. Its controller loses life equal to its power plus its toughness"; + } + + public PhthisisEffect(final PhthisisEffect effect) { + super(effect); + } + + @Override + public PhthisisEffect copy() { + return new PhthisisEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent creature = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (creature != null) { + Player controller = game.getPlayer(creature.getControllerId()); + if (controller != null) { + int lifeLoss = creature.getPower().getValue() + creature.getToughness().getValue(); + creature.destroy(source.getSourceId(), game, false); + // the life loss happens also if the creature is indestructible or regenerated (legal targets) + controller.loseLife(lifeLoss, game); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/SuddenShock.java b/Mage.Sets/src/mage/sets/timespiral/SuddenShock.java new file mode 100644 index 00000000000..899a2c50527 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/SuddenShock.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.timespiral; + +import java.util.UUID; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.SplitSecondAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LevelX2 + */ +public class SuddenShock extends CardImpl { + + public SuddenShock(UUID ownerId) { + super(ownerId, 179, "Sudden Shock", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{1}{R}"); + this.expansionSetCode = "TSP"; + + this.color.setRed(true); + + // Split second + this.addAbility(SplitSecondAbility.getInstance()); + // Sudden Shock deals 2 damage to target creature or player. + this.getSpellAbility().addEffect(new DamageTargetEffect(2, true)); + this.getSpellAbility().addTarget(new TargetCreatureOrPlayer(true)); + } + + public SuddenShock(final SuddenShock card) { + super(card); + } + + @Override + public SuddenShock copy() { + return new SuddenShock(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/TrompTheDomains.java b/Mage.Sets/src/mage/sets/timespiral/TrompTheDomains.java new file mode 100644 index 00000000000..329d08a2d56 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/TrompTheDomains.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.timespiral; + +import java.util.UUID; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.DomainValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continious.BoostControlledEffect; +import mage.abilities.effects.common.continious.GainAbilityControlledEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class TrompTheDomains extends CardImpl { + + public TrompTheDomains(UUID ownerId) { + super(ownerId, 230, "Tromp the Domains", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{5}{G}"); + this.expansionSetCode = "TSP"; + + this.color.setGreen(true); + + // Domain - Until end of turn, creatures you control gain trample and get +1/+1 for each basic land type among lands you control. + Effect effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); + effect.setText("Domain - Until end of turn, creatures you control gain Trample"); + this.getSpellAbility().addEffect(effect); + DynamicValue domain = new DomainValue(); + effect = new BoostControlledEffect(domain, domain, Duration.EndOfTurn, new FilterCreaturePermanent(), false); + effect.setText(" and get +1/+1 for each basic land type among lands you control"); + this.getSpellAbility().addEffect(effect); + + } + + public TrompTheDomains(final TrompTheDomains card) { + super(card); + } + + @Override + public TrompTheDomains copy() { + return new TrompTheDomains(this); + } +} diff --git a/Mage.Sets/src/mage/sets/urzaslegacy/FranticSearch.java b/Mage.Sets/src/mage/sets/urzaslegacy/FranticSearch.java index 78225e1f969..97705ef069e 100644 --- a/Mage.Sets/src/mage/sets/urzaslegacy/FranticSearch.java +++ b/Mage.Sets/src/mage/sets/urzaslegacy/FranticSearch.java @@ -28,10 +28,9 @@ package mage.sets.urzaslegacy; import java.util.UUID; +import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.constants.CardType; import mage.constants.Rarity; -import mage.abilities.effects.common.DiscardControllerEffect; -import mage.abilities.effects.common.DrawCardControllerEffect; import mage.abilities.effects.common.UntapLandsEffect; import mage.cards.CardImpl; @@ -48,8 +47,7 @@ public class FranticSearch extends CardImpl { this.color.setBlue(true); // Draw two cards, then discard two cards. Untap up to three lands. - this.getSpellAbility().addEffect(new DrawCardControllerEffect(2)); - this.getSpellAbility().addEffect(new DiscardControllerEffect(2)); + this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(2, 2)); this.getSpellAbility().addEffect(new UntapLandsEffect(3)); } diff --git a/Mage.Sets/src/mage/sets/urzassaga/Catalog.java b/Mage.Sets/src/mage/sets/urzassaga/Catalog.java index 89e3830c460..2f1d132b2cd 100644 --- a/Mage.Sets/src/mage/sets/urzassaga/Catalog.java +++ b/Mage.Sets/src/mage/sets/urzassaga/Catalog.java @@ -33,6 +33,7 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.players.Player; @@ -49,7 +50,7 @@ public class Catalog extends CardImpl { this.color.setBlue(true); // Draw two cards, then discard a card. - this.getSpellAbility().addEffect(new CatalogEffect()); + this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(2,1)); } public Catalog(final Catalog card) { @@ -61,31 +62,3 @@ public class Catalog extends CardImpl { return new Catalog(this); } } - -class CatalogEffect extends OneShotEffect { - - public CatalogEffect() { - super(Outcome.DrawCard); - this.staticText = "Draw two cards, then discard a card"; - } - - public CatalogEffect(final CatalogEffect effect) { - super(effect); - } - - @Override - public CatalogEffect copy() { - return new CatalogEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - player.drawCards(2, game); - player.discard(1, source, game); - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/urzassaga/FertileGround.java b/Mage.Sets/src/mage/sets/urzassaga/FertileGround.java new file mode 100644 index 00000000000..d7d5290e76a --- /dev/null +++ b/Mage.Sets/src/mage/sets/urzassaga/FertileGround.java @@ -0,0 +1,113 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.urzassaga; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.common.AddManaOfAnyColorEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.mana.TriggeredManaAbility; +import mage.cards.CardImpl; +import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author Plopman + */ +public class FertileGround extends CardImpl { + + public FertileGround(UUID ownerId) { + super(ownerId, 252, "Fertile Ground", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + this.expansionSetCode = "USG"; + this.subtype.add("Aura"); + + this.color.setGreen(true); + + // Enchant land + TargetPermanent auraTarget = new TargetLandPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Whenever enchanted land is tapped for mana, its controller adds one mana of any color to his or her mana pool. + this.addAbility(new FertileGroundTriggeredAbility()); + } + + public FertileGround(final FertileGround card) { + super(card); + } + + @Override + public FertileGround copy() { + return new FertileGround(this); + } +} + +class FertileGroundTriggeredAbility extends TriggeredManaAbility { + + + public FertileGroundTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect()); + this.addChoice(new ChoiceColor()); + } + + public FertileGroundTriggeredAbility(FertileGroundTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent enchantment = game.getPermanent(this.getSourceId()); + if(event.getType() == GameEvent.EventType.TAPPED_FOR_MANA){ + if (enchantment != null && event.getSourceId().equals(enchantment.getAttachedTo())) { + return true; + } + } + return false; + } + + @Override + public FertileGroundTriggeredAbility copy() { + return new FertileGroundTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever enchanted land is tapped for mana, its controller adds one mana of any color to his or her mana pool"; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/worldwake/ChainReaction.java b/Mage.Sets/src/mage/sets/worldwake/ChainReaction.java index a205f8f5530..c9cdc58679b 100644 --- a/Mage.Sets/src/mage/sets/worldwake/ChainReaction.java +++ b/Mage.Sets/src/mage/sets/worldwake/ChainReaction.java @@ -47,6 +47,7 @@ public class ChainReaction extends CardImpl { this.color.setRed(true); + // Chain Reaction deals X damage to each creature, where X is the number of creatures on the battlefield. this.getSpellAbility().addEffect(new DamageAllEffect(new PermanentsOnBattlefieldCount(new FilterCreaturePermanent()), new FilterCreaturePermanent())); } diff --git a/Mage.Sets/src/mage/sets/zendikar/BalaGedThief.java b/Mage.Sets/src/mage/sets/zendikar/BalaGedThief.java index 407148ade61..52815a1318f 100644 --- a/Mage.Sets/src/mage/sets/zendikar/BalaGedThief.java +++ b/Mage.Sets/src/mage/sets/zendikar/BalaGedThief.java @@ -152,7 +152,7 @@ class BalaGedThiefEffect extends OneShotEffect { Card card = revealedCards.get(targetInHand.getFirstTarget(), game); if (card != null) { targetPlayer.discard(card, source, game); - game.informPlayers(targetPlayer + "discarded " + card.getName()); + game.informPlayers(new StringBuilder("Bala Ged Thief: ").append(targetPlayer.getName()).append(" discarded ").append(card.getName()).toString()); } } return true; diff --git a/Mage.Sets/src/mage/sets/zendikar/MoldShambler.java b/Mage.Sets/src/mage/sets/zendikar/MoldShambler.java index 052ece5cedb..d623ff2dd9c 100644 --- a/Mage.Sets/src/mage/sets/zendikar/MoldShambler.java +++ b/Mage.Sets/src/mage/sets/zendikar/MoldShambler.java @@ -40,6 +40,7 @@ import mage.cards.CardImpl; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.Target; import mage.target.TargetPermanent; /** @@ -69,7 +70,9 @@ public class MoldShambler extends CardImpl { // When Mold Shambler enters the battlefield, if it was kicked, destroy target noncreature permanent. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); - ability.addTarget(new TargetPermanent(filter)); + Target target = new TargetPermanent(filter); + target.setRequired(true); + ability.addTarget(target); this.addAbility(new ConditionalTriggeredAbility(ability, KickedCondition.getInstance(), "When {this} enters the battlefield, if it was kicked, destroy target noncreature permanent.")); } diff --git a/Mage.Sets/src/mage/sets/zendikar/QuestForTheGemblades.java b/Mage.Sets/src/mage/sets/zendikar/QuestForTheGemblades.java index d3d4a6522bc..9159cb8ba21 100644 --- a/Mage.Sets/src/mage/sets/zendikar/QuestForTheGemblades.java +++ b/Mage.Sets/src/mage/sets/zendikar/QuestForTheGemblades.java @@ -28,9 +28,6 @@ package mage.sets.zendikar; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveCountersSourceCost; @@ -38,10 +35,14 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.events.DamagedCreatureEvent; import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** @@ -94,9 +95,15 @@ class QuestForTheGembladesTriggeredAbility extends TriggeredAbilityImpl> implements Ability { @Override public boolean activate(Game game, boolean noMana) { - // 20110204 - 700.2 + /* 20130201 - 601.2b + * If the spell is modal the player announces the mode choice (see rule 700.2). + */ if (!modes.choose(game, this)) { return false; } - //20100716 - 601.2b + + /* 20130201 - 601.2b + * If the player wishes to splice any cards onto the spell (see rule 702.45), he + * or she reveals those cards in his or her hand. + */ + if (this.abilityType.equals(AbilityType.SPELL)) { + game.getContinuousEffects().applySpliceEffects(this, game); + } + + Card card = game.getCard(sourceId); if (card != null) { card.adjustChoices(this, game); } - if (getChoices().size() > 0 && getChoices().choose(game, this) == false) { - logger.debug("activate failed - choice"); - return false; + for (UUID modeId :this.getModes().getSelectedModes()) { + this.getModes().setMode(this.getModes().get(modeId)); + if (getChoices().size() > 0 && getChoices().choose(game, this) == false) { + logger.debug("activate failed - choice"); + return false; + } } - // 20121001 - 601.2b + // 20130201 - 601.2b // If the spell has alternative or additional costs that will be paid as it's being cast such // as buyback, kicker, or convoke costs (see rules 117.8 and 117.9), the player announces his // or her intentions to pay any or all of those costs (see rule 601.2e). @@ -193,38 +209,43 @@ public abstract class AbilityImpl> implements Ability { } } } + // 20121001 - 601.2b // If the spell has a variable cost that will be paid as it's being cast (such as an {X} in // its mana cost; see rule 107.3), the player announces the value of that variable. VariableManaCost variableManaCost = handleXCosts(game, noMana); - //20121001 - 601.2c - // 601.2c The player announces his or her choice of an appropriate player, object, or zone for - // each target the spell requires. A spell may require some targets only if an alternative or - // additional cost (such as a buyback or kicker cost), or a particular mode, was chosen for it; - // otherwise, the spell is cast as though it did not require those targets. If the spell has a - // variable number of targets, the player announces how many targets he or she will choose before - // he or she announces those targets. The same target can't be chosen multiple times for any one - // instance of the word "target" on the spell. However, if the spell uses the word "target" in - // multiple places, the same object, player, or zone can be chosen once for each instance of the - // word "target" (as long as it fits the targeting criteria). If any effects say that an object - // or player must be chosen as a target, the player chooses targets so that he or she obeys the - // maximum possible number of such effects without violating any rules or effects that say that - // an object or player can't be chosen as a target. The chosen players, objects, and/or zones - // each become a target of that spell. (Any abilities that trigger when those players, objects, - // and/or zones become the target of a spell trigger at this point; they'll wait to be put on - // the stack until the spell has finished being cast.) - if (card != null) { - card.adjustTargets(this, game); - } - if (getTargets().size() > 0 && getTargets().chooseTargets(getEffects().get(0).getOutcome(), this.controllerId, this, game) == false) { - if (variableManaCost != null) { - game.informPlayers(new StringBuilder(card.getName()).append(": no valid targets with this value of X").toString()); - } else { - logger.debug("activate failed - target"); + for (UUID modeId :this.getModes().getSelectedModes()) { + this.getModes().setMode(this.getModes().get(modeId)); + //20121001 - 601.2c + // 601.2c The player announces his or her choice of an appropriate player, object, or zone for + // each target the spell requires. A spell may require some targets only if an alternative or + // additional cost (such as a buyback or kicker cost), or a particular mode, was chosen for it; + // otherwise, the spell is cast as though it did not require those targets. If the spell has a + // variable number of targets, the player announces how many targets he or she will choose before + // he or she announces those targets. The same target can't be chosen multiple times for any one + // instance of the word "target" on the spell. However, if the spell uses the word "target" in + // multiple places, the same object, player, or zone can be chosen once for each instance of the + // word "target" (as long as it fits the targeting criteria). If any effects say that an object + // or player must be chosen as a target, the player chooses targets so that he or she obeys the + // maximum possible number of such effects without violating any rules or effects that say that + // an object or player can't be chosen as a target. The chosen players, objects, and/or zones + // each become a target of that spell. (Any abilities that trigger when those players, objects, + // and/or zones become the target of a spell trigger at this point; they'll wait to be put on + // the stack until the spell has finished being cast.) + + if (card != null) { + card.adjustTargets(this, game); } - return false; - } + if (getTargets().size() > 0 && getTargets().chooseTargets(getEffects().get(0).getOutcome(), this.controllerId, this, game) == false) { + if (variableManaCost != null) { + game.informPlayers(new StringBuilder(card != null ? card.getName(): "").append(": no valid targets with this value of X").toString()); + } else { + logger.debug("activate failed - target"); + } + return false; + } + } // end modes // TODO: Handle optionalCosts at the same time as already OptionalAdditionalSourceCosts are handled. for (Cost cost : optionalCosts) { diff --git a/Mage/src/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/mage/abilities/ActivatedAbilityImpl.java index eb0e95f2da5..1f0ca1412e7 100644 --- a/Mage/src/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/mage/abilities/ActivatedAbilityImpl.java @@ -243,21 +243,59 @@ public abstract class ActivatedAbilityImpl> ex } else { sb.append("unknown"); } - if (object instanceof Spell && ((Spell) object).getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) { - Spell spell = (Spell) object; - int i = 0; - for (SpellAbility spellAbility : spell.getSpellAbilities()) { - i++; - String half; - if (i == 1) { - half = " left"; - } else { - half = " right"; + if (object instanceof Spell && ((Spell) object).getSpellAbilities().size() > 1) { + if (((Spell) object).getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) { + Spell spell = (Spell) object; + int i = 0; + for (SpellAbility spellAbility : spell.getSpellAbilities()) { + i++; + String half; + if (i == 1) { + half = " left"; + } else { + half = " right"; + } + if (spellAbility.getTargets().size() > 0) { + sb.append(half).append(" half targeting "); + for (Target target: spellAbility.getTargets()) { + sb.append(target.getTargetedName(game)); + } + } } - if (spellAbility.getTargets().size() > 0) { - sb.append(half).append(" half targeting "); - for (Target target: spellAbility.getTargets()) { - sb.append(target.getTargetedName(game)); + } else { + Spell spell = (Spell) object; + int i = 0; + for (SpellAbility spellAbility : spell.getSpellAbilities()) { + i++; + if ( i > 1) { + sb.append(" splicing "); + if (spellAbility.name.length() > 5 && spellAbility.name.startsWith("Cast ")) { + sb.append(spellAbility.name.substring(5)); + } else { + sb.append(spellAbility.name); + } + } + if (spellAbility.getTargets().size() > 0) { + for (Target target: spellAbility.getTargets()) { + sb.append(" targeting "); + sb.append(target.getTargetedName(game)); + } + } + } + } + } else if (object instanceof Spell && ((Spell) object).getSpellAbility().getModes().size() > 1) { + Modes spellModes = ((Spell) object).getSpellAbility().getModes(); + int item = 0; + for (Mode mode : spellModes.values()) { + item++; + if (spellModes.getSelectedModes().contains(mode.getId())) { + spellModes.setMode(mode); + sb.append(" (mode ").append(item).append(")"); + if (getTargets().size() > 0) { + sb.append(" targeting "); + for (Target target: getTargets()) { + sb.append(target.getTargetedName(game)); + } } } } diff --git a/Mage/src/mage/abilities/Modes.java b/Mage/src/mage/abilities/Modes.java index c1d15c99c13..47bd7304758 100644 --- a/Mage/src/mage/abilities/Modes.java +++ b/Mage/src/mage/abilities/Modes.java @@ -28,8 +28,12 @@ package mage.abilities; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import java.util.UUID; +import mage.abilities.costs.OptionalAdditionalModeSourceCosts; +import mage.cards.Card; import mage.game.Game; import mage.players.Player; @@ -40,11 +44,18 @@ import mage.players.Player; public class Modes extends LinkedHashMap { private UUID modeId; + private Set selectedModes = new LinkedHashSet(); + private int minModes; + private int maxModes; public Modes() { Mode mode = new Mode(); this.put(mode.getId(), mode); this.modeId = mode.getId(); + this.minModes = 1; + this.maxModes = 1; + this.selectedModes.add(modeId); + } public Modes(Modes modes) { @@ -52,6 +63,9 @@ public class Modes extends LinkedHashMap { for (Map.Entry entry: modes.entrySet()) { this.put(entry.getKey(), entry.getValue().copy()); } + this.minModes = modes.minModes; + this.maxModes = modes.maxModes; + this.selectedModes.addAll(modes.selectedModes); } public Modes copy() { @@ -62,9 +76,30 @@ public class Modes extends LinkedHashMap { return get(modeId); } + public Set getSelectedModes() { + return selectedModes; + } + + public void setMinModes(int minModes) { + this.minModes = minModes; + } + + public int getMinModes() { + return this.minModes; + } + + public void setMaxModes(int maxModes) { + this.maxModes = maxModes; + } + + public int getMaxModes() { + return this.maxModes; + } + public void setMode(Mode mode) { if (this.containsKey(mode.getId())) { this.modeId = mode.getId(); + this.selectedModes.add(mode.getId()); } } @@ -74,40 +109,78 @@ public class Modes extends LinkedHashMap { public boolean choose(Game game, Ability source) { if (this.size() > 1) { - Player player = game.getPlayer(source.getControllerId()); - Mode choice = player.chooseMode(this, source, game); - if (choice == null) { - return false; + this.selectedModes.clear(); + // check if mode modifying abilities exist + Card card = game.getCard(source.getSourceId()); + if (card != null) { + for (Ability modeModifyingAbility : card.getAbilities()) { + if (modeModifyingAbility instanceof OptionalAdditionalModeSourceCosts) { + ((OptionalAdditionalModeSourceCosts)modeModifyingAbility).addOptionalAdditionalModeCosts(source, game); + } + } + } + // check if all modes can be activated automatically + if (this.size() == this.getMinModes()) { + for (Mode mode: this.values()) { + if (mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { + this.selectedModes.add(mode.getId()); + } + } + return selectedModes.size() > 0; + } + // player chooses modes manually + Player player = game.getPlayer(source.getControllerId()); + while (this.selectedModes.size() < this.getMaxModes()) { + Mode choice = player.chooseMode(this, source, game); + if (choice == null) { + return this.selectedModes.size() >= this.getMinModes(); + } + setMode(choice); + this.selectedModes.add(choice.getId()); } - setMode(choice); return true; } this.modeId = this.values().iterator().next().getId(); + this.selectedModes.add(modeId); return true; } public String getText() { + String andOr = ""; StringBuilder sb = new StringBuilder(); if (this.size() > 1) { - sb.append("Choose one - "); + if (this.getMinModes() == 1 && this.getMaxModes() == 3) { + sb.append("Choose one or more - "); + andOr = "; and/or "; + }else if (this.getMinModes() == 1 && this.getMaxModes() == 2) { + sb.append("Choose one or both - "); + andOr = "; and/or "; + } else if (this.getMinModes() == 2 && this.getMaxModes() == 2) { + sb.append("Choose two - "); + andOr = "; or "; + } else { + sb.append("Choose one - "); + andOr = "; or "; + } } for (Mode mode: this.values()) { - sb.append(mode.getEffects().getText(mode)).append("; or "); + sb.append(mode.getEffects().getText(mode)); + if (this.size() > 1) { + if (sb.length() > 2 && sb.substring(sb.length()-2, sb.length()).equals(". ")) { + sb.delete(sb.length()-2, sb.length()); + } + sb.append(andOr); + } + } + if (this.size() > 1) { + sb.delete(sb.length() - andOr.length(), sb.length()); + sb.append("."); } - sb.delete(sb.length() - 5, sb.length()); return sb.toString(); } public String getText(String sourceName) { - StringBuilder sb = new StringBuilder(); - if (this.size() > 1) { - sb.append("Choose one - "); - } - for (Mode mode: this.values()) { - sb.append(mode.getEffects().getText(mode)).append("; or "); - } - sb.delete(sb.length() - 5, sb.length()); - String text = sb.toString(); + String text = getText(); text = text.replace("{this}", sourceName); text = text.replace("{source}", sourceName); return text; diff --git a/Mage/src/mage/abilities/common/BlocksAttachedTriggeredAbility.java b/Mage/src/mage/abilities/common/BlocksAttachedTriggeredAbility.java index 8b9b87db34b..ba7e08a2965 100644 --- a/Mage/src/mage/abilities/common/BlocksAttachedTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/BlocksAttachedTriggeredAbility.java @@ -19,6 +19,7 @@ import mage.target.targetpointer.FixedTarget; public class BlocksAttachedTriggeredAbility extends TriggeredAbilityImpl{ private boolean setFixedTargetPointer; private String attachedDescription; + private boolean setFixedTargetPointerToBlocked; public BlocksAttachedTriggeredAbility(Effect effect, String attachedDescription, boolean optional) { this(effect, attachedDescription, optional, false); @@ -29,6 +30,13 @@ public class BlocksAttachedTriggeredAbility extends TriggeredAbilityImpl 0) { - return true; + if (found) { + if (game.getState().getZone(card.getId()) == Zone.EXILED && + card.getCounters().getCount(CounterType.TIME) > 0) { + return true; + } } } return false; diff --git a/Mage/src/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java b/Mage/src/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java new file mode 100644 index 00000000000..104542486d7 --- /dev/null +++ b/Mage/src/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.costs; + +import mage.abilities.Ability; +import mage.game.Game; + +/** + * + * @author LevelX2 + */ + + +public interface OptionalAdditionalModeSourceCosts { + void addOptionalAdditionalModeCosts(Ability ability, Game game); + String getCastMessageSuffix(); +} diff --git a/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java b/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java index 053c9f0f295..b877e972408 100644 --- a/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java +++ b/Mage/src/mage/abilities/costs/common/ExileFromGraveCost.java @@ -28,16 +28,16 @@ package mage.abilities.costs.common; -import mage.constants.Outcome; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.CostImpl; import mage.cards.Card; +import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; - -import java.util.UUID; +import mage.util.CardUtil; /** * @@ -48,7 +48,7 @@ public class ExileFromGraveCost extends CostImpl { public ExileFromGraveCost(TargetCardInYourGraveyard target) { this.addTarget(target); if (target.getMaxNumberOfTargets() > 1) { - this.text = "Exile " + target.getMaxNumberOfTargets() + " " + target.getTargetName(); + this.text = "Exile " + CardUtil.numberToText(target.getMaxNumberOfTargets()) + " " + target.getTargetName(); } else { this.text = "Exile " + target.getTargetName(); diff --git a/Mage/src/mage/abilities/decorator/ConditionalContinousEffect.java b/Mage/src/mage/abilities/decorator/ConditionalContinousEffect.java index 0614935d669..b3379612178 100644 --- a/Mage/src/mage/abilities/decorator/ConditionalContinousEffect.java +++ b/Mage/src/mage/abilities/decorator/ConditionalContinousEffect.java @@ -1,12 +1,12 @@ package mage.abilities.decorator; -import mage.constants.Duration; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.condition.Condition; import mage.abilities.condition.common.FixedCondition; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.Duration; import mage.constants.Layer; import mage.constants.SubLayer; import mage.game.Game; @@ -84,6 +84,9 @@ public class ConditionalContinousEffect extends ContinuousEffectImpl 0) { - count++; - } - if(mana.getBlue() > 0) { - count++; - } - if(mana.getGreen() > 0) { - count++; - } - if(mana.getRed() > 0) { - count++; - } - if(mana.getWhite() > 0) { - count++; + if (!game.getStack().isEmpty()) { + StackObject spell = game.getStack().getFirst(); + if (spell != null && spell instanceof Spell && ((Spell)spell).getSourceId().equals(source.getSourceId())) { + Mana mana = ((Spell)spell).getSpellAbility().getManaCostsToPay().getPayment(); + if(mana.getBlack() > 0) { + count++; + } + if(mana.getBlue() > 0) { + count++; + } + if(mana.getGreen() > 0) { + count++; + } + if(mana.getRed() > 0) { + count++; + } + if(mana.getWhite() > 0) { + count++; + } } } return count; diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index 11c7cbce8e1..88cd165bd1d 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -36,11 +36,22 @@ import mage.constants.Layer; import mage.constants.SubLayer; import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.SpellAbility; import mage.abilities.StaticAbility; +import mage.abilities.keyword.SpliceOntoArcaneAbility; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.Outcome; +import mage.constants.SpellAbilityType; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.common.TargetCardInHand; /** * @@ -58,6 +69,7 @@ public class ContinuousEffects implements Serializable { private ContinuousEffectsList restrictionEffects = new ContinuousEffectsList(); private ContinuousEffectsList asThoughEffects = new ContinuousEffectsList(); private ContinuousEffectsList costModificationEffects = new ContinuousEffectsList(); + private ContinuousEffectsList spliceCardEffects = new ContinuousEffectsList(); private List> allEffectsLists = new ArrayList>(); @@ -88,6 +100,7 @@ public class ContinuousEffects implements Serializable { restrictionEffects = effect.restrictionEffects.copy(); asThoughEffects = effect.asThoughEffects.copy(); costModificationEffects = effect.costModificationEffects.copy(); + spliceCardEffects = effect.spliceCardEffects.copy(); for (Map.Entry entry : effect.sources.entrySet()) { sources.put(entry.getKey(), entry.getValue()); } @@ -103,6 +116,7 @@ public class ContinuousEffects implements Serializable { allEffectsLists.add(restrictionEffects); allEffectsLists.add(asThoughEffects); allEffectsLists.add(costModificationEffects); + allEffectsLists.add(spliceCardEffects); } public ContinuousEffects copy() { @@ -125,6 +139,7 @@ public class ContinuousEffects implements Serializable { restrictionEffects.removeEndOfCombatEffects(); asThoughEffects.removeEndOfCombatEffects(); costModificationEffects.removeEndOfCombatEffects(); + spliceCardEffects.removeEndOfCombatEffects(); } public void removeEndOfTurnEffects() { @@ -135,6 +150,7 @@ public class ContinuousEffects implements Serializable { restrictionEffects.removeEndOfTurnEffects(); asThoughEffects.removeEndOfTurnEffects(); costModificationEffects.removeEndOfTurnEffects(); + spliceCardEffects.removeEndOfTurnEffects(); } public void removeInactiveEffects(Game game) { @@ -145,6 +161,7 @@ public class ContinuousEffects implements Serializable { restrictionEffects.removeInactiveEffects(game); asThoughEffects.removeInactiveEffects(game); costModificationEffects.removeInactiveEffects(game); + spliceCardEffects.removeInactiveEffects(game); } public List getLayeredEffects(Game game) { @@ -156,7 +173,8 @@ public class ContinuousEffects implements Serializable { case WhileInGraveyard: HashSet abilities = layeredEffects.getAbility(effect.getId()); for (Ability ability: abilities) { - if (ability.isInUseableZone(game, null, false)) { + // If e.g. triggerd abilities (non static) created the effect, the ability must not be in usable zone (e.g. Unearth giving Haste effect) + if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, false)) { layerEffects.add(effect); break; } @@ -327,6 +345,29 @@ public class ContinuousEffects implements Serializable { return costEffects; } + /** + * Filters out splice effects that are not active. + * + * @param game + * @return + */ + private List getApplicableSpliceCardEffects(Game game, UUID playerId) { + List spliceEffects = new ArrayList(); + + for (SpliceCardEffect effect: spliceCardEffects) { + HashSet abilities = spliceCardEffects.getAbility(effect.getId()); + for (Ability ability : abilities) { + if (ability.getControllerId().equals(playerId) && (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, false))) { + if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { + spliceEffects.add(effect); + break; + } + } + } + } + + return spliceEffects; + } public boolean asThough(UUID objectId, AsThoughEffectType type, Game game) { List asThoughEffectsList = getApplicableAsThoughEffects(game); @@ -389,6 +430,68 @@ public class ContinuousEffects implements Serializable { } } + /** + * Checks all available splice effects to be applied. + * + * @param abilityToModify + * @param game + * @return + */ + public void applySpliceEffects ( Ability abilityToModify, Game game ) { + if ( ((SpellAbility) abilityToModify).getSpellAbilityType().equals(SpellAbilityType.SPLICE)) { + // on a spliced ability of a spell can't be spliced again + return; + } + List spliceEffects = getApplicableSpliceCardEffects(game, abilityToModify.getControllerId()); + // get the applyable splice abilities + List spliceAbilities = new ArrayList(); + for (SpliceCardEffect effect : spliceEffects) { + HashSet abilities = spliceCardEffects.getAbility(effect.getId()); + for (Ability ability : abilities) { + if (effect.applies(abilityToModify, ability, game) ) { + spliceAbilities.add((SpliceOntoArcaneAbility) ability); + } + } + } + // check if player wants to use splice + + if (spliceAbilities.size() > 0) { + Player controller = game.getPlayer(abilityToModify.getControllerId()); + if (controller.chooseUse(Outcome.Benefit, "Splice a card?", game)) { + Cards cardsToReveal = new CardsImpl(); + do { + FilterCard filter = new FilterCard("a card to splice"); + ArrayList> idPredicates = new ArrayList>(); + for (SpliceOntoArcaneAbility ability : spliceAbilities) { + idPredicates.add(new CardIdPredicate((ability.getSourceId()))); + } + filter.add(Predicates.or(idPredicates)); + TargetCardInHand target = new TargetCardInHand(filter); + target.setRequired(true); + controller.chooseTarget(Outcome.Benefit, target, abilityToModify, game); + UUID cardId = target.getFirstTarget(); + if (cardId != null) { + SpliceOntoArcaneAbility selectedAbility = null; + for(SpliceOntoArcaneAbility ability :spliceAbilities) { + if (ability.getSourceId().equals(cardId)) { + selectedAbility = ability; + break; + } + } + if (selectedAbility != null) { + SpliceCardEffect spliceEffect = (SpliceCardEffect) selectedAbility.getEffects().get(0); + spliceEffect.apply(game, selectedAbility, abilityToModify); + cardsToReveal.add(game.getCard(cardId)); + spliceAbilities.remove(selectedAbility); + } + } + } while (!spliceAbilities.isEmpty() && controller.chooseUse(Outcome.Benefit, "Splice another card?", game)); + controller.revealCards("Spliced cards", cardsToReveal, game); + } + } + } + + public boolean replaceEvent(GameEvent event, Game game) { boolean caught = false; HashMap> consumed = new HashMap>(); @@ -616,6 +719,10 @@ public class ContinuousEffects implements Serializable { CostModificationEffect newCostModificationEffect = (CostModificationEffect)effect; costModificationEffects.addEffect(newCostModificationEffect, source); break; + case SPLICE: + SpliceCardEffect newSpliceCardEffect = (SpliceCardEffect)effect; + spliceCardEffects.addEffect(newSpliceCardEffect, source); + break; default: ContinuousEffect newEffect = (ContinuousEffect)effect; layeredEffects.addEffect(newEffect, source); diff --git a/Mage/src/mage/abilities/effects/SpliceCardEffect.java b/Mage/src/mage/abilities/effects/SpliceCardEffect.java new file mode 100644 index 00000000000..094b3a98916 --- /dev/null +++ b/Mage/src/mage/abilities/effects/SpliceCardEffect.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.abilities.effects; + +import mage.abilities.Ability; +import mage.game.Game; + +/** + * Represents a {@link ContinuousEffect} that will modify the cost and abilities of a spell + * on the stack (splice a card). {@link mage.abilities.Ability Abilities} with this type of effect will be + * called once and only once from the {@link mage.abilities.AbilityImpl#activate(mage.game.Game, + * boolean) Ability.activate} method before alternative or additional costs are paid. + * + * @param + * @author levelX2 + */ + +public interface SpliceCardEffect> extends ContinuousEffect { + /** + * Called by the {@link ContinuousEffects#costModification(Ability abilityToModify, Game game) ContinuousEffects.costModification} + * method. + * + * @param game The game for which this effect should be applied. + * @param source The source ability of this effect. + * @param abilityToModify The {@link mage.abilities.SpellAbility} or {@link Ability} which should be modified. + * @return + */ + boolean apply ( Game game, Ability source, Ability abilityToModify ); + + /** + * Called by the {@link ContinuousEffects#costModification(mage.abilities.Ability, mage.game.Game) ContinuousEffects.costModification} + * method. + * + * @param abilityToModify The ability to possibly modify. + * @param source The source ability of this effect. + * @param game The game for which this effect shoul dbe applied. + * @return + */ + boolean applies(Ability abilityToModify, Ability source, Game game); +} diff --git a/Mage/src/mage/abilities/effects/SpliceCardEffectImpl.java b/Mage/src/mage/abilities/effects/SpliceCardEffectImpl.java new file mode 100644 index 00000000000..4a4aa90cd2f --- /dev/null +++ b/Mage/src/mage/abilities/effects/SpliceCardEffectImpl.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.abilities.effects; + +import mage.abilities.Ability; +import mage.constants.Duration; +import mage.constants.EffectType; +import mage.constants.Outcome; +import mage.game.Game; + + +/** + * Simple implementation of a {@link SpliceCardEffect} offering simplified + * construction to setup the object for use by the mage framework. + + * @author LevelX2 + */ +public abstract class SpliceCardEffectImpl> extends ContinuousEffectImpl implements SpliceCardEffect { + + public SpliceCardEffectImpl ( Duration duration, Outcome outcome ) { + super(duration, outcome); + this.effectType = EffectType.SPLICE; + } + + public SpliceCardEffectImpl(final SpliceCardEffectImpl effect) { + super(effect); + this.effectType = effect.effectType; + } + + /** + * Overridden and 'no-op' implementation put in place. + * + * @see #apply(mage.game.Game, mage.abilities.Ability, mage.abilities.Ability) + * + * @param game + * @param source + * @return + */ + @Override + public final boolean apply ( Game game, Ability source ) { return false; } +} diff --git a/Mage/src/mage/abilities/effects/common/CounterTargetEffect.java b/Mage/src/mage/abilities/effects/common/CounterTargetEffect.java index a756b4b819d..b0d764e2c9e 100644 --- a/Mage/src/mage/abilities/effects/common/CounterTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/CounterTargetEffect.java @@ -1,33 +1,33 @@ /* -* 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.abilities.effects.common; +import java.util.UUID; import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.Mode; @@ -55,12 +55,20 @@ public class CounterTargetEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - return game.getStack().counter(source.getFirstTarget(), source.getSourceId(), game); + boolean countered = false; + for (UUID targetId : source.getTargets().get(0).getTargets()) { + if (game.getStack().counter(targetId, source.getSourceId(), game)) { + countered = true; + } + } + return countered; } @Override public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; + } return "Counter target " + mode.getTargets().get(0).getTargetName(); } - } diff --git a/Mage/src/mage/abilities/effects/common/DamagePlayersEffect.java b/Mage/src/mage/abilities/effects/common/DamagePlayersEffect.java index 365b6381b9f..9fd3fe37060 100644 --- a/Mage/src/mage/abilities/effects/common/DamagePlayersEffect.java +++ b/Mage/src/mage/abilities/effects/common/DamagePlayersEffect.java @@ -78,7 +78,7 @@ public class DamagePlayersEffect extends OneShotEffect { for (UUID playerId: game.getPlayer(source.getControllerId()).getInRange()) { Player player = game.getPlayer(playerId); if (player != null) { - player.damage(amount.calculate(game, source), source.getId(), game, false, true); + player.damage(amount.calculate(game, source), source.getSourceId(), game, false, true); } } break; @@ -86,7 +86,7 @@ public class DamagePlayersEffect extends OneShotEffect { for (UUID playerId: game.getOpponents(source.getControllerId())) { Player player = game.getPlayer(playerId); if (player != null) { - player.damage(amount.calculate(game, source), source.getId(), game, false, true); + player.damage(amount.calculate(game, source), source.getSourceId(), game, false, true); } } break; diff --git a/Mage/src/mage/abilities/effects/common/DestroyTargetEffect.java b/Mage/src/mage/abilities/effects/common/DestroyTargetEffect.java index 944254c350c..bd5578f504f 100644 --- a/Mage/src/mage/abilities/effects/common/DestroyTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/DestroyTargetEffect.java @@ -28,15 +28,14 @@ package mage.abilities.effects.common; -import mage.constants.Outcome; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; - -import java.util.UUID; import mage.target.targetpointer.FirstTargetPointer; /** @@ -105,12 +104,14 @@ public class DestroyTargetEffect extends OneShotEffect { StringBuilder sb = new StringBuilder(); if (mode.getTargets().size() == 0) { sb.append("destroy that creature"); //TODO add possibility to specify text with targetPointer usage - } else if (mode.getTargets().get(0).getNumberOfTargets() == 1) + } else if (mode.getTargets().get(0).getNumberOfTargets() == 1) { sb.append("Destroy target ").append(mode.getTargets().get(0).getTargetName()); - else + } else { sb.append("Destroy ").append(mode.getTargets().get(0).getNumberOfTargets()).append(" target ").append(mode.getTargets().get(0).getTargetName()); - if (noRegen) + } + if (noRegen) { sb.append(". It can't be regenerated"); + } return sb.toString(); } diff --git a/Mage/src/mage/abilities/effects/common/DiscardHandControllerEffect.java b/Mage/src/mage/abilities/effects/common/DiscardHandControllerEffect.java new file mode 100644 index 00000000000..5698b0004e6 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/DiscardHandControllerEffect.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ + + +public class DiscardHandControllerEffect extends OneShotEffect { + + public DiscardHandControllerEffect() { + super(Outcome.Discard); + this.staticText = "Discard your hand"; + } + + public DiscardHandControllerEffect(final DiscardHandControllerEffect effect) { + super(effect); + } + + @Override + public DiscardHandControllerEffect copy() { + return new DiscardHandControllerEffect(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; + } +} diff --git a/Mage/src/mage/abilities/effects/common/DrawDiscardControllerEffect.java b/Mage/src/mage/abilities/effects/common/DrawDiscardControllerEffect.java index c37d692d13e..251843ae5c3 100644 --- a/Mage/src/mage/abilities/effects/common/DrawDiscardControllerEffect.java +++ b/Mage/src/mage/abilities/effects/common/DrawDiscardControllerEffect.java @@ -28,11 +28,12 @@ package mage.abilities.effects.common; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; +import mage.util.CardUtil; /** * @@ -40,13 +41,29 @@ import mage.players.Player; */ public class DrawDiscardControllerEffect extends OneShotEffect { + private int cardsToDraw; + private int cardsToDiscard; + public DrawDiscardControllerEffect() { + this(1,1); + } + + public DrawDiscardControllerEffect(int cardsToDraw, int cardsToDiscard) { super(Outcome.DrawCard); - staticText = "Draw a card, then discard a card"; + this.cardsToDraw = cardsToDraw; + this.cardsToDiscard = cardsToDiscard; + staticText = new StringBuilder("Draw ") + .append(cardsToDraw == 1?"a": CardUtil.numberToText(cardsToDraw)) + .append(" card").append(cardsToDraw == 1?" ": "s") + .append(", then discard ") + .append(cardsToDiscard == 1?"a": CardUtil.numberToText(cardsToDiscard)) + .append(" card").append(cardsToDiscard == 1?" ": "s").toString(); } public DrawDiscardControllerEffect(final DrawDiscardControllerEffect effect) { super(effect); + this.cardsToDraw = effect.cardsToDraw; + this.cardsToDiscard = effect.cardsToDiscard; } @Override @@ -58,8 +75,8 @@ public class DrawDiscardControllerEffect extends OneShotEffect { + + private int cardsToDraw; + private int cardsToDiscard; + + public DrawDiscardTargetEffect() { + this(1,1); + } + + public DrawDiscardTargetEffect(int cardsToDraw, int cardsToDiscard) { + super(Outcome.DrawCard); + this.cardsToDraw = cardsToDraw; + this.cardsToDiscard = cardsToDiscard; + staticText = new StringBuilder("Target player draws ") + .append(cardsToDraw == 1?"a": CardUtil.numberToText(cardsToDraw)) + .append(" card").append(cardsToDraw == 1?" ": "s") + .append(", then discard ") + .append(cardsToDiscard == 1?"a": CardUtil.numberToText(cardsToDiscard)) + .append(" card").append(cardsToDiscard == 1?" ": "s").toString(); + } + + public DrawDiscardTargetEffect(final DrawDiscardTargetEffect effect) { + super(effect); + this.cardsToDraw = effect.cardsToDraw; + this.cardsToDiscard = effect.cardsToDiscard; + } + + @Override + public DrawDiscardTargetEffect copy() { + return new DrawDiscardTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null) { + player.drawCards(cardsToDraw, game); + player.discard(cardsToDiscard, source, game); + return true; + } + return false; + } + +} diff --git a/Mage/src/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java b/Mage/src/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java index 40307e1aa22..9d0f893fbf6 100644 --- a/Mage/src/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/PutLibraryIntoGraveTargetEffect.java @@ -86,8 +86,9 @@ public class PutLibraryIntoGraveTargetEffect extends OneShotEffect @Override public String getText(Mode mode) { - if ("".equals(staticText) && !mode.getTargets().isEmpty()) { + if (staticText.isEmpty() && !mode.getTargets().isEmpty()) { if (mode.getTargets().get(0).getNumberOfTargets() == 1) { return "The controller of target " + mode.getTargets().get(0).getTargetName() + " sacrifices it"; } else { diff --git a/Mage/src/mage/abilities/effects/common/continious/GainAbilitySourceEffect.java b/Mage/src/mage/abilities/effects/common/continious/GainAbilitySourceEffect.java index a18465d7c56..307ffd1bef3 100644 --- a/Mage/src/mage/abilities/effects/common/continious/GainAbilitySourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/continious/GainAbilitySourceEffect.java @@ -28,12 +28,13 @@ package mage.abilities.effects.common.continious; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.cards.Card; import mage.constants.Duration; import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.SubLayer; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; import mage.game.Game; import mage.game.permanent.Permanent; @@ -44,6 +45,8 @@ import mage.game.permanent.Permanent; public class GainAbilitySourceEffect extends ContinuousEffectImpl { protected Ability ability; + // shall a card gain the ability (otherwise permanent) + private boolean onCard; /** * Add ability with Duration.WhileOnBattlefield @@ -54,14 +57,20 @@ public class GainAbilitySourceEffect extends ContinuousEffectImpl { protected Ability ability; + // shall a card gain the ability (otherwise permanent) + private boolean onCard; public GainAbilityTargetEffect(Ability ability, Duration duration) { - super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, - ability.getEffects().size() > 0 ? ability.getEffects().get(0).getOutcome() : Outcome.AddAbility); - this.ability = ability; + this(ability, duration, null); } public GainAbilityTargetEffect(Ability ability, Duration duration, String rule) { + this(ability, duration, rule, false); + } + + public GainAbilityTargetEffect(Ability ability, Duration duration, String rule, boolean onCard) { super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, ability.getEffects().size() > 0 ? ability.getEffects().get(0).getOutcome() : Outcome.AddAbility); this.ability = ability; staticText = rule; + this.onCard = onCard; } public GainAbilityTargetEffect(final GainAbilityTargetEffect effect) { super(effect); this.ability = effect.ability.copy(); + this.onCard = effect.onCard; } @Override @@ -81,11 +88,24 @@ public class GainAbilityTargetEffect extends ContinuousEffectImpl 0; diff --git a/Mage/src/mage/abilities/effects/common/counter/AddCountersSourceEffect.java b/Mage/src/mage/abilities/effects/common/counter/AddCountersSourceEffect.java index 5029184f207..72a752e21a3 100644 --- a/Mage/src/mage/abilities/effects/common/counter/AddCountersSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/counter/AddCountersSourceEffect.java @@ -33,6 +33,7 @@ import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; import mage.counters.Counter; import mage.game.Game; import mage.game.permanent.Permanent; @@ -44,8 +45,9 @@ import mage.players.Player; public class AddCountersSourceEffect extends OneShotEffect { private Counter counter; - protected boolean informPlayers; - protected DynamicValue amount; + private boolean informPlayers; + private DynamicValue amount; + private boolean putOnCard; public AddCountersSourceEffect(Counter counter) { this(counter, false); @@ -55,17 +57,23 @@ public class AddCountersSourceEffect extends OneShotEffect 0) { + int adjCost = 0; + for (UUID cardId: target.getTargets()) { + Card card = game.getCard(cardId); + if (card == null) { + continue; + } + card.moveToExile(null, null, this.getSourceId(), game); + ++adjCost; + } + game.informPlayers(new StringBuilder(player.getName()).append(" delved ") + .append(adjCost).append(" creature").append(adjCost != 1?"s":"").append(" from his or her graveyard").toString()); + CardUtil.adjustCost((SpellAbility)ability, adjCost); + } + } + } + + @Override + public String getRule() { + return "Delve (You may exile any number of cards from your graveyard as you cast this spell. It costs {1} less to cast for each card exiled this way.)"; + } +} diff --git a/Mage/src/mage/abilities/keyword/EchoAbility.java b/Mage/src/mage/abilities/keyword/EchoAbility.java index ccd2eee72ed..c4dc45d3e9b 100644 --- a/Mage/src/mage/abilities/keyword/EchoAbility.java +++ b/Mage/src/mage/abilities/keyword/EchoAbility.java @@ -29,14 +29,15 @@ package mage.abilities.keyword; import java.util.UUID; - -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.CostsImpl; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.events.EntersTheBattlefieldEvent; @@ -52,18 +53,27 @@ public class EchoAbility extends TriggeredAbilityImpl { protected UUID lastController; protected boolean echoPaid; - protected String manaString; + protected Costs echoCosts = new CostsImpl(); + private boolean manaEcho = true; public EchoAbility(String manaString) { super(Zone.BATTLEFIELD, new EchoEffect(new ManaCostsImpl(manaString)), false); this.echoPaid = false; - this.manaString = manaString; + this.echoCosts.add(new ManaCostsImpl(manaString)); + } + + public EchoAbility(Cost echoCost) { + super(Zone.BATTLEFIELD, new EchoEffect(echoCost), false); + this.echoPaid = false; + this.echoCosts.add(echoCost); + this.manaEcho = false; } public EchoAbility(final EchoAbility ability) { super(ability); this.echoPaid = ability.echoPaid; - this.manaString = ability.manaString; + this.echoCosts = ability.echoCosts.copy(); + this.manaEcho = ability.manaEcho; } @Override @@ -98,7 +108,15 @@ public class EchoAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Echo " + manaString + " (At the beginning of your upkeep, if this came under your control since the beginning of your last upkeep," + getEffects().getText(modes.getMode()) + ")"; + StringBuilder sb = new StringBuilder("Echo"); + if (manaEcho) { + sb.append(" "); + } else { + sb.append("-"); + } + sb.append(echoCosts.getText()); + sb.append(" (At the beginning of your upkeep, if this came under your control since the beginning of your last upkeep, sacrifice it unless you pay its echo cost.)"); + return sb.toString(); } } @@ -137,7 +155,7 @@ class EchoEffect extends OneShotEffect { return new EchoEffect(this); } - @Override + @Override public String getText(Mode mode) { StringBuilder sb = new StringBuilder("sacrifice {this} unless you "); String costText = cost.getText(); @@ -145,8 +163,9 @@ class EchoEffect extends OneShotEffect { sb.append(costText.substring(0, 1).toLowerCase()); sb.append(costText.substring(1)); } - else + else { sb.append("pay ").append(costText); + } return sb.toString(); diff --git a/Mage/src/mage/abilities/keyword/EntwineAbility.java b/Mage/src/mage/abilities/keyword/EntwineAbility.java new file mode 100644 index 00000000000..8e755cebded --- /dev/null +++ b/Mage/src/mage/abilities/keyword/EntwineAbility.java @@ -0,0 +1,160 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.keyword; + +import java.util.Iterator; + +import mage.constants.Zone; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.StaticAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.OptionalAdditionalCost; +import mage.abilities.costs.OptionalAdditionalCostImpl; +import mage.abilities.costs.OptionalAdditionalModeSourceCosts; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; + +/** + * 702.40. Entwine + * + * 702.40a Entwine is a static ability of modal spells (see rule 700.2) that functions + * while the spell is on the stack. "Entwine [cost]" means "You may choose all modes + * of this spell instead of just one. If you do, you pay an additional [cost]." Using + * the entwine ability follows the rules for choosing modes and paying additional costs + * in rules 601.2b and 601.2e-g. + * + * 702.40b If the entwine cost was paid, follow the text of each of the modes in the order + * written on the card when the spell resolves. + * + * @author LevelX2 + */ + +public class EntwineAbility extends StaticAbility implements OptionalAdditionalModeSourceCosts { + + private static final String keywordText = "Entwine"; + private static final String reminderText = " (Choose both if you pay the entwine cost.)"; + protected OptionalAdditionalCost additionalCost; + + public EntwineAbility(String manaString) { + super(Zone.STACK, null); + this.additionalCost = new OptionalAdditionalCostImpl(keywordText, reminderText, new ManaCostsImpl(manaString)); + } + + public EntwineAbility(Cost cost) { + super(Zone.STACK, null); + this.additionalCost = new OptionalAdditionalCostImpl(keywordText, "-", reminderText, cost); + setRuleAtTheTop(true); + } + + public EntwineAbility(final EntwineAbility ability) { + super(ability); + additionalCost = ability.additionalCost; + } + + @Override + public EntwineAbility copy() { + return new EntwineAbility(this); + } + + @Override + public void addCost(Cost cost) { + if (additionalCost != null) { + ((Costs) additionalCost).add(cost); + } + } + + public boolean isActivated() { + if (additionalCost != null) { + return additionalCost.isActivated(); + } + return false; + } + + public void resetCosts() { + if (additionalCost != null) { + additionalCost.reset(); + } + } + + @Override + public void addOptionalAdditionalModeCosts(Ability ability, Game game) { + if (ability instanceof SpellAbility) { + Player player = game.getPlayer(controllerId); + if (player != null) { + this.resetCosts(); + if (additionalCost != null) { + if (player.chooseUse(Outcome.Benefit,new StringBuilder("Pay ").append(additionalCost.getText(false)).append(" ?").toString(), game)) { + additionalCost.activate(); + for (Iterator it = ((Costs) additionalCost).iterator(); it.hasNext();) { + Cost cost = (Cost) it.next(); + if (cost instanceof ManaCostsImpl) { + ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy()); + } else { + ability.getCosts().add(cost.copy()); + } + } + ability.getModes().setMinModes(2); + ability.getModes().setMaxModes(2); + } + } + } + } + } + + + @Override + public String getRule() { + StringBuilder sb = new StringBuilder(); + if (additionalCost != null) { + sb.append(additionalCost.getText(false)); + sb.append(" ").append(additionalCost.getReminderText()); + } + return sb.toString(); + } + + @Override + public String getCastMessageSuffix() { + if (additionalCost != null) { + return additionalCost.getCastSuffixMessage(0); + } else { + return ""; + } + } + + public String getReminderText() { + if (additionalCost != null) { + return additionalCost.getReminderText(); + } else { + return ""; + } + } +} diff --git a/Mage/src/mage/abilities/keyword/InfectAbility.java b/Mage/src/mage/abilities/keyword/InfectAbility.java index 9b60d0a33dc..05db0001047 100644 --- a/Mage/src/mage/abilities/keyword/InfectAbility.java +++ b/Mage/src/mage/abilities/keyword/InfectAbility.java @@ -75,7 +75,7 @@ public class InfectAbility extends StaticAbility implements MageS @Override public String getRule() { - return "Infect"; + return "Infect (This creature deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters.)"; } @Override diff --git a/Mage/src/mage/abilities/keyword/KickerAbility.java b/Mage/src/mage/abilities/keyword/KickerAbility.java index 12e08e9e6f3..0724b88a056 100644 --- a/Mage/src/mage/abilities/keyword/KickerAbility.java +++ b/Mage/src/mage/abilities/keyword/KickerAbility.java @@ -31,8 +31,6 @@ package mage.abilities.keyword; import java.util.Iterator; import java.util.LinkedList; import java.util.List; - -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.StaticAbility; @@ -41,8 +39,11 @@ import mage.abilities.costs.Costs; import mage.abilities.costs.OptionalAdditionalCost; import mage.abilities.costs.OptionalAdditionalCostImpl; import mage.abilities.costs.OptionalAdditionalSourceCosts; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.costs.mana.VariableManaCost; import mage.constants.Outcome; +import mage.constants.Zone; import mage.game.Game; import mage.players.Player; @@ -88,6 +89,7 @@ public class KickerAbility extends StaticAbility implements Optio protected String keywordText; protected String reminderText; protected List kickerCosts = new LinkedList(); + private int xManaValue = 0; public KickerAbility(String manaString) { this(KICKER_KEYWORD, KICKER_REMINDER_MANA); @@ -112,6 +114,8 @@ public class KickerAbility extends StaticAbility implements Optio this.kickerCosts = ability.kickerCosts; this.keywordText = ability.keywordText; this.reminderText = ability.reminderText; + this.xManaValue = ability.xManaValue; + } @Override @@ -137,6 +141,10 @@ public class KickerAbility extends StaticAbility implements Optio } } + public int getXManaValue() { + return xManaValue; + } + public int getKickedCounter() { int counter = 0; for (OptionalAdditionalCost cost: kickerCosts) { @@ -178,7 +186,16 @@ public class KickerAbility extends StaticAbility implements Optio for (Iterator it = ((Costs) kickerCost).iterator(); it.hasNext();) { Cost cost = (Cost) it.next(); if (cost instanceof ManaCostsImpl) { - ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy()); + List varCosts = ((ManaCostsImpl)cost).getVariableCosts(); + if (!varCosts.isEmpty()) { + // use only first variable cost + xManaValue = game.getPlayer(this.controllerId).announceXMana(varCosts.get(0).getMinX(), Integer.MAX_VALUE, "Announce kicker value for " + varCosts.get(0).getText(), game, this); + // kicker variable X costs handled internally as multikicker with {1} cost (no multikicker on card) + game.informPlayers(new StringBuilder(game.getPlayer(this.controllerId).getName()).append(" announced a value of ").append(xManaValue).append(" for ").append(" kicker X ").toString()); + ability.getManaCostsToPay().add(new GenericManaCost(xManaValue)); + } else { + ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy()); + } } else { ability.getCosts().add(cost.copy()); } diff --git a/Mage/src/mage/abilities/keyword/ModularAbility.java b/Mage/src/mage/abilities/keyword/ModularAbility.java index 216c55a71dd..549b0bacd21 100644 --- a/Mage/src/mage/abilities/keyword/ModularAbility.java +++ b/Mage/src/mage/abilities/keyword/ModularAbility.java @@ -1,8 +1,5 @@ package mage.abilities.keyword; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.StaticAbility; @@ -11,6 +8,9 @@ import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.Card; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterArtifactPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -42,17 +42,30 @@ public class ModularAbility extends DiesTriggeredAbility { filter.add(new CardTypePredicate(CardType.CREATURE)); } private int amount; + private boolean sunburst; public ModularAbility(Card card, int amount) { + this(card, amount, false); + } + + public ModularAbility(Card card, int amount, boolean sunburst) { super(new ModularDistributeCounterEffect(), true); this.addTarget(new TargetArtifactPermanent(filter)); this.amount = amount; - card.addAbility(new ModularStaticAbility(amount)); + this.sunburst = sunburst; + if (sunburst) { + Ability ability = new SunburstAbility(card); + ability.setRuleVisible(false); + card.addAbility(ability); + } else { + card.addAbility(new ModularStaticAbility(amount)); + } } public ModularAbility(ModularAbility ability) { super(ability); this.amount = ability.amount; + this.sunburst = ability.sunburst; } @Override @@ -71,19 +84,31 @@ public class ModularAbility extends DiesTriggeredAbility { @Override public String getRule() { - return "Modular " + amount + " (This enters the battlefield with " + amount + " +1/+1 counter on it. When it dies, you may put its +1/+1 counters on target artifact creature.)"; + StringBuilder sb = new StringBuilder("Modular"); + if (sunburst) { + sb.append("-Sunburst (This enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it. When it dies, you may put its +1/+1 counters on target artifact creature.)"); + } else { + sb.append(" ").append(amount).append(" (This enters the battlefield with ") + .append(amount).append(" +1/+1 counter on it. When it dies, you may put its +1/+1 counters on target artifact creature.)"); + } + return sb.toString(); } } class ModularStaticAbility extends StaticAbility { + private String ruleText; + public ModularStaticAbility(int amount) { super(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(amount)))); + ruleText = new StringBuilder("This enters the battlefield with ").append(amount).append(" +1/+1 counter on it.").toString(); + this.setRuleVisible(false); } public ModularStaticAbility(final ModularStaticAbility ability) { super(ability); + this.ruleText = ability.ruleText; } @Override @@ -93,7 +118,7 @@ class ModularStaticAbility extends StaticAbility { @Override public String getRule() { - return ""; + return ruleText; } } diff --git a/Mage/src/mage/abilities/keyword/ProwlAbility.java b/Mage/src/mage/abilities/keyword/ProwlAbility.java new file mode 100644 index 00000000000..4ca59aa9f30 --- /dev/null +++ b/Mage/src/mage/abilities/keyword/ProwlAbility.java @@ -0,0 +1,199 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.abilities.keyword; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.StaticAbility; +import mage.abilities.costs.AlternativeCost2; +import mage.abilities.costs.AlternativeCost2Impl; +import mage.abilities.costs.AlternativeSourceCosts; +import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.cards.Card; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.watchers.common.ProwlWatcher; + +/** + * 702.74. Prowl # + * + * 702.74a Prowl is a static ability that functions on the stack. "Prowl [cost]" means + * "You may pay [cost] rather than pay this spell's mana cost if a player was dealt combat + * damage this turn by a source that, at the time it dealt that damage, was under your + * control and had any of this spell's creature types." Paying a spell's prowl cost follows + * the rules for paying alternative costs in rules 601.2b and 601.2e-g + * + * @author LevelX2 + */ + +public class ProwlAbility extends StaticAbility implements AlternativeSourceCosts { + + private static final String PROWL_KEYWORD = "Prowl"; + private List prowlCosts = new LinkedList(); + private String reminderText; + + public ProwlAbility(Card card, String manaString) { + super(Zone.STACK, null); + setRuleAtTheTop(true); + name = PROWL_KEYWORD; + setReminderText(card); + this.addProwlCost(manaString); + card.addWatcher(new ProwlWatcher()); + + } + + public ProwlAbility(final ProwlAbility ability) { + super(ability); + this.prowlCosts.addAll(ability.prowlCosts); + this.reminderText = ability.reminderText; + } + + @Override + public ProwlAbility copy() { + return new ProwlAbility(this); + } + + public final AlternativeCost2 addProwlCost(String manaString) { + AlternativeCost2 prowlCost = new AlternativeCost2Impl(PROWL_KEYWORD, reminderText, new ManaCostsImpl(manaString)); + prowlCosts.add(prowlCost); + return prowlCost; + } + + public void resetProwl() { + for (AlternativeCost2 cost: prowlCosts) { + cost.reset(); + } + } + @Override + public boolean isActivated() { + for (AlternativeCost2 cost: prowlCosts) { + if(cost.isActivated()) { + return true; + } + } + return false; + } + + @Override + public boolean askToActivateAlternativeCosts(Ability ability, Game game) { + if (ability instanceof SpellAbility) { + Player player = game.getPlayer(controllerId); + ProwlWatcher prowlWatcher = (ProwlWatcher) game.getState().getWatchers().get("Prowl"); + Card card = game.getCard(ability.getSourceId()); + if (player == null || prowlWatcher == null || card == null) { + throw new IllegalArgumentException("Params can't be null"); + } + boolean canProwl = false; + if (prowlWatcher.getDamagingSubtypes(ability.getControllerId()) != null) { + for (String subtype : prowlWatcher.getDamagingSubtypes(ability.getControllerId())) { + if (card.getSubtype().contains(subtype)) { + canProwl = true; + break; + } + } + } + if (canProwl) { + this.resetProwl(); + for (AlternativeCost2 prowlCost: prowlCosts) { + if (prowlCost.canPay(sourceId, controllerId, game) && + player.chooseUse(Outcome.Benefit, new StringBuilder("Cast for ").append(PROWL_KEYWORD).append(" cost ").append(prowlCost.getText(true)).append(" ?").toString(), game)) { + prowlCost.activate(); + ability.getManaCostsToPay().clear(); + ability.getCosts().clear(); + for (Iterator it = ((Costs) prowlCost).iterator(); it.hasNext();) { + Cost cost = (Cost) it.next(); + if (cost instanceof ManaCostsImpl) { + ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy()); + } else { + ability.getCosts().add(cost.copy()); + } + } + } + } + } + } + return isActivated(); + } + + @Override + public String getRule() { + StringBuilder sb = new StringBuilder(); + int numberCosts = 0; + String remarkText = ""; + for (AlternativeCost2 prowlCost: prowlCosts) { + if (numberCosts == 0) { + sb.append(prowlCost.getText(false)); + remarkText = prowlCost.getReminderText(); + } else { + sb.append(" and/or ").append(prowlCost.getText(true)); + } + ++numberCosts; + } + if (numberCosts == 1) { + sb.append(" ").append(remarkText); + } + + return sb.toString(); + } + + @Override + public String getCastMessageSuffix() { + StringBuilder sb = new StringBuilder(); + int position = 0; + for (AlternativeCost2 cost : prowlCosts) { + if (cost.isActivated()) { + sb.append(cost.getCastSuffixMessage(position)); + ++position; + } + } + return sb.toString(); + } + + private void setReminderText(Card card) { + StringBuilder sb = new StringBuilder("(You may cast this for its prowl cost if you dealt combat damage to a player this turn with a "); + int i = 0; + for (String subtype: card.getSubtype()) { + i++; + sb.append(subtype); + if (card.getSupertype().size() > 1 && i < card.getSupertype().size()) { + sb.append(" or "); + } + } + //private static final String REMINDER_TEXT = "{subtypes}.)"; + + reminderText = sb.toString(); + } +} diff --git a/Mage/src/mage/abilities/keyword/RetraceAbility.java b/Mage/src/mage/abilities/keyword/RetraceAbility.java index cb15ed79647..2347e178270 100644 --- a/Mage/src/mage/abilities/keyword/RetraceAbility.java +++ b/Mage/src/mage/abilities/keyword/RetraceAbility.java @@ -67,9 +67,7 @@ public class RetraceAbility extends ActivatedAbilityImpl { @Override public String getRule() { - StringBuilder sbRule = new StringBuilder("Retrace"); - - return sbRule.toString(); + return "Retrace (You may cast this card from your graveyard by discarding a land card in addition to paying its other costs.)"; } } class RetraceEffect extends OneShotEffect { diff --git a/Mage/src/mage/abilities/keyword/SpliceOntoArcaneAbility.java b/Mage/src/mage/abilities/keyword/SpliceOntoArcaneAbility.java new file mode 100644 index 00000000000..299aaf3cc7f --- /dev/null +++ b/Mage/src/mage/abilities/keyword/SpliceOntoArcaneAbility.java @@ -0,0 +1,208 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.keyword; + +import java.util.Iterator; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.CostsImpl; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.SpliceCardEffectImpl; +import mage.cards.Card; +import mage.cards.CardsImpl; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SpellAbilityType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; + + +/** + * 702.45. Splice + * + * 702.45a Splice is a static ability that functions while a card is in your hand. + * "Splice onto [subtype] [cost]" means "You may reveal this card from your hand + * as you cast a [subtype] spell. If you do, copy this card's text box onto that + * spell and pay [cost] as an additional cost to cast that spell." Paying a card's + * splice cost follows the rules for paying additional costs in rules 601.2b and + * 601.2e-g. + * + * Example: Since the card with splice remains in the player's hand, it can later + * be cast normally or spliced onto another spell. It can even be discarded to pay + * a "discard a card" cost of the spell it's spliced onto. + * + * 702.45b You can't choose to use a splice ability if you can't make the required + * choices (targets, etc.) for that card's instructions. You can't splice any one + * card onto the same spell more than once. If you're splicing more than one card + * onto a spell, reveal them all at once and choose the order in which their + * instructions will be followed. The instructions on the main spell have to be + * followed first. + * + * 702.45c The spell has the characteristics of the main spell, plus the text boxes + * of each of the spliced cards. The spell doesn't gain any other characteristics + * (name, mana cost, color, supertypes, card types, subtypes, etc.) of the spliced + * cards. Text copied onto the spell that refers to a card by name refers to the spell + * on the stack, not the card from which the text was copied. + * + * Example: Glacial Ray is a red card with splice onto Arcane that reads, "Glacial + * Ray deals 2 damage to target creature or player." Suppose Glacial Ray is spliced + * onto Reach Through Mists, a blue spell. The spell is still blue, and Reach Through + * Mists deals the damage. This means that the ability can target a creature with + * protection from red and deal 2 damage to that creature. + * + * 702.45d Choose targets for the added text normally (see rule 601.2c). Note that a + * spell with one or more targets will be countered if all of its targets are illegal + * on resolution. + * + * 702.45e The spell loses any splice changes once it leaves the stack (for example, + * when it's countered, it's exiled, or it resolves). + * + * Rulings + * + * You must reveal all of the cards you intend to splice at the same time. Each individual card can only be spliced once onto a spell. + * If you have more than one card with the same name in your hand, you may splice both of them onto the spell. + * A card with a splice ability can't be spliced onto itself because the spell is on the stack (and not in your hand) when you reveal the cards you want to splice onto it. + * The target for a card that's spliced onto a spell may be the same as the target chosen for the original spell or for another spliced-on card. (A recent change to the targeting rules allows this, but most other cards are unaffected by the change.) + * If you splice a targeted card onto an untargeted spell, the entire spell will be countered if the target isn't legal when the spell resolves. + * If you splice an untargeted card onto a targeted spell, the entire spell will be countered if the target isn't legal when the spell resolves. + * A spell is countered on resolution only if *all* of its targets are illegal (or the spell is countered by an effect). + * + * @author LevelX2 + */ + + +public class SpliceOntoArcaneAbility extends SimpleStaticAbility { + + private static final String KEYWORD_TEXT = "Splice onto Arcane"; + private Costs spliceCosts = new CostsImpl(); + private boolean nonManaCosts = false; + + public SpliceOntoArcaneAbility(String manaString) { + super(Zone.HAND, new SpliceOntoArcaneEffect()); + spliceCosts.add(new ManaCostsImpl(manaString)); + } + + public SpliceOntoArcaneAbility(Cost cost) { + super(Zone.HAND, new SpliceOntoArcaneEffect()); + spliceCosts.add(cost); + nonManaCosts = true; + } + + public SpliceOntoArcaneAbility(final SpliceOntoArcaneAbility ability) { + super(ability); + this.spliceCosts = ability.spliceCosts.copy(); + this.nonManaCosts = ability.nonManaCosts; + } + + @Override + public SimpleStaticAbility copy() { + return new SpliceOntoArcaneAbility(this); + } + + public Costs getSpliceCosts() { + return spliceCosts; + } + + @Override + public String getRule() { + StringBuilder sb = new StringBuilder(); + sb.append(KEYWORD_TEXT).append(nonManaCosts?"-":" "); + sb.append(spliceCosts.getText()).append(nonManaCosts?". ":" "); + sb.append("(As you cast an Arcane spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell.)"); + return sb.toString(); + } +} + + +class SpliceOntoArcaneEffect extends SpliceCardEffectImpl { + + public SpliceOntoArcaneEffect() { + super(Duration.WhileOnBattlefield, Outcome.Copy); + staticText = "Splice onto Arcane"; + } + + public SpliceOntoArcaneEffect(final SpliceOntoArcaneEffect effect) { + super(effect); + } + + + + @Override + public SpliceOntoArcaneEffect copy() { + return new SpliceOntoArcaneEffect(this); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + Player controller = game.getPlayer(source.getControllerId()); + Card spliceCard = game.getCard(source.getSourceId()); + if (spliceCard != null && controller != null) { + Spell spell = game.getStack().getSpell(abilityToModify.getId()); + if (spell != null) { + SpellAbility splicedAbility = spliceCard.getSpellAbility().copy(); + splicedAbility.setSpellAbilityType(SpellAbilityType.SPLICE); + splicedAbility.setSourceId(abilityToModify.getSourceId()); + spell.addSpellAbility(splicedAbility); + for (Iterator it = ((SpliceOntoArcaneAbility) source).getSpliceCosts().iterator(); it.hasNext();) { + Cost cost = (Cost) it.next(); + if (cost instanceof ManaCostsImpl) { + spell.getSpellAbility().getManaCostsToPay().add((ManaCostsImpl) cost.copy()); + } else { + spell.getSpellAbility().getCosts().add(cost.copy()); + } + } + } + return true; + } + return false; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + MageObject object = game.getObject(abilityToModify.getSourceId()); + if (object != null && object.getSubtype().contains("Arcane")) { + return spliceSpellCanBeActivated(source, game); + } + return false; + } + + private boolean spliceSpellCanBeActivated(Ability source, Game game) { + // check if spell can be activated (protection problem not solved because effect will be used from the base spell?) + Card card = game.getCard(source.getSourceId()); + if (card != null) { + return card.getSpellAbility().canActivate(source.getControllerId(), game); + } + return false; + } +} diff --git a/Mage/src/mage/abilities/keyword/SunburstAbility.java b/Mage/src/mage/abilities/keyword/SunburstAbility.java index c399361a14a..c7271b2fcd8 100644 --- a/Mage/src/mage/abilities/keyword/SunburstAbility.java +++ b/Mage/src/mage/abilities/keyword/SunburstAbility.java @@ -33,6 +33,7 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.SunburstCount; import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; import mage.constants.CardType; import mage.constants.Outcome; import mage.counters.Counter; @@ -49,12 +50,18 @@ import mage.players.Player; public class SunburstAbility extends EntersBattlefieldAbility{ - public SunburstAbility(){ + private final static String ruleCreature ="Sunburst (This enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.)"; + private final static String ruleNonCreature ="Sunburst (This enters the battlefield with a charge counter on it for each color of mana spent to cast it.)"; + private boolean isCreature; + + public SunburstAbility(Card card){ super(new SunburstEffect(),""); + isCreature = card.getCardType().contains(CardType.CREATURE); } public SunburstAbility(final SunburstAbility ability){ super(ability); + this.isCreature = ability.isCreature; } @@ -65,7 +72,7 @@ public class SunburstAbility extends EntersBattlefieldAbility{ @Override public String getRule() { - return "Sunburst"; + return isCreature ? ruleCreature : ruleNonCreature; } @@ -114,5 +121,4 @@ class SunburstEffect extends OneShotEffect { return new SunburstEffect(this); } - -} \ No newline at end of file +} diff --git a/Mage/src/mage/abilities/keyword/SuspendAbility.java b/Mage/src/mage/abilities/keyword/SuspendAbility.java index 0510cbe2d42..567b84df65e 100644 --- a/Mage/src/mage/abilities/keyword/SuspendAbility.java +++ b/Mage/src/mage/abilities/keyword/SuspendAbility.java @@ -28,6 +28,8 @@ package mage.abilities.keyword; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import mage.constants.AsThoughEffectType; import mage.constants.CardType; @@ -42,7 +44,6 @@ import mage.abilities.Ability; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.SuspendedCondition; import mage.abilities.costs.mana.ManaCost; import mage.abilities.decorator.ConditionalTriggeredAbility; @@ -139,44 +140,53 @@ import mage.players.Player; public class SuspendAbility extends ActivatedAbilityImpl { private String ruleText; + private boolean gainedTemporary; + private boolean shortRule; + /** + * Gives the card the SuspendAbility + * + * @param suspend - amount of time counters + * @param cost - null is used for temporary gained suspend ability + * @param card - card that has the suspend ability + */ public SuspendAbility(int suspend, ManaCost cost, Card card) { + this(suspend, cost, card, false); + } + + public SuspendAbility(int suspend, ManaCost cost, Card card, boolean shortRule) { super(Zone.HAND, new SuspendExileEffect(suspend), cost); this.usesStack = false; - ruleText = new StringBuilder("Suspend ").append(suspend).append(" - ").append(cost.getText()) - .append(" (Rather than cast this card from your hand, pay ") - .append(cost.getText()) - .append(" and exile it with ") - .append(suspend == 1 ? "a time counter":suspend + " time counters") - .append(" on it.") - .append(" At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost.") - .append(card.getCardType().contains(CardType.CREATURE)? " If you play it this way and it's a creature, it gains haste until you lose control of it.":"") - .append(")") - .toString(); + this.shortRule = shortRule; + StringBuilder sb = new StringBuilder("Suspend "); + if (cost != null) { + sb.append(suspend).append(" - ").append(cost.getText()); + if (!shortRule) { + sb.append(" (Rather than cast this card from your hand, pay ") + .append(cost.getText()) + .append(" and exile it with ") + .append(suspend == 1 ? "a time counter":suspend + " time counters") + .append(" on it.") + .append(" At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost.") + .append(card.getCardType().contains(CardType.CREATURE)? " If you play it this way and it's a creature, it gains haste until you lose control of it.":"") + .append(")"); + } + } else { + gainedTemporary = true; + } + ruleText = sb.toString(); if (card.getManaCost().isEmpty()) { setRuleAtTheTop(true); - } - - // add triggered ability to remove the counter from the card - Ability ability = new ConditionalTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), TargetController.YOU, false), - SuspendedCondition.getInstance(), - "At the beginning of your upkeep, if this card is suspended, remove a time counter from it."); - ability.setRuleVisible(false); - card.addAbility(ability); - // add triggered ability that casts the suspended card, if all counters are removed + } + card.addAbility(new SuspendBeginningOfUpkeepTriggeredAbility()); card.addAbility(new SuspendPlayCardAbility(card.getCardType().contains(CardType.CREATURE))); - // if it's a creature card, add Haste ability - if (card.getCardType().contains(CardType.CREATURE)) { - ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainHasteEffect(Duration.WhileOnBattlefield)); - ability.setRuleVisible(false); - card.addAbility(ability); - } } public SuspendAbility(SuspendAbility ability) { super(ability); this.ruleText = ability.getRule(); + this.gainedTemporary = ability.gainedTemporary; + this.shortRule = ability.shortRule; } @Override @@ -196,6 +206,10 @@ public class SuspendAbility extends ActivatedAbilityImpl { return ruleText; } + public boolean isGainedTemporary() { + return gainedTemporary; + } + @Override public SuspendAbility copy() { return new SuspendAbility(this); @@ -252,6 +266,9 @@ class SuspendPlayCardAbility extends TriggeredAbilityImpl { public SuspendPlayCardEffect(boolean isCreature) { super(Outcome.PutCardInPlay); - this.staticText = new StringBuilder("play it without paying its mana cost if able. If you can't, it remains removed from the game") - .append(isCreature ? ". If you play it this way and it's a creature, it gains haste until you lose control of it":"").toString(); + this.staticText = "play it without paying its mana cost if able. If you can't, it remains removed from the game"; } public SuspendPlayCardEffect(final SuspendPlayCardEffect effect) { @@ -301,9 +317,33 @@ class SuspendPlayCardEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); Card card = game.getCard(source.getSourceId()); if (player != null && card != null) { + // remove temporary suspend ability (used e.g. for Epochrasite) + List abilitiesToRemove = new ArrayList(); + for (Ability ability : card.getAbilities()) { + if (ability instanceof SuspendAbility) { + if (((SuspendAbility)ability).isGainedTemporary()) { + abilitiesToRemove.add(ability); + } + } + } + if (!abilitiesToRemove.isEmpty()) { + for (Ability ability : card.getAbilities()) { + if (ability instanceof SuspendBeginningOfUpkeepTriggeredAbility || ability instanceof SuspendPlayCardAbility ) { + abilitiesToRemove.add(ability); + } + } + // remove the triggered abilities from the game + game.getState().resetTriggersForSourceId(card.getId()); + // remove the continious effects from the game + game.getState().getContinuousEffects().removeGainedEffectsForSource(card.getId()); + // remove the abilities from the card + card.getAbilities().removeAll(abilitiesToRemove); + } + // cast the card for free player.cast(card.getSpellAbility(), game, true); } return false; @@ -314,8 +354,8 @@ class GainHasteEffect extends ContinuousEffectImpl { private UUID suspendController; - public GainHasteEffect(Duration duration) { - super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + public GainHasteEffect() { + super(Duration.Custom, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); staticText = "If you play it this way and it's a creature, it gains haste until you lose control of it"; } @@ -336,14 +376,34 @@ class GainHasteEffect extends ContinuousEffectImpl { } Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - if (suspendController.equals(source.getControllerId()) && !used) { // used stores if the control changed + if (suspendController.equals(source.getControllerId())) { permanent.addAbility(HasteAbility.getInstance(), source.getSourceId(), game); return true; } else { - used = true; + this.discard(); } } return false; } } + +class SuspendBeginningOfUpkeepTriggeredAbility extends ConditionalTriggeredAbility { + + public SuspendBeginningOfUpkeepTriggeredAbility() { + super(new BeginningOfUpkeepTriggeredAbility(Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), TargetController.YOU, false), + SuspendedCondition.getInstance(), + "At the beginning of your upkeep, if this card is suspended, remove a time counter from it."); + this.setRuleVisible(false); + + } + + public SuspendBeginningOfUpkeepTriggeredAbility(final SuspendBeginningOfUpkeepTriggeredAbility effect) { + super(effect); + } + + @Override + public SuspendBeginningOfUpkeepTriggeredAbility copy() { + return new SuspendBeginningOfUpkeepTriggeredAbility(this); + } +} \ No newline at end of file diff --git a/Mage/src/mage/abilities/keyword/UnearthAbility.java b/Mage/src/mage/abilities/keyword/UnearthAbility.java index 4d08f2ca605..59a84127fae 100644 --- a/Mage/src/mage/abilities/keyword/UnearthAbility.java +++ b/Mage/src/mage/abilities/keyword/UnearthAbility.java @@ -28,10 +28,6 @@ package mage.abilities.keyword; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.TimingRule; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.ActivatedAbilityImpl; import mage.abilities.DelayedTriggeredAbility; @@ -39,8 +35,12 @@ import mage.abilities.costs.mana.ManaCosts; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ExileSourceEffect; -import mage.abilities.effects.common.continious.GainAbilitySourceEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; +import mage.abilities.effects.common.continious.GainAbilitySourceEffect; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TimingRule; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; @@ -49,11 +49,19 @@ import mage.game.events.ZoneChangeEvent; /** * * @author BetaSteward_at_googlemail.com + * + * + * 702.82. Unearth + * + * 702.82a Unearth is an activated ability that functions while the card with unearth + * is in a graveyard. "Unearth [cost]" means "[Cost]: Return this card from your graveyard + * to the battlefield. It gains haste. Exile it at the beginning of the next end step. + * If it would leave the battlefield, exile it instead of putting it anywhere else. + * Activate this ability only any time you could cast a sorcery." + * */ public class UnearthAbility extends ActivatedAbilityImpl { - protected boolean unearthed; - public UnearthAbility(ManaCosts costs) { super(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(), costs); this.timing = TimingRule.SORCERY; @@ -64,7 +72,6 @@ public class UnearthAbility extends ActivatedAbilityImpl { public UnearthAbility(final UnearthAbility ability) { super(ability); - this.unearthed = ability.unearthed; } @Override @@ -72,13 +79,12 @@ public class UnearthAbility extends ActivatedAbilityImpl { return new UnearthAbility(this); } - public boolean isUnearthed() { - return unearthed; - } - @Override public String getRule() { - return "Unearth " + super.getRule(); + StringBuilder sb = new StringBuilder("Unearth ").append(this.getManaCosts().getText()); + sb.append(" (").append(this.getManaCosts().getText()); + sb.append(": Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a sorcery.)"); + return sb.toString(); } } @@ -133,8 +139,9 @@ class UnearthLeavesBattlefieldEffect extends ReplacementEffectImpl> extends MageObjectImpl case LIBRARY: game.getPlayer(ownerId).removeFromLibrary(this, game); break; + case EXILED: + game.getExile().removeCard(this, game); + break; default: logger.warn("moveToExile, not fully implemented: from="+fromZone); } diff --git a/Mage/src/mage/cards/decks/importer/DeckImporter.java b/Mage/src/mage/cards/decks/importer/DeckImporter.java index 6af78ca0cf2..0f50787b9a5 100644 --- a/Mage/src/mage/cards/decks/importer/DeckImporter.java +++ b/Mage/src/mage/cards/decks/importer/DeckImporter.java @@ -46,6 +46,10 @@ public abstract class DeckImporter { public DeckCardLists importDeck(String file) { File f = new File(file); DeckCardLists deckList = new DeckCardLists(); + if (!f.exists()) { + logger.warn("Deckfile " + file + " not found."); + return deckList; + } lineCount = 0; sbMessage.setLength(0); try { diff --git a/Mage/src/mage/constants/EffectType.java b/Mage/src/mage/constants/EffectType.java index b83b5f3891c..aa483ea23c4 100644 --- a/Mage/src/mage/constants/EffectType.java +++ b/Mage/src/mage/constants/EffectType.java @@ -14,7 +14,8 @@ public enum EffectType { ASTHOUGH("As Though Effect"), RESTRICTION("Restriction Effect"), REQUIREMENT("Requirement Effect"), - COSTMODIFICATION("Cost Modification Effect"); + COSTMODIFICATION("Cost Modification Effect"), + SPLICE("Splice Card Effect"); private String text; diff --git a/Mage/src/mage/constants/MatchTimeLimit.java b/Mage/src/mage/constants/MatchTimeLimit.java new file mode 100644 index 00000000000..40e8444f90a --- /dev/null +++ b/Mage/src/mage/constants/MatchTimeLimit.java @@ -0,0 +1,42 @@ +package mage.constants; + +/** + * The time per player to have activity in a match. + * If time runs out for a player, he looses the currently running game of a match. + * + * @author LevelX2 + */ +public enum MatchTimeLimit { + NONE(0,"None"), + MIN__10(600, "10 Minutes"), + MIN__15(900, "15 Minutes"), + MIN__20(1200, "20 Minutes"), + MIN__25(1500, "25 Minutes"), + MIN__30(1800, "30 Minutes"), + MIN__40(2400, "40 Minutes"), + MIN__50(3000, "50 Minutes"), + MIN__60(3600, "60 Minutes"), + MIN__90(5400, "90 Minutes"), + MIN_120(7200, "120 Minutes"); + + private int matchSeconds; + private String name; + + MatchTimeLimit(int matchSeconds, String name) { + this.matchSeconds = matchSeconds; + this.name = name; + } + + public int getTimeLimit() { + return matchSeconds; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/Mage/src/mage/filter/common/FilterControlledCreaturePermanent.java b/Mage/src/mage/filter/common/FilterControlledCreaturePermanent.java index 4d69b6393db..5831922c2f3 100644 --- a/Mage/src/mage/filter/common/FilterControlledCreaturePermanent.java +++ b/Mage/src/mage/filter/common/FilterControlledCreaturePermanent.java @@ -30,6 +30,7 @@ package mage.filter.common; import mage.constants.CardType; import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; /** * @@ -44,6 +45,13 @@ public class FilterControlledCreaturePermanent extends FilterControlledPermanent public FilterControlledCreaturePermanent(String name) { super(name); this.add(new CardTypePredicate(CardType.CREATURE)); + } + + + public FilterControlledCreaturePermanent(String subtype, String name) { + super(name); + this.add(new CardTypePredicate(CardType.CREATURE)); + this.add(new SubtypePredicate(subtype)); } public FilterControlledCreaturePermanent(final FilterControlledCreaturePermanent filter) { diff --git a/Mage/src/mage/filter/common/FilterCreaturePermanent.java b/Mage/src/mage/filter/common/FilterCreaturePermanent.java index b23a54be977..290176f307d 100644 --- a/Mage/src/mage/filter/common/FilterCreaturePermanent.java +++ b/Mage/src/mage/filter/common/FilterCreaturePermanent.java @@ -31,6 +31,7 @@ package mage.filter.common; import mage.constants.CardType; import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; /** * @@ -45,6 +46,12 @@ public class FilterCreaturePermanent extends FilterPermanent { public FilterCreaturePermanent(String name) { super(name); this.add(new CardTypePredicate(CardType.CREATURE)); + } + + public FilterCreaturePermanent(String subtype, String name) { + super(name); + this.add(new CardTypePredicate(CardType.CREATURE)); + this.add(new SubtypePredicate(subtype)); } public FilterCreaturePermanent(final FilterCreaturePermanent filter) { diff --git a/Mage/src/mage/filter/predicate/permanent/CounterPredicate.java b/Mage/src/mage/filter/predicate/permanent/CounterPredicate.java index 1096383d4d2..4c8852246fa 100644 --- a/Mage/src/mage/filter/predicate/permanent/CounterPredicate.java +++ b/Mage/src/mage/filter/predicate/permanent/CounterPredicate.java @@ -27,16 +27,16 @@ */ package mage.filter.predicate.permanent; +import mage.cards.Card; import mage.counters.CounterType; import mage.filter.predicate.Predicate; import mage.game.Game; -import mage.game.permanent.Permanent; /** * * @author jeff */ -public class CounterPredicate implements Predicate { +public class CounterPredicate implements Predicate { private final CounterType counter; @@ -45,7 +45,7 @@ public class CounterPredicate implements Predicate { } @Override - public boolean apply(Permanent input, Game game) { + public boolean apply(Card input, Game game) { return input.getCounters().containsKey(counter); } diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index c4f2b06bd81..5eedb6188c6 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -28,9 +28,6 @@ package mage.game; -import mage.constants.MultiplayerAttackOption; -import mage.constants.RangeOfInfluence; -import mage.constants.Zone; import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; @@ -44,6 +41,10 @@ import mage.cards.Card; import mage.cards.Cards; import mage.cards.decks.Deck; import mage.choices.Choice; +import mage.constants.Duration; +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; +import mage.constants.Zone; import mage.game.combat.Combat; import mage.game.command.Emblem; import mage.game.events.GameEvent; @@ -65,7 +66,6 @@ import mage.util.functions.ApplyToPermanent; import java.io.Serializable; import java.util.*; -import mage.constants.Duration; public interface Game extends MageItem, Serializable { @@ -225,4 +225,11 @@ public interface Game extends MageItem, Serializable { // controlling the behaviour of replacement effects void setScopeRelevant(boolean scopeRelevant); public boolean getScopeRelevant(); + + // players' timers + void initTimer(UUID playerId); + void resumeTimer(UUID playerId); + void pauseTimer(UUID playerId); + int getPriorityTime(); + void setPriorityTime(int priorityTime); } diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index f7fa2fc9758..e73cd74e881 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -29,7 +29,6 @@ package mage.game; import mage.Constants; -import mage.constants.CardType; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; @@ -49,12 +48,14 @@ import mage.actions.impl.MageAction; import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; +import mage.cards.SplitCard; import mage.cards.decks.Deck; import mage.choices.Choice; import mage.constants.*; import mage.counters.CounterType; import mage.filter.Filter; import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterPlaneswalkerPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.NamePredicate; @@ -89,8 +90,6 @@ import java.io.IOException; import java.io.Serializable; import java.util.*; import java.util.Map.Entry; -import mage.cards.SplitCard; -import mage.filter.common.FilterControlledCreaturePermanent; public abstract class GameImpl> implements Game, Serializable { @@ -156,6 +155,8 @@ public abstract class GameImpl> implements Game, Serializa // used to indicate that currently applied replacement effects have to check for scope relevance (614.12 13/01/18) private boolean scopeRelevant = false; + private int priorityTime; + @Override public abstract T copy(); @@ -199,6 +200,7 @@ public abstract class GameImpl> implements Game, Serializa this.stateCheckRequired = game.stateCheckRequired; this.scorePlayer = game.scorePlayer; this.scopeRelevant = game.scopeRelevant; + this.priorityTime = game.priorityTime; } @Override @@ -590,6 +592,9 @@ public abstract class GameImpl> implements Game, Serializa protected void init(UUID choosingPlayerId, GameOptions gameOptions) { for (Player player: state.getPlayers().values()) { player.beginTurn(this); + if (priorityTime > 0) { + initTimer(player.getId()); + } } if (startMessage == null || startMessage.isEmpty()) { startMessage = "Game has started"; @@ -1060,7 +1065,9 @@ public abstract class GameImpl> implements Game, Serializa public void addTriggeredAbility(TriggeredAbility ability) { if (ability instanceof TriggeredManaAbility || ability instanceof DelayedTriggeredManaAbility) { // 20110715 - 605.4 - ability.resolve(this); + Ability manaAbiltiy = ability.copy(); + manaAbiltiy.activate(this, false); + manaAbiltiy.resolve(this); } else { TriggeredAbility newAbility = (TriggeredAbility) ability.copy(); @@ -1946,4 +1953,35 @@ public abstract class GameImpl> implements Game, Serializa public void setStartMessage(String startMessage) { this.startMessage = startMessage; } + + @Override + public void initTimer(UUID playerId) { + if (priorityTime > 0) { + tableEventSource.fireTableEvent(EventType.INIT_TIMER, playerId, null, this); + } + } + + @Override + public void resumeTimer(UUID playerId) { + if (priorityTime > 0) { + tableEventSource.fireTableEvent(EventType.RESUME_TIMER, playerId, null, this); + } + } + + @Override + public void pauseTimer(UUID playerId) { + if (priorityTime > 0) { + tableEventSource.fireTableEvent(EventType.PAUSE_TIMER, playerId, null, this); + } + } + + @Override + public int getPriorityTime() { + return priorityTime; + } + + @Override + public void setPriorityTime(int priorityTime) { + this.priorityTime = priorityTime; + } } diff --git a/Mage/src/mage/game/events/TableEvent.java b/Mage/src/mage/game/events/TableEvent.java index b9c9041cead..6d6637b4220 100644 --- a/Mage/src/mage/game/events/TableEvent.java +++ b/Mage/src/mage/game/events/TableEvent.java @@ -46,7 +46,8 @@ import java.util.UUID; public class TableEvent extends EventObject implements ExternalEvent, Serializable { public enum EventType { - UPDATE, INFO, STATUS, REVEAL, LOOK, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, ERROR + UPDATE, INFO, STATUS, REVEAL, LOOK, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, ERROR, + INIT_TIMER, RESUME_TIMER, PAUSE_TIMER } private Game game; diff --git a/Mage/src/mage/game/match/MatchImpl.java b/Mage/src/mage/game/match/MatchImpl.java index 4d11d3e3499..5fcb9b018c2 100644 --- a/Mage/src/mage/game/match/MatchImpl.java +++ b/Mage/src/mage/game/match/MatchImpl.java @@ -162,6 +162,7 @@ public abstract class MatchImpl implements Match { game.loadCards(matchPlayer.getDeck().getSideboard(), matchPlayer.getPlayer().getId()); game.addPlayer(matchPlayer.getPlayer(), matchPlayer.getDeck()); } + game.setPriorityTime(options.getPriorityTime()); } protected void shufflePlayers() { diff --git a/Mage/src/mage/game/match/MatchOptions.java b/Mage/src/mage/game/match/MatchOptions.java index 72aee136ee6..b54e3adabb3 100644 --- a/Mage/src/mage/game/match/MatchOptions.java +++ b/Mage/src/mage/game/match/MatchOptions.java @@ -31,6 +31,7 @@ package mage.game.match; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import mage.constants.MatchTimeLimit; import mage.constants.MultiplayerAttackOption; import mage.constants.RangeOfInfluence; @@ -49,6 +50,10 @@ public class MatchOptions implements Serializable { protected String deckType; protected boolean limited; protected List playerTypes = new ArrayList(); + /** + * Time each player has during the game to play using his\her priority. + */ + protected MatchTimeLimit matchTimeLimit; // 0 = no priorityTime handling public MatchOptions(String name, String gameType) { this.name = name; @@ -90,6 +95,7 @@ public class MatchOptions implements Serializable { public void setFreeMulligans(int freeMulligans) { this.freeMulligans = freeMulligans; } + public String getGameType() { return gameType; } @@ -117,4 +123,16 @@ public class MatchOptions implements Serializable { public void setLimited(boolean limited) { this.limited = limited; } + + public int getPriorityTime() { + if (matchTimeLimit == null) { + return MatchTimeLimit.NONE.getTimeLimit(); + } + return matchTimeLimit.getTimeLimit(); + } + + public void setMatchTimeLimit(MatchTimeLimit matchTimeLimit) { + this.matchTimeLimit = matchTimeLimit; + } + } diff --git a/Mage/src/mage/game/permanent/token/Token.java b/Mage/src/mage/game/permanent/token/Token.java index 75355cecb6f..743e1459f6c 100644 --- a/Mage/src/mage/game/permanent/token/Token.java +++ b/Mage/src/mage/game/permanent/token/Token.java @@ -49,6 +49,8 @@ public class Token extends MageObjectImpl { protected String description; private UUID lastAddedTokenId; private int tokenType; + private int originalCardNumber; + private String originalExpansionSetCode; public enum Type { FIRST(1), @@ -146,4 +148,21 @@ public class Token extends MageObjectImpl { public void setTokenType(int tokenType) { this.tokenType = tokenType; } + + public int getOriginalCardNumber() { + return originalCardNumber; + } + + public void setOriginalCardNumber(int originalCardNumber) { + this.originalCardNumber = originalCardNumber; + } + + public String getOriginalExpansionSetCode() { + return originalExpansionSetCode; + } + + public void setOriginalExpansionSetCode(String originalExpansionSetCode) { + this.originalExpansionSetCode = originalExpansionSetCode; + } + } diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 006ea540017..fab094b1409 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -118,9 +118,21 @@ public class Spell> implements StackObject, Card { public boolean activate(Game game, boolean noMana) { + if (!spellAbilities.get(0).activate(game, noMana)) { + return false; + } + // if there are more abilities (fused split spell) or first ability added new abilities (splice), activate the additional abilities + boolean ignoreAbility = true; + boolean payNoMana = noMana; for (SpellAbility spellAbility: spellAbilities) { - if (!spellAbility.activate(game, noMana)) { - return false; + // costs for spliced abilities were added to main spellAbility, so pay no man for spliced abilities + payNoMana |= spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE); + if (ignoreAbility) { + ignoreAbility = false; + } else { + if (!spellAbility.activate(game, payNoMana)) { + return false; + } } } return true; @@ -138,10 +150,15 @@ public class Spell> implements StackObject, Card { result = false; boolean legalParts = false; for(SpellAbility spellAbility: this.spellAbilities) { - if (spellAbility.getTargets().stillLegal(spellAbility, game)) { - legalParts = true; - updateOptionalCosts(index); - result |= spellAbility.resolve(game); + for (UUID modeId :spellAbility.getModes().getSelectedModes()) { + spellAbility.getModes().setMode(spellAbility.getModes().get(modeId)); + if (spellAbility.getTargets().stillLegal(spellAbility, game)) { + legalParts = true; + if (!spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE)) { + updateOptionalCosts(index); + } + result |= spellAbility.resolve(game); + } } index++; } @@ -226,13 +243,16 @@ public class Spell> implements StackObject, Card { String name = null; if (object == null) { Player targetPlayer = game.getPlayer(targetId); - if (targetPlayer != null) name = targetPlayer.getName(); + if (targetPlayer != null) { + name = targetPlayer.getName(); + } } else { name = object.getName(); } if (name != null && player.chooseUse(spellAbility.getEffects().get(0).getOutcome(), "Change target from " + name + "?", game)) { - if (!player.chooseTarget(spellAbility.getEffects().get(0).getOutcome(), newTarget, spellAbility, game)) + if (!player.chooseTarget(spellAbility.getEffects().get(0).getOutcome(), newTarget, spellAbility, game)) { newTarget.addTarget(targetId, spellAbility, game, false); + } } else { newTarget.addTarget(targetId, spellAbility, game, false); @@ -345,6 +365,10 @@ public class Spell> implements StackObject, Card { return card.getOwnerId(); } + public void addSpellAbility(SpellAbility spellAbility) { + spellAbilities.add(spellAbility); + } + @Override public void addAbility(Ability ability) {} diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index b755ad8cc69..45134926757 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -299,4 +299,18 @@ public interface Player extends MageItem, Copyable { * */ void revealFaceDownCard(Card card, Game game); + + /** + * Set seconds left to play the game. + * + * @return + */ + void setPriorityTimeLeft(int timeLeft); + + /** + * Returns seconds left to play the game. + * + * @return + */ + int getPriorityTimeLeft(); } diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 9ba6065ec4b..12bdedd2e58 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -28,8 +28,6 @@ package mage.players; -import mage.constants.*; -import mage.constants.Zone; import mage.MageObject; import mage.Mana; import mage.abilities.*; @@ -46,10 +44,13 @@ import mage.actions.MageDrawAction; import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; +import mage.cards.SplitCard; import mage.cards.decks.Deck; +import mage.constants.*; import mage.counters.Counter; import mage.counters.CounterType; import mage.counters.Counters; +import mage.filter.FilterCard; import mage.filter.common.FilterCreatureForCombat; import mage.game.ExileZone; import mage.game.Game; @@ -59,11 +60,13 @@ import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; +import mage.game.stack.Spell; import mage.game.stack.StackAbility; import mage.game.stack.StackObject; import mage.players.net.UserData; import mage.target.Target; import mage.target.TargetAmount; +import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetDiscard; import mage.watchers.common.BloodthirstWatcher; @@ -72,11 +75,6 @@ import org.apache.log4j.Logger; import java.io.Serializable; import java.util.*; -import mage.cards.SplitCard; -import mage.filter.FilterCard; -import mage.game.stack.Spell; -import mage.target.TargetCard; - public abstract class PlayerImpl> implements Player, Serializable { @@ -108,6 +106,7 @@ public abstract class PlayerImpl> implements Player, Ser protected boolean passedTurn; protected int turns; protected int storedBookmark = -1; + protected int priorityTimeLeft = Integer.MAX_VALUE; /** * This indicates that player passed all turns until his own turn starts. @@ -1793,4 +1792,14 @@ public abstract class PlayerImpl> implements Player, Ser this.revealCards(name, cards, game); } } + + @Override + public void setPriorityTimeLeft(int timeLeft) { + priorityTimeLeft = timeLeft; + } + + @Override + public int getPriorityTimeLeft() { + return priorityTimeLeft; + } } diff --git a/Mage/src/mage/target/common/TargetCardInExile.java b/Mage/src/mage/target/common/TargetCardInExile.java index 4322d0dd586..c6835dcb43d 100644 --- a/Mage/src/mage/target/common/TargetCardInExile.java +++ b/Mage/src/mage/target/common/TargetCardInExile.java @@ -27,15 +27,17 @@ */ package mage.target.common; -import mage.constants.Zone; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; import mage.abilities.Ability; import mage.cards.Card; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.ExileZone; import mage.game.Game; import mage.target.TargetCard; -import java.util.UUID; /** * @@ -44,26 +46,67 @@ import java.util.UUID; public class TargetCardInExile extends TargetCard { private UUID zoneId; + private boolean allExileZones; public TargetCardInExile(FilterCard filter, UUID zoneId) { this(1, 1, filter, zoneId); } public TargetCardInExile(int minNumTargets, int maxNumTargets, FilterCard filter, UUID zoneId) { + this(minNumTargets, maxNumTargets, filter, zoneId, false); + } + + public TargetCardInExile(int minNumTargets, int maxNumTargets, FilterCard filter, UUID zoneId, boolean allExileZones) { super(minNumTargets, maxNumTargets, Zone.EXILED, filter); this.zoneId = zoneId; + this.allExileZones = allExileZones; this.targetName = filter.getMessage(); } public TargetCardInExile(final TargetCardInExile target) { super(target); this.zoneId = target.zoneId; + this.allExileZones = target.allExileZones; } - @Override + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + if (allExileZones) { + Set possibleTargets = new HashSet(); + for (Card card : game.getExile().getAllCards(game)) { + if (filter.match(card, sourceControllerId, game)) { + possibleTargets.add(card.getId()); + } + } + return possibleTargets; + } else { + return super.possibleTargets(sourceId, sourceControllerId, game); + } + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + if (allExileZones) { + int numberTargets = 0; + for(ExileZone exileZone : game.getExile().getExileZones()) { + numberTargets += exileZone.count(filter, sourceId, sourceControllerId, game); + if (numberTargets >= this.minNumberOfTargets) { + return true; + } + } + return false; + } else { + return super.canChoose(sourceControllerId, game); + } + } + + @Override public boolean canTarget(UUID id, Ability source, Game game) { Card card = game.getCard(id); if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) { + if (allExileZones) { + return filter.match(card, source.getControllerId(), game); + } ExileZone exile; if (zoneId != null) { exile = game.getExile().getExileZone(zoneId); diff --git a/Mage/src/mage/util/CardUtil.java b/Mage/src/mage/util/CardUtil.java index 2a6c6468952..96f3cbca77c 100644 --- a/Mage/src/mage/util/CardUtil.java +++ b/Mage/src/mage/util/CardUtil.java @@ -29,6 +29,7 @@ package mage.util; import java.util.Iterator; +import java.util.UUID; import mage.Mana; import mage.abilities.Ability; @@ -43,6 +44,7 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.VariableManaCost; import mage.cards.Card; import mage.constants.CardType; +import mage.game.Game; import mage.game.permanent.token.Token; import mage.util.functions.CopyFunction; import mage.util.functions.CopyTokenFunction; @@ -365,4 +367,25 @@ public class CardUtil { } return true; } + + /** + * Creates and saves a (card + zoneChangeCounter) specific exileId. + * + * + * @param game + * @param source - source ability + * @return - the specific UUID + */ + public static UUID getCardExileZoneId(Game game, Ability source) { + UUID exileId = null; + Card card = game.getCard(source.getSourceId()); + if (card != null) { + exileId = (UUID) game.getState().getValue(new StringBuilder("SourceExileZone").append(source.getSourceId()).append(card.getZoneChangeCounter()).toString()); + if (exileId == null) { + exileId = UUID.randomUUID(); + game.getState().setValue(new StringBuilder("SourceExileZone").append(source.getSourceId()).append(card.getZoneChangeCounter()).toString(), exileId); + } + } + return exileId; + } } diff --git a/Mage/src/mage/util/functions/CopyTokenFunction.java b/Mage/src/mage/util/functions/CopyTokenFunction.java index 4943f498e56..b83582c791e 100644 --- a/Mage/src/mage/util/functions/CopyTokenFunction.java +++ b/Mage/src/mage/util/functions/CopyTokenFunction.java @@ -79,7 +79,8 @@ public class CopyTokenFunction implements Function { for (String type : sourceObj.getSupertype()) { target.getSupertype().add(type); } - //target.setExpansionSetCode(source.getExpansionSetCode()); + target.setOriginalExpansionSetCode(source.getExpansionSetCode()); + target.setOriginalCardNumber(source.getCardNumber()); target.getAbilities().clear(); for (Ability ability0 : sourceObj.getAbilities()) { diff --git a/Mage/src/mage/watchers/common/ProwlWatcher.java b/Mage/src/mage/watchers/common/ProwlWatcher.java new file mode 100644 index 00000000000..0f8fa533e23 --- /dev/null +++ b/Mage/src/mage/watchers/common/ProwlWatcher.java @@ -0,0 +1,97 @@ +/* + * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * 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.watchers.common; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; +import mage.constants.WatcherScope; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.watchers.WatcherImpl; + +/** + * Watcher stores with which creature subtypes a player made combat damage to + * other players during a turn. + * + * @author LevelX + */ +public class ProwlWatcher extends WatcherImpl { + + private Map> damagingSubtypes = new HashMap>(); + + public ProwlWatcher() { + super("Prowl", WatcherScope.GAME); + } + + public ProwlWatcher(final ProwlWatcher watcher) { + super(watcher); + for (Entry> entry : watcher.damagingSubtypes.entrySet()) { + damagingSubtypes.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public ProwlWatcher copy() { + return new ProwlWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == EventType.DAMAGED_PLAYER) { + DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event; + if (dEvent.isCombatDamage()) { + Permanent creature = game.getPermanent(dEvent.getSourceId()); + if (creature != null) { + Set subtypes = damagingSubtypes.get(creature.getControllerId()); + if (subtypes == null) { + subtypes = new LinkedHashSet(); + } + subtypes.addAll(creature.getSubtype()); + damagingSubtypes.put(creature.getControllerId(), subtypes); + } + } + } + } + + @Override + public void reset() { + super.reset(); + damagingSubtypes.clear(); + } + + public Set getDamagingSubtypes(UUID playerId) { + return damagingSubtypes.get(playerId); + } +} diff --git a/Utils/keywords.txt b/Utils/keywords.txt index 7703191a843..4b4a2e77d18 100644 --- a/Utils/keywords.txt +++ b/Utils/keywords.txt @@ -3,6 +3,7 @@ Bloodthirst|number| Bushido|number| Dredge|number| Evoke|card, manaString| +Entwine|manaString| Soulshift|number| Basic landcycling|cost| Forestcycling|cost| diff --git a/Utils/known-sets.txt b/Utils/known-sets.txt index 64660b8762f..dbd8ed79250 100644 --- a/Utils/known-sets.txt +++ b/Utils/known-sets.txt @@ -13,6 +13,7 @@ Magic 2010|magic2010| Magic 2011|magic2011| Magic 2012|magic2012| Magic 2013|magic2013| +Magic 2014|magic2014| Planechase|planechase| Planechase 2012 Edition|planechase2012| Duel Decks: Elspeth vs. Tezzeret|elspethvstezzeret| diff --git a/Utils/mtg-sets-data.txt b/Utils/mtg-sets-data.txt index 918e837264a..dabe32f3866 100644 --- a/Utils/mtg-sets-data.txt +++ b/Utils/mtg-sets-data.txt @@ -59,6 +59,7 @@ Magic 2010|M10| Magic 2011|M11| Magic 2012|M12| Magic 2013|M13| +Magic 2014|M14| Magic: The Gathering-Commander|CMD| Masters Edition II|ME2| Masters Edition III|ME3|