diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml
index e48d07e8091..13330da5fda 100644
--- a/Mage.Client/pom.xml
+++ b/Mage.Client/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
org.mage
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java
index 4c4ff30e053..88653281241 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MagicCardsImageSource.java
@@ -13,7 +13,7 @@ import org.mage.plugins.card.utils.CardImageUtils;
public class MagicCardsImageSource implements CardImageSource {
private static CardImageSource instance = new MagicCardsImageSource();
-
+
private static final Map setNameTokenReplacement = new HashMap() {
{
put("BFZ", "battle-for-zendikar");
@@ -31,8 +31,8 @@ public class MagicCardsImageSource implements CardImageSource {
put("MM2", "modern-masters-2015");
put("PTC", "prerelease-events");
put("DTK", "dragons-of-tarkir");
- put("GRC","wpngateway");
- put("MBP","media-inserts");
+ put("GRC", "wpngateway");
+ put("MBP", "media-inserts");
put("MLP", "launch-party");
put("WMCQ", "world-magic-cup-qualifier");
put("GPX", "grand-prix");
@@ -40,7 +40,7 @@ public class MagicCardsImageSource implements CardImageSource {
put("MGDC", "magic-game-day-cards");
put("FNMP", "friday-night-magic");
put("FRF", "fate-reforged");
- put("C14", "commander-2014-edition");
+ put("C14", "commander-2014");
put("KTK", "khans-of-tarkir");
put("VMA", "vintage-masters");
put("CNS", "conspiracy");
@@ -130,7 +130,7 @@ public class MagicCardsImageSource implements CardImageSource {
String set = CardImageUtils.updateSet(cardSet, true);
String preferedLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en");
-
+
StringBuilder url = new StringBuilder("http://magiccards.info/scans/").append(preferedLanguage).append("/");
url.append(set.toLowerCase()).append("/").append(collectorId);
diff --git a/Mage.Client/src/main/resources/card-pictures-tok.txt b/Mage.Client/src/main/resources/card-pictures-tok.txt
index ce5970f6821..eee4bed26eb 100644
--- a/Mage.Client/src/main/resources/card-pictures-tok.txt
+++ b/Mage.Client/src/main/resources/card-pictures-tok.txt
@@ -61,14 +61,19 @@
#|Generate|TOK:PTC|Wolf|
#|Generate|TOK:PTC|Wurm|
-#|Generate|TOK:DTK|Djinn Monk|
-#|Generate|TOK:DTK|Dragon|
-#|Generate|TOK:DTK|Goblin|
-#|Generate|TOK:DTK|Morph|
-#|Generate|TOK:DTK|Warrior|
-#|Generate|TOK:DTK|Zombie|
-#|Generate|TOK:DTK|Zombie Horror|
-#|Generate|EMBLEM!:DTK|Emblem Narset Transcendent|
+|Generate|TOK:DTK|Djinn Monk|
+|Generate|TOK:DTK|Dragon|
+|Generate|TOK:DTK|Goblin|
+|Generate|TOK:DTK|Morph|
+|Generate|TOK:DTK|Warrior|
+|Generate|TOK:DTK|Zombie|
+|Generate|TOK:DTK|Zombie Horror|
+|Generate|EMBLEM!:DTK|Emblem Narset|
+
+|Generate|TOK:FRF|Monk|
+|Generate|TOK:FRF|Spirit|
+|Generate|TOK:FRF|Warrior|
+|Generate|TOK:FRF|Manifest|
#|Generate|TOK:GRC|Bird|
#|Generate|TOK:GRC|Golem|
@@ -105,21 +110,59 @@
|Generate|TOK:FNMP|Wolf|
#|Generate|TOK:FNMP|Wurm|
+|Generate|TOK:C14|Angel|
+|Generate|TOK:C14|Cat|
+|Generate|TOK:C14|Goat|
+|Generate|TOK:C14|Kor Soldier|
+|Generate|TOK:C14|Pegasus|
+|Generate|TOK:C14|Soldier|
+|Generate|TOK:C14|Spirit|
+|Generate|TOK:C14|Fish|
+|Generate|TOK:C14|Kraken|
+|Generate|TOK:C14|Whale|
+|Generate|TOK:C14|Zombie 1|
+|Generate|TOK:C14|Demon 1|
+|Generate|TOK:C14|Demon 2|
+|Generate|TOK:C14|Germ|
+|Generate|TOK:C14|Horror|
+|Generate|TOK:C14|Zombie 2|
+|Generate|TOK:C14|Goblin|
+|Generate|TOK:C14|Ape|
+|Generate|TOK:C14|Beast 1|
+|Generate|TOK:C14|Beast 2|
+|Generate|TOK:C14|Elemental|
+|Generate|TOK:C14|Elephant|
+|Generate|TOK:C14|Elf Druid|
+|Generate|TOK:C14|Elf Warrior|
+|Generate|TOK:C14|Treefolk|
+|Generate|TOK:C14|Wolf|
+|Generate|TOK:C14|Gargoyle|
+|Generate|TOK:C14|Myr|
+|Generate|TOK:C14|Pentavite|
+|Generate|TOK:C14|Stoneforged Blade|
+|Generate|TOK:C14|Tuktuk the Returned|
+|Generate|TOK:C14|Wurm 1|
+|Generate|TOK:C14|Wurm 2|
+|Generate|EMBLEM!:C14|Emblem Teferi
+|Generate|EMBLEM!:C14|Emblem Nixilis
+|Generate|EMBLEM!:C14|Emblem Daretti
+
+
|Generate|TOK:DDN|Goblin|
-#|Generate|TOK:KTK|Bear|
-#|Generate|TOK:KTK|Bird|
-#|Generate|TOK:KTK|Goblin|
-#|Generate|TOK:KTK|Morph|
-#|Generate|TOK:KTK|Snake|
-#|Generate|TOK:KTK|Spirit Warrior|
-#|Generate|TOK:KTK|Spirit|
-#|Generate|TOK:KTK|Vampire|
-#|Generate|TOK:KTK|Warrior 1|
-#|Generate|TOK:KTK|Warrior 2|
-#|Generate|TOK:KTK|Zombie|
-#|Generate|EMBLEM!:KTK|Emblem Sarkhan, the Dragonspeaker|
-#|Generate|EMBLEM!:KTK|Emblem Sorin, Solemn Visitor|
+|Generate|TOK:KTK|Bear|
+|Generate|TOK:KTK|Bird|
+|Generate|TOK:KTK|Goblin|
+|Generate|TOK:KTK|Morph|
+|Generate|TOK:KTK|Snake|
+|Generate|TOK:KTK|Spirit Warrior|
+|Generate|TOK:KTK|Spirit|
+|Generate|TOK:KTK|Vampire|
+|Generate|TOK:KTK|Warrior 1|
+|Generate|TOK:KTK|Warrior 2|
+|Generate|TOK:KTK|Zombie|
+|Generate|EMBLEM!:KTK|Emblem Sarkhan|
+|Generate|EMBLEM!:KTK|Emblem Sorin|
|Generate|TOK:M15|Sliver|
|Generate|TOK:M15|Soldier|
@@ -448,4 +491,4 @@
|Generate|TOK:CSP|Marit Lage|
-|Generate|TOK:CHK|Spirit|
\ No newline at end of file
+#|Generate|TOK:CHK|Spirit|
\ No newline at end of file
diff --git a/Mage.Common/pom.xml b/Mage.Common/pom.xml
index 09ab27aea29..d41740ec9f5 100644
--- a/Mage.Common/pom.xml
+++ b/Mage.Common/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
mage-common
diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java
index 3357d3052b3..fd22657ae44 100644
--- a/Mage.Common/src/mage/utils/MageVersion.java
+++ b/Mage.Common/src/mage/utils/MageVersion.java
@@ -40,8 +40,8 @@ public class MageVersion implements Serializable, Comparable {
*/
public final static int MAGE_VERSION_MAJOR = 1;
public final static int MAGE_VERSION_MINOR = 4;
- public final static int MAGE_VERSION_PATCH = 3;
- public final static String MAGE_VERSION_MINOR_PATCH = "v3";
+ public final static int MAGE_VERSION_PATCH = 4;
+ public final static String MAGE_VERSION_MINOR_PATCH = "v0";
public final static String MAGE_VERSION_INFO = "";
private final int major;
diff --git a/Mage.Plugins/Mage.Counter.Plugin/pom.xml b/Mage.Plugins/Mage.Counter.Plugin/pom.xml
index df8cc7328b3..128d50a5ca8 100644
--- a/Mage.Plugins/Mage.Counter.Plugin/pom.xml
+++ b/Mage.Plugins/Mage.Counter.Plugin/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-plugins
- 1.4.3
+ 1.4.4
mage-counter-plugin
diff --git a/Mage.Plugins/Mage.Theme.Plugin/pom.xml b/Mage.Plugins/Mage.Theme.Plugin/pom.xml
index eebc730e4a8..f58f45d1d6d 100644
--- a/Mage.Plugins/Mage.Theme.Plugin/pom.xml
+++ b/Mage.Plugins/Mage.Theme.Plugin/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-plugins
- 1.4.3
+ 1.4.4
mage-theme-plugin
@@ -29,7 +29,7 @@
${project.groupId}
mage-client
- 1.4.3
+ 1.4.4
diff --git a/Mage.Plugins/pom.xml b/Mage.Plugins/pom.xml
index 4e6b8ad8521..e1a1ba632b5 100644
--- a/Mage.Plugins/pom.xml
+++ b/Mage.Plugins/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
mage-plugins
diff --git a/Mage.Server.Console/pom.xml b/Mage.Server.Console/pom.xml
index 77cb534fd1d..8a31921aef7 100644
--- a/Mage.Server.Console/pom.xml
+++ b/Mage.Server.Console/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
org.mage
diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml
index dabc671779d..ed0bd5025fd 100644
--- a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml
+++ b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-deck-constructed
diff --git a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml
index 3ab629a71a6..978f5fe60ea 100644
--- a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml
+++ b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-deck-limited
diff --git a/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml
index 66972c3a272..e42e4d1eb72 100644
--- a/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-game-commanderduel
diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml
index ccfa64fc609..7b4738d4885 100644
--- a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-game-commanderfreeforall
diff --git a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml
index a608c789705..551b33a9650 100644
--- a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-game-freeforall
diff --git a/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml
index 7f1ff12438f..8f037f31689 100644
--- a/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-game-tinyleadersduel
diff --git a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml
index 7c6e74649f0..f5febf5042b 100644
--- a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-game-twoplayerduel
diff --git a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml
index bf21ad2d2fe..cb6012e3f6e 100644
--- a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml
+++ b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-player-ai-draftbot
diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml
index 4495a41f8a6..23942195fde 100644
--- a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml
+++ b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-player-ai-ma
diff --git a/Mage.Server.Plugins/Mage.Player.AI/pom.xml b/Mage.Server.Plugins/Mage.Player.AI/pom.xml
index 51788aff21a..43387e7f257 100644
--- a/Mage.Server.Plugins/Mage.Player.AI/pom.xml
+++ b/Mage.Server.Plugins/Mage.Player.AI/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-player-ai
diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml
index 62c8e069013..5107921f395 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml
+++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-player-ai-mcts
diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml
index 696f0b3043f..c18ef70a712 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml
+++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-player-aiminimax
diff --git a/Mage.Server.Plugins/Mage.Player.Human/pom.xml b/Mage.Server.Plugins/Mage.Player.Human/pom.xml
index 28493362e66..c1b13ea06a1 100644
--- a/Mage.Server.Plugins/Mage.Player.Human/pom.xml
+++ b/Mage.Server.Plugins/Mage.Player.Human/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-player-human
diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml
index 06efa02a054..4bb3a3af1af 100644
--- a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml
+++ b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-tournament-boosterdraft
diff --git a/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml
index 884159dba8a..ece1bd9e9ef 100644
--- a/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml
+++ b/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-tournament-constructed
diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml
index 30abbd2009c..7b3ed663f08 100644
--- a/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml
+++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.3
+ 1.4.4
mage-tournament-sealed
diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml
index 49073190dca..590c8fbc00d 100644
--- a/Mage.Server.Plugins/pom.xml
+++ b/Mage.Server.Plugins/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
mage-server-plugins
diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml
index a3b4db6ffdf..7490945b1e7 100644
--- a/Mage.Server/pom.xml
+++ b/Mage.Server/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
mage-server
diff --git a/Mage.Sets/pom.xml b/Mage.Sets/pom.xml
index a206bff7596..bf208a1fcc7 100644
--- a/Mage.Sets/pom.xml
+++ b/Mage.Sets/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
org.mage
diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/BlightHerder.java b/Mage.Sets/src/mage/sets/battleforzendikar/BlightHerder.java
new file mode 100644
index 00000000000..d6317ebf1bf
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/battleforzendikar/BlightHerder.java
@@ -0,0 +1,118 @@
+/*
+ * 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.battleforzendikar;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.CastSourceTriggeredAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+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.TargetController;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+import mage.filter.predicate.other.OwnerPredicate;
+import mage.game.Game;
+import mage.game.permanent.token.EldraziScionToken;
+import mage.players.Player;
+import mage.target.Target;
+import mage.target.common.TargetCardInExile;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class BlightHerder extends CardImpl {
+
+ public BlightHerder(UUID ownerId) {
+ super(ownerId, 2, "Blight Herder", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}");
+ this.expansionSetCode = "BFZ";
+ this.subtype.add("Eldrazi");
+ this.subtype.add("Processor");
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(5);
+
+ // When you cast Blight Herder, you may put two cards your opponents own from exile into their owners' graveyards. If you do, put three 1/1 colorless Eldrazi Scion creature tokens onto the battlefield. They have "Sacrifice this creature: Add {1} to your mana pool."
+ this.addAbility(new CastSourceTriggeredAbility(new BlightHerderEffect(), true));
+ }
+
+ public BlightHerder(final BlightHerder card) {
+ super(card);
+ }
+
+ @Override
+ public BlightHerder copy() {
+ return new BlightHerder(this);
+ }
+}
+
+class BlightHerderEffect extends OneShotEffect {
+
+ private final static FilterCard filter = new FilterCard("cards your opponents own from exile");
+
+ static {
+ filter.add(new OwnerPredicate(TargetController.OPPONENT));
+ }
+
+ public BlightHerderEffect() {
+ super(Outcome.PutCreatureInPlay);
+ this.staticText = "you may put two cards your opponents own from exile into their owners' graveyards. If you do, put three 1/1 colorless Eldrazi Scion creature tokens onto the battlefield. They have \"Sacrifice this creature: Add {1} to your mana pool.";
+ }
+
+ public BlightHerderEffect(final BlightHerderEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public BlightHerderEffect copy() {
+ return new BlightHerderEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ Target target = new TargetCardInExile(2, 2, filter, null);
+ if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) {
+ if (controller.chooseTarget(outcome, target, source, game)) {
+ Cards cardsToGraveyard = new CardsImpl(target.getTargets());
+ controller.moveCards(cardsToGraveyard, null, Zone.GRAVEYARD, source, game);
+ return new CreateTokenEffect(new EldraziScionToken(), 3).apply(game, source);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/OblivionSower.java b/Mage.Sets/src/mage/sets/battleforzendikar/OblivionSower.java
new file mode 100644
index 00000000000..bfc7d1b0917
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/battleforzendikar/OblivionSower.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.battleforzendikar;
+
+import java.util.UUID;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.CastSourceTriggeredAbility;
+import mage.abilities.effects.common.ExileCardsFromTopOfLibraryTargetEffect;
+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.FilterLandCard;
+import mage.filter.predicate.other.OwnerIdPredicate;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.TargetCard;
+import mage.target.common.TargetOpponent;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class OblivionSower extends CardImpl {
+
+ public OblivionSower(UUID ownerId) {
+ super(ownerId, 11, "Oblivion Sower", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{6}");
+ this.expansionSetCode = "BFZ";
+ this.subtype.add("Eldrazi");
+ this.power = new MageInt(5);
+ this.toughness = new MageInt(8);
+
+ // When you cast Oblivion Sower, target opponent exiles the top four cards of his or her library, then you may put any number of land cards that player owns from exile onto the battlefield under your control.
+ Ability ability = new CastSourceTriggeredAbility(new ExileCardsFromTopOfLibraryTargetEffect(4, "target opponent"), false);
+ ability.addEffect(new OblivionSowerEffect());
+ ability.addTarget(new TargetOpponent());
+ this.addAbility(ability);
+ }
+
+ public OblivionSower(final OblivionSower card) {
+ super(card);
+ }
+
+ @Override
+ public OblivionSower copy() {
+ return new OblivionSower(this);
+ }
+}
+
+class OblivionSowerEffect extends OneShotEffect {
+
+ public OblivionSowerEffect() {
+ super(Outcome.PutLandInPlay);
+ this.staticText = ", then you may put any number of land cards that player owns from exile onto the battlefield under your control";
+ }
+
+ public OblivionSowerEffect(final OblivionSowerEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public OblivionSowerEffect copy() {
+ return new OblivionSowerEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
+ if (controller != null && targetPlayer != null) {
+ FilterLandCard filter = new FilterLandCard();
+ filter.add(new OwnerIdPredicate(targetPlayer.getId()));
+ Cards exiledCards = new CardsImpl();
+ exiledCards.addAll(game.getExile().getAllCards(game));
+ Cards exiledLands = new CardsImpl();
+ exiledLands.addAll(exiledCards.getCards(filter, source.getSourceId(), controller.getId(), game));
+ if (!exiledLands.isEmpty() && controller.chooseUse(outcome, "Put lands into play?", source, game)) {
+ FilterCard filterToPlay = new FilterCard("Lands owned by " + targetPlayer.getName() + " to put into play under your control");
+ TargetCard targetCards = new TargetCard(0, exiledLands.size(), Zone.EXILED, filterToPlay);
+ if (controller.chooseTarget(outcome, exiledLands, targetCards, source, game)) {
+ controller.moveCards(new CardsImpl(targetCards.getTargets()), null, Zone.BATTLEFIELD, source, game);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/TitansPresence.java b/Mage.Sets/src/mage/sets/battleforzendikar/TitansPresence.java
new file mode 100644
index 00000000000..f19f583b71d
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/battleforzendikar/TitansPresence.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.battleforzendikar;
+
+import java.util.List;
+import java.util.UUID;
+import mage.abilities.Ability;
+import mage.abilities.costs.common.RevealTargetFromHandCost;
+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.FilterCreatureCard;
+import mage.filter.predicate.mageobject.ColorlessPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.common.TargetCardInHand;
+import mage.target.common.TargetCreaturePermanent;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class TitansPresence extends CardImpl {
+
+ private static final FilterCreatureCard filter = new FilterCreatureCard("a colorless creature card from your hand to reveal");
+
+ static {
+ filter.add(new ColorlessPredicate());
+ }
+
+ public TitansPresence(UUID ownerId) {
+ super(ownerId, 14, "Titan's Presence", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{3}");
+ this.expansionSetCode = "BFZ";
+
+ // As an additional cost to cast Titan's Presence, reveal a colorless creature card from your hand.
+ this.getSpellAbility().addCost(new RevealTargetFromHandCost(new TargetCardInHand(filter)));
+
+ // Exile target creature if its power is less than or equal to the revealed card's power.
+ this.getSpellAbility().addEffect(new TitansPresenceEffect());
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent());
+ }
+
+ public TitansPresence(final TitansPresence card) {
+ super(card);
+ }
+
+ @Override
+ public TitansPresence copy() {
+ return new TitansPresence(this);
+ }
+}
+
+class TitansPresenceEffect extends OneShotEffect {
+
+ public TitansPresenceEffect() {
+ super(Outcome.Exile);
+ staticText = "Exile target creature if its power is less than or equal to the revealed card's power";
+ }
+
+ public TitansPresenceEffect(TitansPresenceEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ RevealTargetFromHandCost cost = (RevealTargetFromHandCost) source.getCosts().get(0);
+ Permanent creature = game.getPermanent(getTargetPointer().getFirst(game, source));
+ Player controller = game.getPlayer(source.getControllerId());
+ if (cost != null && creature != null && controller != null) {
+ List revealedCards = cost.getRevealedCards();
+ if (!revealedCards.isEmpty()) {
+ Card card = revealedCards.iterator().next();
+ if (card != null && card.getPower().getValue() >= creature.getPower().getValue()) {
+ controller.moveCards(creature, null, Zone.EXILED, source, game);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public TitansPresenceEffect copy() {
+ return new TitansPresenceEffect(this);
+ }
+
+}
diff --git a/Mage.Sets/src/mage/sets/bornofthegods/BrimazKingOfOreskos.java b/Mage.Sets/src/mage/sets/bornofthegods/BrimazKingOfOreskos.java
index 7d967d2d226..8ebc5ab5fc8 100644
--- a/Mage.Sets/src/mage/sets/bornofthegods/BrimazKingOfOreskos.java
+++ b/Mage.Sets/src/mage/sets/bornofthegods/BrimazKingOfOreskos.java
@@ -64,10 +64,10 @@ public class BrimazKingOfOreskos extends CardImpl {
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
-
+
// Whenever Brimaz, King of Oreskos attacks, put a 1/1 white Cat Soldier creature token with vigilance onto the battlefield attacking.
this.addAbility(new AttacksTriggeredAbility(new CreateTokenEffect(new CatSoldierCreatureToken(), 1, false, true), false));
-
+
// Whenever Brimaz blocks a creature, put a 1/1 white Cat Soldier creature token with vigilance onto the battlefield blocking that creature.
this.addAbility(new BlocksCreatureTriggeredAbility(new BrimazKingOfOreskosEffect(), false, true));
}
@@ -83,44 +83,49 @@ public class BrimazKingOfOreskos extends CardImpl {
}
class BrimazKingOfOreskosEffect extends OneShotEffect {
-
+
public BrimazKingOfOreskosEffect() {
super(Outcome.Benefit);
this.staticText = "put a 1/1 white Cat Soldier creature token with vigilance onto the battlefield blocking that creature";
}
-
+
public BrimazKingOfOreskosEffect(final BrimazKingOfOreskosEffect effect) {
super(effect);
}
-
+
@Override
public BrimazKingOfOreskosEffect copy() {
return new BrimazKingOfOreskosEffect(this);
}
-
+
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
-
+
if (controller != null) {
Token token = new CatSoldierCreatureToken();
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
- Permanent catToken = game.getPermanent(token.getLastAddedToken());
- Permanent attackingCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
- if (catToken != null && attackingCreature != null && game.getState().getCombat() != null) {
+ Permanent attackingCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
+ if (attackingCreature != null && game.getState().getCombat() != null) {
// Possible ruling (see Ætherplasm)
// The token you put onto the battlefield is blocking the attacking creature,
// even if the block couldn't legally be declared (for example, if that creature
- // enters the battlefield tapped, or it can't block, or the attacking creature
+ // enters the battlefield tapped, or it can't block, or the attacking creature
// has protection from it)
CombatGroup combatGroup = game.getState().getCombat().findGroup(attackingCreature.getId());
if (combatGroup != null) {
- combatGroup.addBlocker(catToken.getId(), source.getControllerId(), game);
- game.getCombat().addBlockingGroup(catToken.getId(),attackingCreature.getId() , source.getControllerId(), game);
+ for (UUID tokenId : token.getLastAddedTokenIds()) {
+ Permanent catToken = game.getPermanent(tokenId);
+ if (catToken != null) {
+ combatGroup.addBlocker(tokenId, source.getControllerId(), game);
+ game.getCombat().addBlockingGroup(tokenId, attackingCreature.getId(), controller.getId(), game);
+ }
+ }
+ combatGroup.pickBlockerOrder(attackingCreature.getControllerId(), game);
}
}
return true;
- }
+ }
return false;
}
}
diff --git a/Mage.Sets/src/mage/sets/commander2014/TeferiTemporalArchmage.java b/Mage.Sets/src/mage/sets/commander2014/TeferiTemporalArchmage.java
index bbe6c7346a5..4990384fa41 100644
--- a/Mage.Sets/src/mage/sets/commander2014/TeferiTemporalArchmage.java
+++ b/Mage.Sets/src/mage/sets/commander2014/TeferiTemporalArchmage.java
@@ -51,7 +51,6 @@ import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.command.Emblem;
-import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
/**
@@ -65,7 +64,6 @@ public class TeferiTemporalArchmage extends CardImpl {
this.expansionSetCode = "C14";
this.subtype.add("Teferi");
-
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(5)), false));
// +1: Look at the top two cards of your library. Put one of them into your hand and the other on the bottom of your library.
@@ -73,13 +71,13 @@ public class TeferiTemporalArchmage extends CardImpl {
new StaticValue(2), false, new StaticValue(1), new FilterCard(), Zone.LIBRARY, false, false), 1));
// -1: Untap up to four target permanents.
- LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new UntapTargetEffect(), -1);
- loyaltyAbility.addTarget(new TargetPermanent(0,4, new FilterPermanent(), false));
+ LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new UntapTargetEffect(), -1);
+ loyaltyAbility.addTarget(new TargetPermanent(0, 4, new FilterPermanent(), false));
this.addAbility(loyaltyAbility);
// -10: You get an emblem with "You may activate loyalty abilities of planeswalkers you control on any player's turn any time you could cast an instant."
this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new TeferiTemporalArchmageEmblem()), -10));
-
+
// Teferi, Temporal Archmage can be your commander.
this.addAbility(CanBeYourCommanderAbility.getInstance());
@@ -96,7 +94,9 @@ public class TeferiTemporalArchmage extends CardImpl {
}
class TeferiTemporalArchmageEmblem extends Emblem {
+
// "You may activate loyalty abilities of planeswalkers you control on any player's turn any time you could cast an instant."
+
public TeferiTemporalArchmageEmblem() {
this.setName("EMBLEM: Teferi, Temporal Archmage");
this.getAbilities().add(new SimpleStaticAbility(Zone.COMMAND, new TeferiTemporalArchmageAsThoughEffect()));
@@ -114,7 +114,6 @@ class TeferiTemporalArchmageAsThoughEffect extends AsThoughEffectImpl {
super(effect);
}
-
@Override
public boolean apply(Game game, Ability source) {
return true;
@@ -135,7 +134,7 @@ class TeferiTemporalArchmageAsThoughEffect extends AsThoughEffectImpl {
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- return false; // Not used
+ return false; // Not used
}
}
diff --git a/Mage.Sets/src/mage/sets/legends/HazezonTamar.java b/Mage.Sets/src/mage/sets/legends/HazezonTamar.java
index 21eca703027..19ca690ac55 100644
--- a/Mage.Sets/src/mage/sets/legends/HazezonTamar.java
+++ b/Mage.Sets/src/mage/sets/legends/HazezonTamar.java
@@ -33,7 +33,7 @@ import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
-import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility;
+import mage.abilities.common.delayed.AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@@ -111,7 +111,7 @@ class HazezonTamarEntersEffect extends OneShotEffect {
if (controller != null) {
Effect effect = new CreateTokenEffect(new HazezonTamarSandWarrior(), new PermanentsOnBattlefieldCount(new FilterControlledLandPermanent()));
effect.setText("put X 1/1 Sand Warrior creature tokens that are red, green, and white onto the battlefield, where X is the number of lands you control at that time");
- DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(effect);
+ DelayedTriggeredAbility delayedAbility = new AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility(effect);
delayedAbility.setSourceId(source.getSourceId());
delayedAbility.setControllerId(source.getControllerId());
delayedAbility.setSourceObject(source.getSourceObject(game), game);
diff --git a/Mage.Sets/src/mage/sets/scourge/RavenGuildMaster.java b/Mage.Sets/src/mage/sets/scourge/RavenGuildMaster.java
index 938a4bc5dcb..e6c35248d15 100644
--- a/Mage.Sets/src/mage/sets/scourge/RavenGuildMaster.java
+++ b/Mage.Sets/src/mage/sets/scourge/RavenGuildMaster.java
@@ -29,18 +29,13 @@ package mage.sets.scourge;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.ExileCardsFromTopOfLibraryTargetEffect;
import mage.abilities.keyword.MorphAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.Rarity;
-import mage.game.Game;
-import mage.players.Player;
/**
*
@@ -58,8 +53,8 @@ public class RavenGuildMaster extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Raven Guild Master deals combat damage to a player, that player exiles the top ten cards of his or her library.
- this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new RavenGuildMasterEffect(), false, true));
-
+ this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new ExileCardsFromTopOfLibraryTargetEffect(10, "that player"), false, true));
+
// Morph {2}{U}{U}
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{2}{U}{U}")));
}
@@ -73,36 +68,3 @@ public class RavenGuildMaster extends CardImpl {
return new RavenGuildMaster(this);
}
}
-
-class RavenGuildMasterEffect extends OneShotEffect {
-
- public RavenGuildMasterEffect() {
- super(Outcome.Exile);
- this.staticText = "that player exiles the top ten cards of his or her library";
- }
-
- public RavenGuildMasterEffect(final RavenGuildMasterEffect effect) {
- super(effect);
- }
-
- @Override
- public RavenGuildMasterEffect copy() {
- return new RavenGuildMasterEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(targetPointer.getFirst(game, source));
- if (player != null) {
- int count = Math.min(player.getLibrary().size(), 10);
- for (int i = 0; i < count; i++) {
- Card card = player.getLibrary().removeFromTop(game);
- if (card != null) {
- card.moveToExile(id, "", source.getSourceId(), game);
- }
- }
- return true;
- }
- return false;
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/sets/shadowmoor/DemigodOfRevenge.java b/Mage.Sets/src/mage/sets/shadowmoor/DemigodOfRevenge.java
index e64a220bb48..85977dde261 100644
--- a/Mage.Sets/src/mage/sets/shadowmoor/DemigodOfRevenge.java
+++ b/Mage.Sets/src/mage/sets/shadowmoor/DemigodOfRevenge.java
@@ -30,8 +30,8 @@ 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.effects.common.CastSourceTriggeredAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.Card;
@@ -43,8 +43,6 @@ 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.game.events.GameEvent.EventType;
import mage.players.Player;
/**
@@ -64,10 +62,12 @@ public class DemigodOfRevenge extends CardImpl {
// 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());
+ this.addAbility(new CastSourceTriggeredAbility(new DemigodOfRevengeReturnEffect()));
}
public DemigodOfRevenge(final DemigodOfRevenge card) {
@@ -80,40 +80,10 @@ public class DemigodOfRevenge extends CardImpl {
}
}
-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 checkEventType(GameEvent event, Game game) {
- return event.getType() == EventType.SPELL_CAST;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When you cast {this}, " + super.getRule();
- }
-}
-
class DemigodOfRevengeReturnEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard();
+
static {
filter.add(new NamePredicate("Demigod of Revenge"));
}
diff --git a/Mage.Sets/src/mage/sets/shadowmoor/WildSwing.java b/Mage.Sets/src/mage/sets/shadowmoor/WildSwing.java
index b7737a78b8a..260029f8b84 100644
--- a/Mage.Sets/src/mage/sets/shadowmoor/WildSwing.java
+++ b/Mage.Sets/src/mage/sets/shadowmoor/WildSwing.java
@@ -27,7 +27,9 @@
*/
package mage.sets.shadowmoor;
+import java.util.Random;
import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
@@ -39,6 +41,7 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.target.Target;
import mage.target.TargetPermanent;
/**
@@ -46,9 +49,9 @@ import mage.target.TargetPermanent;
* @author jeffwadsworth
*/
public class WildSwing extends CardImpl {
-
+
private static final FilterPermanent filter = new FilterPermanent("target nonenchantment permanents");
-
+
static {
filter.add(Predicates.not(new CardTypePredicate(CardType.ENCHANTMENT)));
}
@@ -57,11 +60,10 @@ public class WildSwing extends CardImpl {
super(ownerId, 108, "Wild Swing", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{R}");
this.expansionSetCode = "SHM";
-
// Choose three target nonenchantment permanents. Destroy one of them at random.
this.getSpellAbility().addEffect(new WildSwingEffect());
this.getSpellAbility().addTarget(new TargetPermanent(3, filter));
-
+
}
public WildSwing(final WildSwing card) {
@@ -92,11 +94,18 @@ class WildSwingEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- int randomNumber = (int)(Math.random() * 3);
- Permanent target = game.getPermanent(source.getTargets().get(randomNumber).getFirstTarget());
- if (target != null) {
- game.informPlayers("Wild Swing: The randomly chosen target to destroy is " + target.getName());
- return target.destroy(source.getSourceId(), game, false);
+ MageObject sourceObject = source.getSourceObject(game);
+ if (!source.getTargets().isEmpty() && sourceObject != null) {
+ Target target = source.getTargets().get(0);
+ if (target != null && !target.getTargets().isEmpty()) {
+ Random rnd = new Random();
+ Permanent targetPermanent = game.getPermanent(target.getTargets().get(rnd.nextInt(target.getTargets().size())));
+ if (targetPermanent != null) {
+ game.informPlayers(sourceObject.getLogName() + ": The randomly chosen target to destroy is " + targetPermanent.getLogName());
+ targetPermanent.destroy(source.getSourceId(), game, false);
+ }
+ return true;
+ }
}
return false;
}
diff --git a/Mage.Sets/src/mage/sets/timespiral/MishraArtificerProdigy.java b/Mage.Sets/src/mage/sets/timespiral/MishraArtificerProdigy.java
index 28488d56754..0ef45b5d50b 100644
--- a/Mage.Sets/src/mage/sets/timespiral/MishraArtificerProdigy.java
+++ b/Mage.Sets/src/mage/sets/timespiral/MishraArtificerProdigy.java
@@ -142,15 +142,12 @@ class MishraArtificerProdigyEffect extends OneShotEffect {
FilterCard filter = new FilterCard("card named " + this.cardName);
filter.add(new NamePredicate(cardName));
Card card = null;
- Zone zone = null;
// Graveyard
if (controller.chooseUse(Outcome.Neutral, "Search your graveyard?", source, game)) {
- TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(0, 1, filter);
+ // You can't fail to find the card in your graveyard because it's not hidden
+ TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(1, 1, filter);
if (controller.choose(Outcome.PutCardInPlay, controller.getGraveyard(), target, game)) {
card = game.getCard(target.getFirstTarget());
- if (card != null) {
- zone = Zone.GRAVEYARD;
- }
}
}
// Hand
@@ -158,9 +155,6 @@ class MishraArtificerProdigyEffect extends OneShotEffect {
TargetCardInHand target = new TargetCardInHand(0, 1, filter);
if (controller.choose(Outcome.PutCardInPlay, controller.getHand(), target, game)) {
card = game.getCard(target.getFirstTarget());
- if (card != null) {
- zone = Zone.HAND;
- }
}
}
// Library
@@ -168,15 +162,12 @@ class MishraArtificerProdigyEffect extends OneShotEffect {
TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter);
if (controller.searchLibrary(target, game)) {
card = game.getCard(target.getFirstTarget());
- if (card != null) {
- zone = Zone.LIBRARY;
- }
}
controller.shuffleLibrary(game);
}
// Put on battlefield
if (card != null) {
- controller.moveCards(card, zone, Zone.BATTLEFIELD, source, game);
+ controller.moveCards(card, null, Zone.BATTLEFIELD, source, game);
}
return true;
}
diff --git a/Mage.Sets/src/mage/sets/timespiral/RiftwingCloudskate.java b/Mage.Sets/src/mage/sets/timespiral/RiftwingCloudskate.java
index 221faa6eb4d..c0fd5c60bc7 100644
--- a/Mage.Sets/src/mage/sets/timespiral/RiftwingCloudskate.java
+++ b/Mage.Sets/src/mage/sets/timespiral/RiftwingCloudskate.java
@@ -28,8 +28,6 @@
package mage.sets.timespiral;
import java.util.UUID;
-import mage.constants.CardType;
-import mage.constants.Rarity;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -38,6 +36,8 @@ import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.SuspendAbility;
import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Rarity;
import mage.target.TargetPermanent;
/**
@@ -62,7 +62,7 @@ public class RiftwingCloudskate extends CardImpl {
this.addAbility(ability);
// Suspend 3-{1}{U}
- this.addAbility(new SuspendAbility(3, new ManaCostsImpl("{1}{U}"),this));
+ this.addAbility(new SuspendAbility(3, new ManaCostsImpl("{1}{U}"), this));
}
public RiftwingCloudskate(final RiftwingCloudskate card) {
diff --git a/Mage.Sets/src/mage/sets/visions/GoblinRecruiter.java b/Mage.Sets/src/mage/sets/visions/GoblinRecruiter.java
index b2951b39274..9d574f3020b 100644
--- a/Mage.Sets/src/mage/sets/visions/GoblinRecruiter.java
+++ b/Mage.Sets/src/mage/sets/visions/GoblinRecruiter.java
@@ -32,19 +32,16 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
-import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.players.Player;
-import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
/**
@@ -78,18 +75,16 @@ public class GoblinRecruiter extends CardImpl {
class GoblinRecruiterEffect extends OneShotEffect {
private static final FilterCard goblinFilter = new FilterCard("Goblin cards");
-
- private static final FilterCard putOnTopOfLibraryFilter = new FilterCard("card to put on the top of your library (last chosen will be on top)");
-
+
static {
goblinFilter.add(new SubtypePredicate("Goblin"));
}
-
+
public GoblinRecruiterEffect() {
super(Outcome.Benefit);
this.staticText = "search your library for any number of Goblin cards and reveal those cards. Shuffle your library, then put them on top of it in any order.";
}
-
+
public GoblinRecruiterEffect(final GoblinRecruiterEffect effect) {
super(effect);
}
@@ -98,54 +93,26 @@ class GoblinRecruiterEffect extends OneShotEffect {
public GoblinRecruiterEffect copy() {
return new GoblinRecruiterEffect(this);
}
-
+
@Override
public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
TargetCardInLibrary targetGoblins = new TargetCardInLibrary(0, Integer.MAX_VALUE, goblinFilter);
Cards cards = new CardsImpl();
- if (player.searchLibrary(targetGoblins, game)) {
- for (UUID targetId : targetGoblins.getTargets()) {
- Card card = player.getLibrary().remove(targetId, game);
- if (card != null) {
- cards.add(card);
- }
- }
+ if (controller.searchLibrary(targetGoblins, game)) {
+ cards.addAll(targetGoblins.getTargets());
}
-
- player.shuffleLibrary(game);
-
+ controller.revealCards(staticText, cards, game);
+ controller.shuffleLibrary(game);
+
int numberOfGoblins = cards.size();
if (numberOfGoblins > 0) {
- if (cards.size() > 1) {
- TargetCard targetCard = new TargetCard(Zone.LIBRARY, putOnTopOfLibraryFilter);
- while (player.canRespond() && cards.size() > 1) {
- player.choose(Outcome.Benefit, cards, targetCard, game);
- Card card = cards.get(targetCard.getFirstTarget(), game);
- if (card != null) {
- cards.remove(card);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- targetCard.clearChosen();
- }
- }
- if (cards.size() == 1) {
- Card card = cards.get(cards.iterator().next(), game);
- if (card != null) {
- cards.remove(card);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- }
+ controller.putCardsOnTopOfLibrary(cards, game, source, true);
}
-
- game.informPlayers(new StringBuilder(player.getLogName()).append(" puts ")
- .append(numberOfGoblins).append(" Goblin").append(numberOfGoblins == 1 ? " card" : " cards")
- .append(" on top of his library").toString());
-
return true;
}
return false;
}
-
+
}
diff --git a/Mage.Sets/src/mage/sets/worldwake/RoilingTerrain.java b/Mage.Sets/src/mage/sets/worldwake/RoilingTerrain.java
index 6a709b65662..d60e58b151a 100644
--- a/Mage.Sets/src/mage/sets/worldwake/RoilingTerrain.java
+++ b/Mage.Sets/src/mage/sets/worldwake/RoilingTerrain.java
@@ -28,15 +28,13 @@
package mage.sets.worldwake;
import java.util.UUID;
-
-import mage.constants.CardType;
-import mage.constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
+import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.filter.FilterCard;
-import mage.filter.predicate.mageobject.CardTypePredicate;
+import mage.constants.Rarity;
+import mage.filter.common.FilterLandCard;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@@ -52,7 +50,6 @@ public class RoilingTerrain extends CardImpl {
super(ownerId, 88, "Roiling Terrain", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{R}{R}");
this.expansionSetCode = "WWK";
-
// Destroy target land, then Roiling Terrain deals damage to that land's controller equal to the number of land cards in that player's graveyard.
this.getSpellAbility().addEffect(new RoilingTerrainEffect());
this.getSpellAbility().addTarget(new TargetLandPermanent());
@@ -69,12 +66,6 @@ public class RoilingTerrain extends CardImpl {
}
class RoilingTerrainEffect extends OneShotEffect {
-
- private static final FilterCard filter = new FilterCard("lands in graveyard");
-
- static {
- filter.add(new CardTypePredicate(CardType.LAND));
- }
public RoilingTerrainEffect() {
super(Outcome.Sacrifice);
@@ -92,14 +83,16 @@ class RoilingTerrainEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Permanent targetedLand = game.getPermanent(source.getFirstTarget());
+ Permanent targetedLand = game.getPermanent(getTargetPointer().getFirst(game, source));
if (targetedLand != null) {
- Player controller = game.getPlayer(targetedLand.getControllerId());
- targetedLand.destroy(id, game, true);
- int landsInGraveyard = controller.getGraveyard().count(filter, game);
- controller.damage(landsInGraveyard, id, game, false, true);
+ targetedLand.destroy(source.getSourceId(), game, true);
+ Player targetController = game.getPlayer(targetedLand.getControllerId());
+ if (targetController != null) {
+ int landsInGraveyard = targetController.getGraveyard().count(new FilterLandCard(), game);
+ targetController.damage(landsInGraveyard, source.getSourceId(), game, false, true);
+ }
return true;
}
return false;
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/sets/worldwake/SearingBlaze.java b/Mage.Sets/src/mage/sets/worldwake/SearingBlaze.java
index 2cccea80098..dd13eb7b80d 100644
--- a/Mage.Sets/src/mage/sets/worldwake/SearingBlaze.java
+++ b/Mage.Sets/src/mage/sets/worldwake/SearingBlaze.java
@@ -1,16 +1,16 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
- *
+ *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
@@ -20,12 +20,11 @@
* 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.worldwake;
import java.util.HashSet;
@@ -45,7 +44,6 @@ import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.target.TargetPlayer;
-import mage.watchers.Watcher;
import mage.watchers.common.LandfallWatcher;
/**
@@ -140,10 +138,10 @@ class SearingBlazeTarget extends TargetPermanent {
Set possibleTargets = new HashSet<>();
MageObject object = game.getObject(sourceId);
if (object instanceof StackObject) {
- UUID playerId = ((StackObject)object).getStackAbility().getFirstTarget();
+ UUID playerId = ((StackObject) object).getStackAbility().getFirstTarget();
for (UUID targetId : availablePossibleTargets) {
Permanent permanent = game.getPermanent(targetId);
- if(permanent != null && permanent.getControllerId().equals(playerId)){
+ if (permanent != null && permanent.getControllerId().equals(playerId)) {
possibleTargets.add(targetId);
}
}
@@ -155,4 +153,4 @@ class SearingBlazeTarget extends TargetPermanent {
public SearingBlazeTarget copy() {
return new SearingBlazeTarget(this);
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/sets/worldwake/Terastodon.java b/Mage.Sets/src/mage/sets/worldwake/Terastodon.java
index 3192537315c..9999b33da28 100644
--- a/Mage.Sets/src/mage/sets/worldwake/Terastodon.java
+++ b/Mage.Sets/src/mage/sets/worldwake/Terastodon.java
@@ -28,15 +28,15 @@
package mage.sets.worldwake;
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.EntersBattlefieldTriggeredAbility;
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.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
@@ -68,7 +68,7 @@ public class Terastodon extends CardImpl {
// When Terastodon enters the battlefield, you may destroy up to three target noncreature permanents. For each permanent put into a graveyard this way, its controller puts a 3/3 green Elephant creature token onto the battlefield.
Ability ability = new EntersBattlefieldTriggeredAbility(new TerastodonEffect(), true);
- ability.addTarget(new TargetPermanent(0, 3, filter, true));
+ ability.addTarget(new TargetPermanent(0, 3, filter, false));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/sets/zendikarvseldrazi/OblivionSower.java b/Mage.Sets/src/mage/sets/zendikarvseldrazi/OblivionSower.java
new file mode 100644
index 00000000000..875ff61ef2e
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/zendikarvseldrazi/OblivionSower.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.zendikarvseldrazi;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class OblivionSower extends mage.sets.battleforzendikar.OblivionSower {
+
+ public OblivionSower(UUID ownerId) {
+ super(ownerId);
+ this.cardNumber = 41;
+ this.expansionSetCode = "DDP";
+ }
+
+ public OblivionSower(final OblivionSower card) {
+ super(card);
+ }
+
+ @Override
+ public OblivionSower copy() {
+ return new OblivionSower(this);
+ }
+}
diff --git a/Mage.Stats/pom.xml b/Mage.Stats/pom.xml
index 91da9f71b06..e163c6b55fc 100644
--- a/Mage.Stats/pom.xml
+++ b/Mage.Stats/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
org.mage
diff --git a/Mage.Tests/pom.xml b/Mage.Tests/pom.xml
index d5da2643a78..55cc018a56f 100644
--- a/Mage.Tests/pom.xml
+++ b/Mage.Tests/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
mage-tests
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java
index 037de63e93d..1770b99e8cd 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java
@@ -94,9 +94,12 @@ public class SoulbondKeywordTest extends CardTestPlayerBase {
@Test
public void testChangeControllerForSoulbondCreature() {
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
+ // Soulbond (You may pair this creature with another unpaired creature when either enters the battlefield. They remain paired for as long as you control both of them.)
+ // As long as Trusted Forcemage is paired with another creature, each of those creatures gets +1/+1.
addCard(Zone.HAND, playerA, "Trusted Forcemage");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
+ // Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. (It can attack and Tap this turn.)
addCard(Zone.HAND, playerB, "Act of Treason");
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3);
@@ -121,8 +124,10 @@ public class SoulbondKeywordTest extends CardTestPlayerBase {
*/
@Test
public void testChangeControllerForAnotherCreature() {
- addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
- addCard(Zone.HAND, playerA, "Trusted Forcemage");
+ addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard"); // 2,1
+ // Soulbond (You may pair this creature with another unpaired creature when either enters the battlefield. They remain paired for as long as you control both of them.)
+ // As long as Trusted Forcemage is paired with another creature, each of those creatures gets +1/+1.
+ addCard(Zone.HAND, playerA, "Trusted Forcemage"); // 2/2
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
addCard(Zone.HAND, playerB, "Act of Treason");
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/protection/gain/GainProtectionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/protection/gain/GainProtectionTest.java
index 945d61b8325..d3bb9c3eea8 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/protection/gain/GainProtectionTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/protection/gain/GainProtectionTest.java
@@ -70,4 +70,64 @@ public class GainProtectionTest extends CardTestPlayerBase {
assertPowerToughness(playerA, "Elite Vanguard", 6, 5);
}
+ @Test
+ public void testGainProtectionByEnchantment() {
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 5);
+ // Flying
+ // When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control.
+ addCard(Zone.BATTLEFIELD, playerB, "Brago, King Eternal");
+ // Enchant creature
+ // When Pentarch Ward enters the battlefield, draw a card.
+ // As Pentarch Ward enters the battlefield, choose a color.
+ // Enchanted creature has protection from the chosen color. This effect doesn't remove Pentarch Ward.
+ addCard(Zone.HAND, playerB, "Pentarch Ward");// "{2}{W}"
+ // Enchant creature
+ // Enchanted creature gets +1/+1 and has "Whenever this creature attacks, tap target creature defending player controls."
+ addCard(Zone.HAND, playerB, "Grasp of the Hieromancer");
+
+ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Pentarch Ward", "Brago, King Eternal");
+ setChoice(playerB, "White");
+
+ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Grasp of the Hieromancer", "Brago, King Eternal");
+
+ setStopAt(2, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertPermanentCount(playerB, "Pentarch Ward", 1);
+ assertHandCount(playerB, "Grasp of the Hieromancer", 1);
+ assertHandCount(playerB, 3);
+ }
+
+ /**
+ * Pentarch Ward on Brago naming white. Brago combat trigger resolves
+ * blinking Pentarch Ward. Brago retains protection from white even though
+ * Pentarch Ward is now exiled, making him unable to be re-enchanted by
+ * Pentarch Ward.
+ */
+ @Test
+ public void testGainLooseProtectionByEnchantment() {
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
+ // Flying
+ // When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control.
+ addCard(Zone.BATTLEFIELD, playerB, "Brago, King Eternal");
+ // Enchant creature
+ // When Pentarch Ward enters the battlefield, draw a card.
+ // As Pentarch Ward enters the battlefield, choose a color.
+ // Enchanted creature has protection from the chosen color. This effect doesn't remove Pentarch Ward.
+ addCard(Zone.HAND, playerB, "Pentarch Ward");// "{2}{W}"
+
+ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Pentarch Ward", "Brago, King Eternal");
+ setChoice(playerB, "White");
+
+ attack(2, playerB, "Brago, King Eternal");
+ addTarget(playerB, "Pentarch Ward");
+ addTarget(playerB, "Brago, King Eternal");
+
+ setStopAt(2, PhaseStep.END_COMBAT);
+ execute();
+
+ assertLife(playerA, 18);
+ assertPermanentCount(playerB, "Pentarch Ward", 1);
+ assertHandCount(playerB, 3);
+ }
}
diff --git a/Mage.Updater/pom.xml b/Mage.Updater/pom.xml
index 90d4db3a1a6..97c617af46e 100644
--- a/Mage.Updater/pom.xml
+++ b/Mage.Updater/pom.xml
@@ -5,7 +5,7 @@
mage-root
org.mage
- 1.4.3
+ 1.4.4
4.0.0
diff --git a/Mage/pom.xml b/Mage/pom.xml
index c13b047036a..bd275a8c4b7 100644
--- a/Mage/pom.xml
+++ b/Mage/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
mage
diff --git a/Mage/src/mage/abilities/costs/common/RevealTargetFromHandCost.java b/Mage/src/mage/abilities/costs/common/RevealTargetFromHandCost.java
index 492a07fff12..a5ef7e33cba 100644
--- a/Mage/src/mage/abilities/costs/common/RevealTargetFromHandCost.java
+++ b/Mage/src/mage/abilities/costs/common/RevealTargetFromHandCost.java
@@ -28,6 +28,8 @@
// author jeffwadsworth
package mage.abilities.costs.common;
+import java.util.ArrayList;
+import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
@@ -44,16 +46,19 @@ public class RevealTargetFromHandCost extends CostImpl {
public int convertedManaCosts = 0;
protected int numberCardsRevealed = 0;
+ protected List revealedCards;
public RevealTargetFromHandCost(TargetCardInHand target) {
this.addTarget(target);
this.text = (target.getNumberOfTargets() == 0 ? "you may " : "") + "reveal " + target.getTargetName();
+ this.revealedCards = new ArrayList<>();
}
public RevealTargetFromHandCost(final RevealTargetFromHandCost cost) {
super(cost);
this.convertedManaCosts = cost.convertedManaCosts;
this.numberCardsRevealed = cost.numberCardsRevealed;
+ this.revealedCards = new ArrayList<>(cost.revealedCards);
}
@Override
@@ -69,6 +74,7 @@ public class RevealTargetFromHandCost extends CostImpl {
convertedManaCosts += card.getManaCost().convertedManaCost();
numberCardsRevealed++;
cards.add(card);
+ revealedCards.add(card);
}
}
if (numberCardsRevealed > 0) {
@@ -92,6 +98,10 @@ public class RevealTargetFromHandCost extends CostImpl {
return numberCardsRevealed;
}
+ public List getRevealedCards() {
+ return revealedCards;
+ }
+
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
return targets.canChoose(controllerId, game);
diff --git a/Mage/src/mage/abilities/effects/AuraReplacementEffect.java b/Mage/src/mage/abilities/effects/AuraReplacementEffect.java
index 8c4a0e063e9..1a47387a473 100644
--- a/Mage/src/mage/abilities/effects/AuraReplacementEffect.java
+++ b/Mage/src/mage/abilities/effects/AuraReplacementEffect.java
@@ -116,6 +116,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
}
}
+ game.applyEffects(); // So continuousEffects are removed if previous effect of the same ability did move objects that cuase continuous effects
if (targetId == null) {
Target target = card.getSpellAbility().getTargets().get(0);
enchantCardInGraveyard = target instanceof TargetCardInGraveyard;
@@ -169,7 +170,6 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
PermanentCard permanent = new PermanentCard(card, card.getOwnerId(), game);
game.getBattlefield().addPermanent(permanent);
card.setZone(Zone.BATTLEFIELD, game);
- game.applyEffects();
boolean entered = permanent.entersBattlefield(event.getSourceId(), game, fromZone, true);
game.applyEffects();
if (!entered) {
diff --git a/Mage/src/mage/abilities/effects/common/ExileCardsFromTopOfLibraryTargetEffect.java b/Mage/src/mage/abilities/effects/common/ExileCardsFromTopOfLibraryTargetEffect.java
new file mode 100644
index 00000000000..b0be1dd9fcc
--- /dev/null
+++ b/Mage/src/mage/abilities/effects/common/ExileCardsFromTopOfLibraryTargetEffect.java
@@ -0,0 +1,60 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package mage.abilities.effects.common;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.players.Player;
+import mage.util.CardUtil;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class ExileCardsFromTopOfLibraryTargetEffect extends OneShotEffect {
+
+ int amount;
+ String targetName;
+
+ public ExileCardsFromTopOfLibraryTargetEffect(int amount) {
+ this(amount, null);
+ }
+
+ public ExileCardsFromTopOfLibraryTargetEffect(int amount, String targetName) {
+ super(Outcome.Exile);
+ this.amount = amount;
+ this.staticText = (targetName == null ? "that player" : targetName) + " exiles the top "
+ + CardUtil.numberToText(amount, "")
+ + (amount == 1 ? "card" : " cards") + " of his or her library";
+ }
+
+ public ExileCardsFromTopOfLibraryTargetEffect(final ExileCardsFromTopOfLibraryTargetEffect effect) {
+ super(effect);
+ this.amount = effect.amount;
+
+ }
+
+ @Override
+ public ExileCardsFromTopOfLibraryTargetEffect copy() {
+ return new ExileCardsFromTopOfLibraryTargetEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
+ if (targetPlayer != null) {
+ Cards cards = new CardsImpl();
+ cards.addAll(targetPlayer.getLibrary().getTopCards(game, amount));
+ return targetPlayer.moveCards(cards, null, Zone.EXILED, source, game);
+ }
+ return false;
+ }
+}
diff --git a/Mage/src/mage/abilities/effects/common/HideawayPlayEffect.java b/Mage/src/mage/abilities/effects/common/HideawayPlayEffect.java
index b8333d2d39d..749f5214e5e 100644
--- a/Mage/src/mage/abilities/effects/common/HideawayPlayEffect.java
+++ b/Mage/src/mage/abilities/effects/common/HideawayPlayEffect.java
@@ -28,10 +28,12 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
+import mage.abilities.condition.common.MyMainPhaseCondition;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.constants.CardType;
import mage.constants.Outcome;
+import mage.constants.Zone;
import mage.game.ExileZone;
import mage.game.Game;
import mage.players.Player;
@@ -61,7 +63,7 @@ public class HideawayPlayEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
ExileZone zone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
- if (zone ==null || zone.isEmpty()) {
+ if (zone == null || zone.isEmpty()) {
return false;
}
Card card = zone.getCards(game).iterator().next();
@@ -69,10 +71,11 @@ public class HideawayPlayEffect extends OneShotEffect {
if (card != null && controller != null) {
if (card.getCardType().contains(CardType.LAND)) {
// If the revealed card is a land, you can play it only if it's your turn and you haven't yet played a land this turn.
- if (game.getActivePlayerId().equals(source.getControllerId()) && controller.canPlayLand()) {
+ if (game.getActivePlayerId().equals(source.getControllerId()) && controller.canPlayLand() && MyMainPhaseCondition.getInstance().apply(game, source)) {
if (controller.chooseUse(Outcome.Benefit, "Play " + card.getLogName() + " from Exile?", source, game)) {
+ // normal player.playLand(card, game) can't be used because this abilit is on the stack
card.setFaceDown(false, game);
- return controller.playLand(card, game);
+ return controller.moveCards(card, Zone.EXILED, Zone.BATTLEFIELD, source, game);
}
} else if (!game.isSimulation()) {
game.informPlayer(controller, "You're not able to play the land now due to regular restrictions.");
@@ -82,7 +85,7 @@ public class HideawayPlayEffect extends OneShotEffect {
// The land's last ability allows you to play the removed card as part of the resolution of that ability.
// Timing restrictions based on the card's type are ignored (for instance, if it's a creature or sorcery).
// Other play restrictions are not (such as "Play [this card] only during combat").
- if (controller.chooseUse(Outcome.Benefit, "Cast "+ card.getLogName() + " without paying its mana cost?", source, game)) {
+ if (controller.chooseUse(Outcome.Benefit, "Cast " + card.getLogName() + " without paying its mana cost?", source, game)) {
card.setFaceDown(false, game);
return controller.cast(card.getSpellAbility(), game, true);
}
@@ -96,4 +99,3 @@ public class HideawayPlayEffect extends OneShotEffect {
return false;
}
}
-
diff --git a/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java b/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java
index a3eeb0a2c13..58ebc6676bb 100644
--- a/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java
+++ b/Mage/src/mage/abilities/effects/common/ReturnFromExileEffect.java
@@ -96,7 +96,7 @@ public class ReturnFromExileEffect extends OneShotEffect {
case BATTLEFIELD:
card.moveToZone(zone, source.getSourceId(), game, tapped);
if (!game.isSimulation()) {
- game.informPlayers(controller.getLogName() + " moves " + card.getName() + " to " + zone.toString().toLowerCase());
+ game.informPlayers(controller.getLogName() + " moves " + card.getLogName() + " to " + zone.toString().toLowerCase());
}
break;
case HAND:
@@ -111,7 +111,7 @@ public class ReturnFromExileEffect extends OneShotEffect {
default:
card.moveToZone(zone, source.getSourceId(), game, tapped);
if (!game.isSimulation()) {
- game.informPlayers(controller.getLogName() + " moves " + card.getName() + " to " + zone.toString().toLowerCase());
+ game.informPlayers(controller.getLogName() + " moves " + card.getLogName() + " to " + zone.toString().toLowerCase());
}
}
}
diff --git a/Mage/src/mage/abilities/keyword/SuspendAbility.java b/Mage/src/mage/abilities/keyword/SuspendAbility.java
index 03b50951133..c5838c809d9 100644
--- a/Mage/src/mage/abilities/keyword/SuspendAbility.java
+++ b/Mage/src/mage/abilities/keyword/SuspendAbility.java
@@ -409,14 +409,11 @@ class GainHasteEffect extends ContinuousEffectImpl {
suspendController = source.getControllerId();
}
Permanent permanent = game.getPermanent(source.getSourceId());
- if (permanent != null) {
- if (suspendController.equals(source.getControllerId())) {
- permanent.addAbility(HasteAbility.getInstance(), source.getSourceId(), game);
- return true;
- } else {
- this.discard();
- }
+ if (permanent != null && suspendController.equals(source.getControllerId())) {
+ permanent.addAbility(HasteAbility.getInstance(), source.getSourceId(), game);
+ return true;
}
+ this.discard();
return false;
}
diff --git a/Mage/src/mage/game/permanent/token/ZombieToken.java b/Mage/src/mage/game/permanent/token/ZombieToken.java
index ab636da61fe..90b93810049 100644
--- a/Mage/src/mage/game/permanent/token/ZombieToken.java
+++ b/Mage/src/mage/game/permanent/token/ZombieToken.java
@@ -62,6 +62,9 @@ public class ZombieToken extends Token {
if (getOriginalExpansionSetCode().equals("ISD")) {
this.setTokenType(new Random().nextInt(3) + 1);
}
+ if (getOriginalExpansionSetCode().equals("C14")) {
+ this.setTokenType(2);
+ }
}
public ZombieToken(final ZombieToken token) {
diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java
index b121e9f269f..00d83fc7cfc 100644
--- a/Mage/src/mage/players/PlayerImpl.java
+++ b/Mage/src/mage/players/PlayerImpl.java
@@ -2983,7 +2983,7 @@ public abstract class PlayerImpl implements Player, Serializable {
case BATTLEFIELD:
for (Card card : cards) {
fromZone = game.getState().getZone(card.getId());
- if (putOntoBattlefieldWithInfo(card, game, fromZone, source == null ? null : source.getSourceId(), false, !card.isFaceDown(game))) {
+ if (putOntoBattlefieldWithInfo(card, game, fromZone, source == null ? null : source.getSourceId(), false, card.isFaceDown(game))) {
successfulMovedCards.add(card);
}
}
diff --git a/Mage/src/mage/watchers/common/LandfallWatcher.java b/Mage/src/mage/watchers/common/LandfallWatcher.java
index f75d4c0d625..2b4df7a7a12 100644
--- a/Mage/src/mage/watchers/common/LandfallWatcher.java
+++ b/Mage/src/mage/watchers/common/LandfallWatcher.java
@@ -17,14 +17,14 @@ import mage.watchers.Watcher;
public class LandfallWatcher extends Watcher {
Set playerPlayedLand = new HashSet<>();
-
+
public LandfallWatcher() {
super("LandPlayed", WatcherScope.GAME);
}
public LandfallWatcher(final LandfallWatcher watcher) {
super(watcher);
- playerPlayedLand.addAll(playerPlayedLand);
+ playerPlayedLand.addAll(watcher.playerPlayedLand);
}
@Override
@@ -45,9 +45,9 @@ public class LandfallWatcher extends Watcher {
@Override
public void reset() {
playerPlayedLand.clear();
- super.reset();
+ super.reset();
}
-
+
public boolean landPlayed(UUID playerId) {
return playerPlayedLand.contains(playerId);
}
diff --git a/Utils/release/getting_implemented_cards.txt b/Utils/release/getting_implemented_cards.txt
index 98eacef81cd..167b2d493a6 100644
--- a/Utils/release/getting_implemented_cards.txt
+++ b/Utils/release/getting_implemented_cards.txt
@@ -23,6 +23,9 @@ git log 23039572f2206ade860f5835e9b85e82a9c4b2a1..HEAD --diff-filter=A --name-st
since 1.4.3.v2
git log 6d8378d5e49629a2fa126baf84340156a28f25db..23039572f2206ade860f5835e9b85e82a9c4b2a1 --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
+since 1.4.4.v0
+git log 0a458707ddaaa5e7e82ab06d17633084f67077c1..23039572f2206ade860f5835e9b85e82a9c4b2a1 --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
+
3. Copy added_cards.txt to trunk\Utils folder
4. Run script:
diff --git a/pom.xml b/pom.xml
index 65aa64f3d05..9a9d122797a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-root
- 1.4.3
+ 1.4.4
pom
Mage Root
Mage Root POM
@@ -83,7 +83,7 @@
- 1.4.3
+ 1.4.4
UTF-8