duplicatedRules = new HashSet<>();
+
StringBuilder rule = new StringBuilder("
");
if (card.isSplitCard()) {
rule.append("");
@@ -356,7 +358,9 @@ public final class GuiDisplayUtil {
rule.append("
");
for (String ruling : card.getLeftSplitRules()) {
if (ruling != null && !ruling.replace(".", "").trim().isEmpty()) {
- rule.append("").append(ruling).append("
");
+ // split names must be replaced
+ duplicatedRules.add(ruling);
+ rule.append("").append(replaceNamesInRule(ruling, card.getLeftSplitName())).append("
");
}
}
rule.append("");
@@ -369,13 +373,18 @@ public final class GuiDisplayUtil {
rule.append("
");
for (String ruling : card.getRightSplitRules()) {
if (ruling != null && !ruling.replace(".", "").trim().isEmpty()) {
- rule.append("").append(ruling).append("
");
+ // split names must be replaced
+ duplicatedRules.add(ruling);
+ rule.append("").append(replaceNamesInRule(ruling, card.getRightSplitName())).append("
");
}
}
}
if (!textLines.getLines().isEmpty()) {
for (String textLine : textLines.getLines()) {
if (textLine != null && !textLine.replace(".", "").trim().isEmpty()) {
+ if (duplicatedRules.contains(textLine)) {
+ continue;
+ }
rule.append("").append(textLine).append("
");
}
}
@@ -383,8 +392,7 @@ public final class GuiDisplayUtil {
String legal = rule.toString();
if (!legal.isEmpty()) {
- legal = legal.replaceAll("\\{this\\}", card.getName().isEmpty() ? "this" : card.getName());
- legal = legal.replaceAll("\\{source\\}", card.getName().isEmpty() ? "this" : card.getName());
+ legal = replaceNamesInRule(legal, card.getDisplayName()); // must show real display name (e.g. split part, not original card)
buffer.append(ManaSymbols.replaceSymbolsWithHTML(legal, ManaSymbols.Type.TOOLTIP));
}
@@ -397,6 +405,12 @@ public final class GuiDisplayUtil {
return buffer;
}
+ private static String replaceNamesInRule(String rule, String cardName) {
+ String res = rule.replaceAll("\\{this\\}", cardName.isEmpty() ? "this" : cardName);
+ res = res.replaceAll("\\{source\\}", cardName.isEmpty() ? "this" : cardName);
+ return res;
+ }
+
private static String getResourcePath(String image) {
return GuiDisplayUtil.class.getClassLoader().getResource(image).toString();
}
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java
index e4c84b3ac38..f298ffb70da 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanelRenderImpl.java
@@ -154,6 +154,7 @@ public class CardPanelRenderImpl extends CardPanel {
sb.append(this.view.getToughness());
sb.append(this.view.getLoyalty());
sb.append(this.view.getColor().toString());
+ sb.append(this.view.getType());
sb.append(this.view.getExpansionSetCode());
for (CardType type : this.view.getCardTypes()) {
sb.append((char) type.ordinal());
@@ -227,7 +228,7 @@ public class CardPanelRenderImpl extends CardPanel {
private BufferedImage faceArtImage;
// Factory to generate card appropriate views
- private CardRendererFactory cardRendererFactory = new CardRendererFactory();
+ private final CardRendererFactory cardRendererFactory = new CardRendererFactory();
// The rendered card image, with or without the art image loaded yet
// = null while invalid
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java
index 048d4d42dbe..bdb099bac93 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java
@@ -140,13 +140,30 @@ public abstract class CardRenderer {
break;
}
+ // workaround to use real split card names
+ String realCardName = cardView.getDisplayName();
+ if (cardView.isSplitCard()) {
+ for (String partRule : cardView.getLeftSplitRules()) {
+ if (partRule.equals(rule)) {
+ realCardName = cardView.getLeftSplitName();
+ break;
+ }
+ }
+ for (String partRule : cardView.getRightSplitRules()) {
+ if (partRule.equals(rule)) {
+ realCardName = cardView.getRightSplitName();
+ break;
+ }
+ }
+ }
+
// Kill reminder text
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_REMINDER_TEXT, "false").equals("false")) {
rule = CardRendererUtils.killReminderText(rule).trim();
}
if (!rule.isEmpty()) {
- TextboxRule tbRule = TextboxRuleParser.parse(cardView, rule);
+ TextboxRule tbRule = TextboxRuleParser.parse(cardView, rule, realCardName);
if (tbRule.type == TextboxRuleType.SIMPLE_KEYWORD) {
keywords.add(tbRule);
} else if (tbRule.text.isEmpty()) {
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRule.java b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRule.java
index 9dafbcb32bd..371c8158e21 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRule.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRule.java
@@ -7,6 +7,7 @@ package org.mage.card.arcane;
import java.awt.Font;
import java.awt.Image;
+import java.awt.Paint;
import java.awt.font.GraphicAttribute;
import java.awt.font.ImageGraphicAttribute;
import java.awt.font.TextAttribute;
@@ -47,6 +48,25 @@ public class TextboxRule {
}
}
+ public static class ColorRegion implements AttributeRegion {
+
+ ColorRegion(int start, int end, Paint color) {
+ this.start = start;
+ this.end = end;
+ this.color = color;
+ }
+ private final int start;
+ private final int end;
+ private final Paint color;
+
+ @Override
+ public void applyToAttributedString(AttributedString str, Font normal, Font italic) {
+ if (end > start + 1) {
+ str.addAttribute(TextAttribute.FOREGROUND, color, start, end);
+ }
+ }
+ }
+
// A special symbol embedded at some point in a string
public static class EmbeddedSymbol implements AttributeRegion {
diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleParser.java b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleParser.java
index e89873a6701..27fc01cd62e 100644
--- a/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleParser.java
+++ b/Mage.Client/src/main/java/org/mage/card/arcane/TextboxRuleParser.java
@@ -23,13 +23,14 @@ public final class TextboxRuleParser {
private static final Pattern LevelAbilityPattern = Pattern.compile("Level (\\d+)-?(\\d*)(\\+?)");
private static final Pattern LoyaltyAbilityPattern = Pattern.compile("^(\\+|\\-)(\\d+|X): ");
private static final Pattern SimpleKeywordPattern = Pattern.compile("^(\\w+( \\w+)?)\\s*(\\([^\\)]*\\))?\\s*$");
+ private static final Pattern FontColorValuePattern = Pattern.compile("color\\s*=\\s*[\"'](\\w+)[\"']");
// Parse a given rule (given as a string) into a TextboxRule, replacing
// symbol annotations, italics, etc, parsing out information such as
// if the ability is a loyalty ability, and returning an TextboxRule
// representing that information, which can be used to render the rule in
// the textbox of a card.
- public static TextboxRule parse(CardView source, String rule) {
+ public static TextboxRule parse(CardView source, String rule, String cardNameToUse) {
// List of regions to apply
List regions = new ArrayList<>();
@@ -103,10 +104,9 @@ public final class TextboxRuleParser {
String contents = rule.substring(index + 1, closeIndex);
if (contents.equals("this") || contents.equals("source")) {
// Replace {this} with the card's name
- String cardName = source.getName();
- build.append(cardName);
+ build.append(cardNameToUse);
index += contents.length() + 2;
- outputIndex += cardName.length();
+ outputIndex += cardNameToUse.length();
} else {
Image symbol = ManaSymbols.getSizedManaSymbol(contents.replace("/", ""), 10);
if (symbol != null) {
@@ -200,6 +200,11 @@ public final class TextboxRuleParser {
}
}
break;
+ case "/font":
+ // Font it is an additional info of a card
+ // lets make it blue like it is in tooltip
+ regions.add(new TextboxRule.ColorRegion(openingIndex, outputIndex, Color.BLUE));
+ break;
default:
// Unknown
build.append('<').append(tag).append('>');
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java
index 7cd59d0a215..9d6cebf890a 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GrabbagImageSource.java
@@ -18,14 +18,13 @@ public enum GrabbagImageSource implements CardImageSource {
private static final Set supportedSets = new LinkedHashSet() {
{
- add("PTC");
add("SWS");
}
};
@Override
public String getSourceName() {
- return "";
+ return "Grabbag";
}
@Override
@@ -76,16 +75,6 @@ public enum GrabbagImageSource implements CardImageSource {
return;
}
singleLinks = new HashMap<>();
- singleLinks.put("PTC/Arbiter of the Ideal", "MTG/BNG/en/promo/ArbiterOfTheIdeal.jpg");
- singleLinks.put("PTC/Courser of Kruphix", "MTG/BNG/en/promo/CourserOfKruphix.jpg");
- singleLinks.put("PTC/Eater of Hope", "MTG/BNG/en/promo/EaterOfHope.jpg");
- singleLinks.put("PTC/Fated Return", "MTG/BNG/en/promo/FatedReturn.jpg");
- singleLinks.put("PTC/Forgestoker Dragon", "MTG/BNG/en/promo/ForgestokerDragon.jpg");
- singleLinks.put("PTC/Nessian Wilds Ravager", "MTG/BNG/en/promo/NessianWildsRavager.jpg");
- singleLinks.put("PTC/Pain Seer", "MTG/BNG/en/promo/PainSeer.jpg");
- singleLinks.put("PTC/Silent Sentinel", "MTG/BNG/en/promo/SilentSentinel.jpg");
- singleLinks.put("PTC/Tromokratis", "MTG/BNG/en/promo/Tromokratis.jpg");
-
singleLinks.put("SWS/AAT-1", "CqmDY8V.jpg");
singleLinks.put("SWS/Acklay of the Arena", "ESVRm6F.jpg");
singleLinks.put("SWS/Acquire Target", "FOskB4q.jpg");
@@ -478,7 +467,7 @@ public enum GrabbagImageSource implements CardImageSource {
if (card.getSet().equals("MTG")) {
return "http://static.starcitygames.com/sales/cardscans/";
} else if (card.getSet().equals("SWS")) {
- return "http://i.imgur.com/";
+ return "https://i.imgur.com/";
} else {
return "http://magiccards.info/scans/en/";
}
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java
index e2234547e88..1207706b7ed 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportCards.java
@@ -260,6 +260,8 @@ public class ScryfallImageSupportCards {
add("PPP1");
add("PF19");
add("MPS-AKH");
+ add("M21");
+ add("JMP");
}
};
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java
index 242acb7306f..4fc76ae7aab 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSupportTokens.java
@@ -94,16 +94,33 @@ public class ScryfallImageSupportTokens {
put("HOU/Insect", "https://api.scryfall.com/cards/thou/12/en?format=image");
put("HOU/Snake", "https://api.scryfall.com/cards/thou/11/en?format=image");
- //AKH
+ //AKH - tokens
put("AKH/Beast", "https://api.scryfall.com/cards/takh/21/en?format=image");
put("AKH/Cat", "https://api.scryfall.com/cards/takh/16/en?format=image");
put("AKH/Drake", "https://api.scryfall.com/cards/takh/18/en?format=image");
put("AKH/Emblem Gideon", "https://api.scryfall.com/cards/takh/25/en?format=image");
put("AKH/Hippo", "https://api.scryfall.com/cards/takh/22/en?format=image");
+ put("AKH/Insect", "https://api.scryfall.com/cards/takh/19/en?format=image");
put("AKH/Snake", "https://api.scryfall.com/cards/takh/23/en?format=image");
put("AKH/Warrior", "https://api.scryfall.com/cards/takh/17/en?format=image");
put("AKH/Wurm", "https://api.scryfall.com/cards/takh/24/en?format=image");
put("AKH/Zombie", "https://api.scryfall.com/cards/takh/20/en?format=image");
+ //AKH - embalm ability (token from card)
+ put("AKH/Angel of Sanctions", "https://api.scryfall.com/cards/takh/1/en?format=image");
+ put("AKH/Anointer Priest", "https://api.scryfall.com/cards/takh/2/en?format=image");
+ put("AKH/Aven Initiate", "https://api.scryfall.com/cards/takh/3/en?format=image");
+ put("AKH/Aven Wind Guide", "https://api.scryfall.com/cards/takh/4/en?format=image");
+ put("AKH/Glyph Keeper", "https://api.scryfall.com/cards/takh/5/en?format=image");
+ put("AKH/Heart-Piercer Manticore", "https://api.scryfall.com/cards/takh/6/en?format=image");
+ put("AKH/Honored Hydra", "https://api.scryfall.com/cards/takh/7/en?format=image");
+ put("AKH/Labyrinth Guardian", "https://api.scryfall.com/cards/takh/8/en?format=image");
+ put("AKH/Oketra's Attendant", "https://api.scryfall.com/cards/takh/9/en?format=image");
+ put("AKH/Sacred Cat", "https://api.scryfall.com/cards/takh/10/en?format=image");
+ put("AKH/Tah-Crop Skirmisher", "https://api.scryfall.com/cards/takh/11/en?format=image");
+ put("AKH/Temmet, Vizier of Naktamun", "https://api.scryfall.com/cards/takh/12/en?format=image");
+ put("AKH/Trueheart Duelist", "https://api.scryfall.com/cards/takh/13/en?format=image");
+ put("AKH/Unwavering Initiate", "https://api.scryfall.com/cards/takh/14/en?format=image");
+ put("AKH/Vizier of Many Faces", "https://api.scryfall.com/cards/takh/15/en?format=image");
//AER
put("AER/Etherium Cell", "https://api.scryfall.com/cards/taer/3/en?format=image");
@@ -350,6 +367,20 @@ public class ScryfallImageSupportTokens {
put("THB/Wolf", "https://api.scryfall.com/cards/tthb/11/en?format=image");
put("THB/Zombie", "https://api.scryfall.com/cards/tthb/7/en?format=image");
+ // IKO
+ put("IKO/Emblem Narset Of The Ancient Way", "https://api.scryfall.com/cards/tiko/12/en?format=image");
+ put("IKO/Beast", "https://api.scryfall.com/cards/tiko/10/en?format=image");
+ put("IKO/Cat Bird", "https://api.scryfall.com/cards/tiko/2/en?format=image");
+ put("IKO/Cat", "https://api.scryfall.com/cards/tiko/1/en?format=image");
+ put("IKO/Dinosaur Beast", "https://api.scryfall.com/cards/tiko/11/en?format=image");
+ put("IKO/Dinosaur", "https://api.scryfall.com/cards/tiko/8/en?format=image");
+ put("IKO/Feather", "https://api.scryfall.com/cards/tiko/9/en?format=image");
+ put("IKO/Human Soldier/1", "https://api.scryfall.com/cards/tiko/3/en?format=image");
+ put("IKO/Human Soldier/2", "https://api.scryfall.com/cards/tiko/4/en?format=image");
+ put("IKO/Human Soldier/3", "https://api.scryfall.com/cards/tiko/5/en?format=image");
+ put("IKO/Kraken", "https://api.scryfall.com/cards/tiko/6/en?format=image");
+ put("IKO/Shark", "https://api.scryfall.com/cards/tiko/7/en?format=image");
+
// PCA (planes)
put("PCA/Eldrazi", "https://api.scryfall.com/cards/tpca/1/en?format=image");
put("PCA/Plane - Academy at Tolaria West", "https://api.scryfall.com/cards/opca/9/en?format=image");
@@ -374,6 +405,27 @@ public class ScryfallImageSupportTokens {
put("PCA/Plane - Turri Island", "https://api.scryfall.com/cards/opca/82/en?format=image");
put("PCA/Plane - Undercity Reaches", "https://api.scryfall.com/cards/opca/83/en?format=image");
+ // C20
+ put("C20/Angel", "https://api.scryfall.com/cards/tc20/1/en?format=image");
+ put("C20/Beast", "https://api.scryfall.com/cards/tc20/11/en?format=image");
+ put("C20/Bird Illusion", "https://api.scryfall.com/cards/tc20/7/en?format=image");
+ put("C20/Bird", "https://api.scryfall.com/cards/tc20/2/en?format=image");
+ put("C20/Dinosaur Cat", "https://api.scryfall.com/cards/tc20/16/en?format=image");
+ put("C20/Drake", "https://api.scryfall.com/cards/tc20/8/en?format=image");
+ put("C20/Elemental/1", "https://api.scryfall.com/cards/tc20/10/en?format=image"); // 3/1
+ put("C20/Elemental/2", "https://api.scryfall.com/cards/tc20/3/en?format=image"); // 4/4
+ put("C20/Goblin Warrior", "https://api.scryfall.com/cards/tc20/17/en?format=image");
+ put("C20/Human", "https://api.scryfall.com/cards/tc20/4/en?format=image");
+ put("C20/Hydra", "https://api.scryfall.com/cards/tc20/12/en?format=image");
+ put("C20/Insect/1", "https://api.scryfall.com/cards/tc20/13/en?format=image"); // deathtouch
+ put("C20/Insect/2", "https://api.scryfall.com/cards/tc20/18/en?format=image"); // haste
+ put("C20/Saproling", "https://api.scryfall.com/cards/tc20/14/en?format=image");
+ put("C20/Snake", "https://api.scryfall.com/cards/tc20/15/en?format=image");
+ put("C20/Soldier", "https://api.scryfall.com/cards/tc20/5/en?format=image");
+ put("C20/Spirit", "https://api.scryfall.com/cards/tc20/6/en?format=image");
+ put("C20/Treasure", "https://api.scryfall.com/cards/tc20/19/en?format=image");
+ put("C20/Zombie", "https://api.scryfall.com/cards/tc20/9/en?format=image");
+
// generate supported sets
supportedSets.clear();
for (String cardName : this.keySet()) {
diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java
index a077bdf9678..0b3b528436b 100644
--- a/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java
+++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java
@@ -47,7 +47,7 @@ public final class ImageCache {
private static final SoftValuesLoadingCache FACE_IMAGE_CACHE;
/**
- * Common pattern for keys. Format: "##"
+ * Common pattern for keys. See ImageCache.getKey for structure info
*/
private static final Pattern KEY_PATTERN = Pattern.compile("(.*)#(.*)#(.*)#(.*)#(.*)#(.*)");
@@ -84,13 +84,21 @@ public final class ImageCache {
boolean cardback = false;
String path;
- if (collectorId.isEmpty() || "0".equals(collectorId)) {
+ if (collectorId.isEmpty() || "0".equals(collectorId) || !tokenDescriptor.isEmpty()) { // tokenDescriptor for embalm ability
info.setToken(true);
path = CardImageUtils.generateTokenImagePath(info);
if (path == null) {
cardback = true;
- // TODO: replace empty token by other default card, not cardback
- path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
+ // try token image from card
+ CardDownloadData newInfo = new CardDownloadData(info);
+ newInfo.setToken(false);
+ path = CardImageUtils.buildImagePathToCard(newInfo);
+ TFile tokenFile = getTFile(path);
+ if (tokenFile == null || !tokenFile.exists()) {
+ // token empty token image
+ // TODO: replace empty token by other default card, not cardback
+ path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
+ }
}
} else {
path = CardImageUtils.buildImagePathToCard(info);
@@ -245,12 +253,20 @@ public final class ImageCache {
CardDownloadData info = new CardDownloadData(name, set, collectorId, usesVariousArt, type, tokenSetCode, tokenDescriptor);
String path;
- if (collectorId.isEmpty() || "0".equals(collectorId)) {
+ if (collectorId.isEmpty() || "0".equals(collectorId) || !tokenDescriptor.isEmpty()) { // tokenDescriptor for embalm ability
info.setToken(true);
- path = CardImageUtils.generateFullTokenImagePath(info);
+ path = CardImageUtils.generateTokenImagePath(info);
if (path == null) {
- // TODO: replace empty token by other default card, not cardback
- path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
+ // try token image from card
+ CardDownloadData newInfo = new CardDownloadData(info);
+ newInfo.setToken(false);
+ path = CardImageUtils.buildImagePathToCard(newInfo);
+ TFile tokenFile = getTFile(path);
+ if (tokenFile == null || !tokenFile.exists()) {
+ // token empty token image
+ // TODO: replace empty token by other default card, not cardback
+ path = CardImageUtils.buildImagePathToDefault(DirectLinksForDownload.cardbackFilename);
+ }
}
} else {
path = CardImageUtils.buildImagePathToCard(info);
@@ -428,11 +444,14 @@ public final class ImageCache {
* Returns the map key for a card, without any suffixes for the image size.
*/
private static String getKey(CardView card, String name, String suffix) {
- return name + '#' + card.getExpansionSetCode() + '#' + card.getType() + '#' + card.getCardNumber() + '#'
- + (card.getTokenSetCode() == null ? "" : card.getTokenSetCode())
+ return name
+ + '#' + card.getExpansionSetCode()
+ + '#' + card.getType()
+ + '#' + card.getCardNumber()
+ + '#' + (card.getTokenSetCode() == null ? "" : card.getTokenSetCode())
+ suffix
+ (card.getUsesVariousArt() ? "#usesVariousArt" : "")
- + (card.getTokenDescriptor() != null ? '#' + card.getTokenDescriptor() : "#");
+ + '#' + (card.getTokenDescriptor() != null ? card.getTokenDescriptor() : "");
}
/**
diff --git a/Mage.Client/src/main/resources/card-pictures-tok.txt b/Mage.Client/src/main/resources/card-pictures-tok.txt
index 9d1c954caf7..068eead09fd 100644
--- a/Mage.Client/src/main/resources/card-pictures-tok.txt
+++ b/Mage.Client/src/main/resources/card-pictures-tok.txt
@@ -101,6 +101,7 @@
|Generate|EMBLEM:DOM|Teferi, Hero of Dominaria||Emblem Teferi|TeferiHeroOfDominariaEmblem|
|Generate|EMBLEM:AER|Tezzeret the Schemer||Emblem Tezzeret|TezzeretTheSchemerEmblem|
|Generate|EMBLEM:ELD|Garruk, Cursed Huntsman||Emblem Garruk|GarrukCursedHuntsmanEmblem|
+|Generate|EMBLEM:IKO|Narset Of The Ancient Way||Emblem Narset|NarsetOfTheAncientWayEmblem|
|Generate|PLANE:PCA|Plane - Academy at Tolaria West|||AcademyAtTolariaWestPlane|
|Generate|PLANE:PCA|Plane - Agyrem|||AgyremPlane|
|Generate|PLANE:PCA|Plane - Akoum|||AkoumPlane|
@@ -153,7 +154,7 @@
|Generate|TOK:5ED|Serf|||SerfToken|
|Generate|TOK:5ED|Snake|||SerpentGeneratorSnakeToken|
|Generate|TOK:5ED|Thrull|||BreedingPitBlackInsectToken|
-|Generate|TOK:6ED|Cat|||WaitingInTheWeedsCatToken|
+|Generate|TOK:6ED|Cat|||GreenCatToken|
|Generate|TOK:6ED|Citizen|||CitizenToken|
|Generate|TOK:6ED|Djinn|||DjinnToken|
|Generate|TOK:6ED|Goblin|||GoblinToken|
@@ -167,30 +168,34 @@
|Generate|TOK:AER|Etherium Cell|||EtheriumCellToken|
|Generate|TOK:AER|Gremlin|||GremlinToken|
|Generate|TOK:AER|Ragavan|||RagavanToken|
+
+# AKH
|Generate|TOK:AKH|Beast|||BeastToken3|
|Generate|TOK:AKH|Cat|||CatToken2|
|Generate|TOK:AKH|Drake|||DrakeToken|
|Generate|TOK:AKH|Hippo|||HippoToken2|
+|Generate|TOK:AKH|Insect|||NestOfScarabsBlackInsectToken|
|Generate|TOK:AKH|Snake|||DeathtouchSnakeToken|
|Generate|TOK:AKH|Warrior|||WarriorVigilantToken|
-|Generate|TOK:AKH|Wurm|||WurmToken3|
-|Generate|TOK:AKH|Zombie|||ZombieToken
+|Generate|TOK:AKH|Wurm|||Wurm55Token|
+|Generate|TOK:AKH|Zombie|||ZombieToken|
#TOK:AKH - some tokens from real cards (see Embalm ability)
-#|Generate|TOK:AKH|Angel of Sanctions||
-#|Generate|TOK:AKH|Anointer Priest||
-#|Generate|TOK:AKH|Aven Initiate||
-#|Generate|TOK:AKH|Aven Wind Guide||
-#|Generate|TOK:AKH|Glyph Keeper||
-#|Generate|TOK:AKH|Heart-Piercer Manticore||
-#|Generate|TOK:AKH|Honored Hydra||
-#|Generate|TOK:AKH|Labyrinth Guardian||
-#|Generate|TOK:AKH|Oketra's Attendant||
-#|Generate|TOK:AKH|Sacred Cat||
-#|Generate|TOK:AKH|Tah-Crop Skirmisher||
-#|Generate|TOK:AKH|Temmet, Vizier of Naktamun||
-#|Generate|TOK:AKH|Trueheart Duelist||
-#|Generate|TOK:AKH|Unwavering Initiate||
-#|Generate|TOK:AKH|Vizier of Many Faces||
+|Generate|TOK:AKH|Angel of Sanctions||
+|Generate|TOK:AKH|Anointer Priest||
+|Generate|TOK:AKH|Aven Initiate||
+|Generate|TOK:AKH|Aven Wind Guide||
+|Generate|TOK:AKH|Glyph Keeper||
+|Generate|TOK:AKH|Heart-Piercer Manticore||
+|Generate|TOK:AKH|Honored Hydra||
+|Generate|TOK:AKH|Labyrinth Guardian||
+|Generate|TOK:AKH|Oketra's Attendant||
+|Generate|TOK:AKH|Sacred Cat||
+|Generate|TOK:AKH|Tah-Crop Skirmisher||
+|Generate|TOK:AKH|Temmet, Vizier of Naktamun||
+|Generate|TOK:AKH|Trueheart Duelist||
+|Generate|TOK:AKH|Unwavering Initiate||
+|Generate|TOK:AKH|Vizier of Many Faces||
+
|Generate|TOK:ALA|Beast|||GodSireBeastToken|
|Generate|TOK:ALA|Dragon|||DragonToken|
|Generate|TOK:ALA|Goblin|||GoblinTokenWithHaste|
@@ -269,9 +274,9 @@
|Generate|TOK:C13|Beast|||OneDozenEyesBeastToken|
|Generate|TOK:C13|Beast|||SpawningGroundsBeastToken|
|Generate|TOK:C13|Drake|||LeafdrakeRoostDrakeToken|
-|Generate|TOK:C13|Elemental|||SeedGuardianToken|
-|Generate|TOK:C13|Elemental|||WalkerOfTheGroveToken|
-|Generate|TOK:C13|Elemental|||YoungPyromancerElementalToken|
+|Generate|TOK:C13|Elemental|1||SeedGuardianToken|
+|Generate|TOK:C13|Elemental|2||WalkerOfTheGroveToken|
+|Generate|TOK:C13|Elemental|3||RedElementalToken|
|Generate|TOK:C13|Elephant|||ElephantToken|
|Generate|TOK:C13|Elf Warrior|||ElfToken|
|Generate|TOK:C13|Goat|||GoatToken|
@@ -318,8 +323,8 @@
|Generate|TOK:C14|Treefolk|||SylvanOfferingTreefolkToken|
|Generate|TOK:C14|Whale|||ReefWormWhaleToken|
|Generate|TOK:C14|Wolf|||WolfToken|
-|Generate|TOK:C14|Wurm|1||Wurm1Token|
-|Generate|TOK:C14|Wurm|2||Wurm2Token|
+|Generate|TOK:C14|Wurm|1||WurmWithDeathtouchToken|
+|Generate|TOK:C14|Wurm|2||WurmWithLifelinkToken|
|Generate|TOK:C14|Zombie|1||ZombieToken|
|Generate|TOK:C14|Zombie|2||StitcherGeralfZombieToken|
|Generate|TOK:C15|Angel|||AngelToken|
@@ -350,7 +355,7 @@
|Generate|TOK:C16|Beast||
|Generate|TOK:C16|Bird|1|
|Generate|TOK:C16|Bird|2|
-|Generate|TOK:C16|Elemental||
+|Generate|TOK:C16|Elemental|||WhiteElementalToken|
|Generate|TOK:C16|Elf Warrior||
|Generate|TOK:C16|Germ||
|Generate|TOK:C16|Goat||
@@ -368,7 +373,7 @@
|Generate|TOK:C16|Worm||
|Generate|TOK:C16|Zombie||
|Generate|TOK:C17|Bat||
-|Generate|TOK:C17|Cat||
+|Generate|TOK:C17|Cat|||CatToken|
|Generate|TOK:C17|Cat Dragon|||WasitoraCatDragonToken|
|Generate|TOK:C17|Cat Warrior||
|Generate|TOK:C17|Dragon|1||DragonToken|
@@ -566,11 +571,11 @@
|Generate|TOK:DGM|Rhino|||RhinoToken|
|Generate|TOK:DGM|Soldier|||SoldierTokenWithHaste|
|Generate|TOK:DGM|Spirit|||TeysaEnvoyOfGhostsToken|
-|Generate|TOK:DGM|Wurm|||WurmToken2|
-|Generate|TOK:DGM|Wurm|||WurmToken3|
+|Generate|TOK:DGM|Wurm|1||WurmWithTrampleToken|
+|Generate|TOK:DGM|Wurm|2||Wurm55Token|
|Generate|TOK:DIS|Bird|||DovescapeToken|
|Generate|TOK:DIS|Drake|||LeafdrakeRoostDrakeToken|
-|Generate|TOK:DIS|Elemental|||ElementalToken|
+|Generate|TOK:DIS|Elemental|||ResearchDevelopmentToken|
|Generate|TOK:DIS|Goblin|||RakdosGuildmageGoblinToken|
|Generate|TOK:DIS|Saproling|||SaprolingToken|
|Generate|TOK:DIS|Snake|||PatagiaViperSnakeToken|
@@ -618,7 +623,7 @@
|Generate|TOK:EMA|Beast|||CarnivoreToken|
|Generate|TOK:EMA|Carnivore||
|Generate|TOK:EMA|Dragon|||DragonEggDragonToken|
-|Generate|TOK:EMA|Elemental|1||YoungPyromancerElementalToken|
+|Generate|TOK:EMA|Elemental|1||RedElementalToken|
|Generate|TOK:EMA|Elemental|2||CallTheSkyBreakerElementalToken|
|Generate|TOK:EMA|Elephant|||ElephantToken|
|Generate|TOK:EMA|Elf Warrior|||ElfToken|
@@ -654,7 +659,7 @@
|Generate|TOK:EVE|Spirit|||BeckonApparitionToken|
|Generate|TOK:EVE|Wolf|||WolfToken|
|Generate|TOK:EVE|Worm|||WormHarvestToken|
-|Generate|TOK:EVG|Elemental||
+|Generate|TOK:EVG|Elemental|||VoiceOfTheWoodsElementalToken|
|Generate|TOK:EVG|Elf Warrior|||ElfToken|
|Generate|TOK:EVG|Goblin|||GoblinToken|
|Generate|TOK:EXO|Pegasus|||PegasusToken|
@@ -790,8 +795,8 @@
|Generate|TOK:LRW|Avatar|||AvatarToken|
|Generate|TOK:LRW|Beast|||BeastToken|
|Generate|TOK:LRW|Elemental Shaman|||ElementalShamanToken|
-|Generate|TOK:LRW|Elemental|||WalkerOfTheGroveToken|
-|Generate|TOK:LRW|Elemental|||WhiteElementalToken|
+|Generate|TOK:LRW|Elemental|1||WalkerOfTheGroveToken|
+|Generate|TOK:LRW|Elemental|2||WhiteElementalToken|
|Generate|TOK:LRW|Elf Warrior|||ElfToken|
|Generate|TOK:LRW|Goblin Rogue|||GoblinRogueToken|
|Generate|TOK:LRW|Kithkin Soldier|||KithkinToken|
@@ -833,8 +838,8 @@
|Generate|TOK:M14|Beast|||BeastToken|
|Generate|TOK:M14|Cat|||CatToken|
|Generate|TOK:M14|Dragon|||DragonEggDragonToken|
-|Generate|TOK:M14|Elemental|1||YoungPyromancerElementalToken|
-|Generate|TOK:M14|Elemental|2||YoungPyromancerElementalToken|
+|Generate|TOK:M14|Elemental|1||RedElementalToken|
+|Generate|TOK:M14|Elemental|2||RedElementalToken|
|Generate|TOK:M14|Goat|||GoatToken|
|Generate|TOK:M14|Saproling|||SaprolingToken|
|Generate|TOK:M14|Sliver||
@@ -908,7 +913,7 @@
|Generate|TOK:MM3|Bird||
|Generate|TOK:MM3|Centaur||
|Generate|TOK:MM3|Dragon||
-|Generate|TOK:MM3|Elemental||
+|Generate|TOK:MM3|Elemental|||VoiceOfResurgenceToken|
|Generate|TOK:MM3|Elephant||
|Generate|TOK:MM3|Giant Warrior||
|Generate|TOK:MM3|Goblin Warrior||
@@ -955,7 +960,7 @@
|Generate|TOK:MOR|Wolf|||WolfToken|
|Generate|TOK:MRD|Beast|||OneDozenEyesBeastToken|
|Generate|TOK:MRD|Demon|||ReignOfThePitToken|
-|Generate|TOK:MRD|Elemental|||ElementalToken|
+|Generate|TOK:MRD|Elemental|||ElementalTokenWithHaste|
|Generate|TOK:MRD|Insect|||InsectToken|
|Generate|TOK:MRD|Myr|||MyrToken|
|Generate|TOK:MRD|Pentavite|||PentaviteToken|
@@ -989,7 +994,7 @@
|Generate|TOK:OGW|Eldrazi Scion|5||EldraziScionToken|
|Generate|TOK:OGW|Eldrazi Scion|6||EldraziScionToken|
|Generate|TOK:OGW|Elemental|1||SeedGuardianToken|
-|Generate|TOK:OGW|Elemental|2||ElementalToken|
+|Generate|TOK:OGW|Elemental|2||ElementalTokenWithHaste|
|Generate|TOK:OGW|Knight Ally|||KnightAllyToken|
|Generate|TOK:OGW|Kor Ally|||KorAllyToken|
|Generate|TOK:OGW|Octopus|||OctopusToken|
@@ -1062,21 +1067,21 @@
|Generate|TOK:RTR|Bird|||BirdToken|
|Generate|TOK:RTR|Centaur|||CentaurToken|
|Generate|TOK:RTR|Dragon|||UtvaraHellkiteDragonToken|
-|Generate|TOK:RTR|Elemental||
+|Generate|TOK:RTR|Elemental|||GreenAndWhiteElementalToken|
|Generate|TOK:RTR|Goblin|||GoblinToken|
|Generate|TOK:RTR|Knight|||KnightToken|
|Generate|TOK:RTR|Ooze|||MysticGenesisOozeToken|
|Generate|TOK:RTR|Rhino|||RhinoToken|
|Generate|TOK:RTR|Saproling|||SaprolingToken|
|Generate|TOK:RTR|Soldier|||SoldierToken|
-|Generate|TOK:RTR|Wurm|||WurmToken2|
+|Generate|TOK:RTR|Wurm|||WurmWithTrampleToken|
|Generate|TOK:SCG|Angel|||AngelToken|
|Generate|TOK:SCG|Beast|||BeastToken2|
|Generate|TOK:SCG|Dragon|||DragonToken2|
|Generate|TOK:SCG|Goblin|||GoblinToken|
|Generate|TOK:SCG|Soldier|||SoldierToken|
|Generate|TOK:SHM|Elemental|1||DinOfTheFireherdToken|
-|Generate|TOK:SHM|Elemental|2||YoungPyromancerElementalToken|
+|Generate|TOK:SHM|Elemental|2||RedElementalToken|
|Generate|TOK:SHM|Elf Warrior|1|
|Generate|TOK:SHM|Elf Warrior|2|
|Generate|TOK:SHM|Elf Warrior|||ElfToken|
@@ -1105,7 +1110,7 @@
|Generate|TOK:SOI|Vampire Knight|||VampireKnightToken|
|Generate|TOK:SOI|Wolf|||WolfToken|
|Generate|TOK:SOI|Zombie|||ZombieToken|
-|Generate|TOK:SOK|Elemental|||ElementalToken|
+|Generate|TOK:SOK|Elemental|||ElementalTokenWithHaste|
|Generate|TOK:SOK|Snake|||SnakeToken|
|Generate|TOK:SOK|Spirit|||SpiritToken|
|Generate|TOK:SOK|Urami|||UramiToken|
@@ -1117,8 +1122,8 @@
|Generate|TOK:SOM|Myr|||MyrToken|
|Generate|TOK:SOM|Soldier|||SoldierToken|
|Generate|TOK:SOM|Wolf|||WolfToken|
-|Generate|TOK:SOM|Wurm|1||Wurm1Token|
-|Generate|TOK:SOM|Wurm|2||Wurm2Token|
+|Generate|TOK:SOM|Wurm|1||WurmWithDeathtouchToken|
+|Generate|TOK:SOM|Wurm|2||WurmWithLifelinkToken|
|Generate|TOK:STH|Goblin|||GoblinToken|
|Generate|TOK:STH|Insect|||HornetToken|
|Generate|TOK:STH|Insect|||WaspToken|
@@ -1146,7 +1151,7 @@
|Generate|TOK:THS|Soldier|1||SoldierToken|
|Generate|TOK:THS|Soldier|2||SoldierToken|
|Generate|TOK:TMP|Beast|||CarnivoreToken|
-|Generate|TOK:TMP|Hound|||HoundToken|
+|Generate|TOK:TMP|Dog|||GreenDogToken|
|Generate|TOK:TMP|Pegasus|||PegasusToken|
|Generate|TOK:TMP|Reflection|||ReflectionToken|
|Generate|TOK:TMP|Saproling|||SaprolingToken|
@@ -1213,8 +1218,8 @@
|Generate|TOK:VMA|Spirit|||SpiritWhiteToken|
|Generate|TOK:VMA|Squirrel|||SquirrelToken|
|Generate|TOK:VMA|Thopter|||ThopterColorlessToken|
-|Generate|TOK:VMA|Wurm|||PenumbraWurmToken|
-|Generate|TOK:VMA|Wurm|||WurmToken|
+|Generate|TOK:VMA|Wurm|1||PenumbraWurmToken|
+|Generate|TOK:VMA|Wurm|2||WurmToken|
|Generate|TOK:VMA|Zombie|||ZombieToken|
|Generate|TOK:WTH|Squirrel|||SquirrelToken|
|Generate|TOK:WWK|Construct|||StoneTrapIdolToken|
@@ -1238,8 +1243,8 @@
|Generate|TOK:ZEN|Angel|||AngelToken|
|Generate|TOK:ZEN|Beast|||BeastToken2|
|Generate|TOK:ZEN|Bird|||BirdToken|
-|Generate|TOK:ZEN|Elemental||
-|Generate|TOK:ZEN|Elemental|||ZektarShrineElementalToken|
+|Generate|TOK:ZEN|Elemental|1||RedElementalWithTrampleAndHaste|
+|Generate|TOK:ZEN|Elemental|2||RedElementalWithTrampleAndHaste|
|Generate|TOK:ZEN|Illusion|||IllusionToken|
|Generate|TOK:ZEN|Kor Soldier|||KorSoldierToken|
|Generate|TOK:ZEN|Merfolk||
@@ -1268,6 +1273,7 @@
|Generate|TOK:GRN|Soldier|||SoldierLifelinkToken|
|Generate|TOK:WAR|Angel|||AngelVigilanceToken|
|Generate|TOK:WAR|Assassin|||AssassinToken2|
+|Generate|TOK:WAR|Citizen|||PlanewideCelebrationToken|
|Generate|TOK:WAR|Devil|||DevilToken|
|Generate|TOK:WAR|Dragon|||DragonToken|
|Generate|TOK:WAR|Goblin|||GoblinToken|
@@ -1288,7 +1294,7 @@
|Generate|TOK:MH1|Bear|||BearToken|
|Generate|TOK:MH1|Bird|||BirdToken|
|Generate|TOK:MH1|Construct|||KarnConstructToken|
-|Generate|TOK:MH1|Elemental|1||YoungPyromancerElementalToken|
+|Generate|TOK:MH1|Elemental|1||RedElementalToken|
|Generate|TOK:MH1|Elemental|2||AkoumStonewakerElementalToken|
|Generate|TOK:MH1|Elephant|||ElephantToken|
|Generate|TOK:MH1|Goblin|||GoblinToken|
@@ -1318,7 +1324,7 @@
|Generate|TOK:M19|Zombie|||ZombieToken|
|Generate|TOK:M20|Ajani's Pridemate|||AjanisPridemateToken|
|Generate|TOK:M20|Demon|||DemonToken|
-|Generate|TOK:M20|Elemental|||YoungPyromancerElementalToken|
+|Generate|TOK:M20|Elemental|||RedElementalToken|
|Generate|TOK:M20|Elemental Bird|||MuYanlingSkyDancerToken|
|Generate|TOK:M20|Golem|||GolemToken|
|Generate|TOK:M20|Soldier|||SoldierToken|
@@ -1326,6 +1332,8 @@
|Generate|TOK:M20|Treasure|||TreasureToken|
|Generate|TOK:M20|Wolf|||WolfToken|
|Generate|TOK:M20|Zombie|||ZombieToken|
+
+# ELD
|Generate|TOK:ELD|Bear|||BearToken|
|Generate|TOK:ELD|Boar|||WolfsQuarryToken|
|Generate|TOK:ELD|Dwarf|||DwarfToken|
@@ -1344,6 +1352,8 @@
|Generate|TOK:ELD|Mouse|||MouseToken|
|Generate|TOK:ELD|Rat|||RatToken|
|Generate|TOK:ELD|Wolf|||GarrukCursedHuntsmanToken|
+
+# THB
|Generate|TOK:THB|Goat|||GoatToken|
|Generate|TOK:THB|Human Soldier|||HumanSoldierToken|
|Generate|TOK:THB|Pegasus|||PegasusToken2|
@@ -1356,5 +1366,42 @@
|Generate|TOK:THB|Spider|||SpiderToken|
|Generate|TOK:THB|Wolf|||WolfToken|
|Generate|TOK:THB|Nightmare|||AshiokNightmareMuseToken|
-|Generate|TOK:THB|GoldToken|||Gold|
-|Generate|TOK:THB|ArtifactWallToken|||Wall|
\ No newline at end of file
+|Generate|TOK:THB|Gold|||GoldToken|
+|Generate|TOK:THB|Wall|||ArtifactWallToken|
+
+# IKO
+|Generate|TOK:IKO|Beast|||BeastToken|
+|Generate|TOK:IKO|Cat Bird|||CatBirdToken|
+|Generate|TOK:IKO|Cat|||CatToken2|
+|Generate|TOK:IKO|Dinosaur Beast|||DinosaurBeastToken|
+|Generate|TOK:IKO|Dinosaur|||DinosaurHasteToken|
+|Generate|TOK:IKO|Feather|||FeatherToken|
+|Generate|TOK:IKO|Human Soldier|1||HumanSoldierToken|
+|Generate|TOK:IKO|Human Soldier|2||HumanSoldierToken|
+|Generate|TOK:IKO|Human Soldier|3||HumanSoldierToken|
+|Generate|TOK:IKO|Kraken|||KrakenToken|
+|Generate|TOK:IKO|Shark|||SharkToken|
+
+# C20
+|Generate|TOK:C20|Angel|||AngelToken|
+|Generate|TOK:C20|Beast|||BeastToken2|
+|Generate|TOK:C20|Bird|||BirdToken|
+|Generate|TOK:C20|Bird Illusion|||BirdIllusionToken|
+|Generate|TOK:C20|Dinosaur Cat|||DinosaurCatToken|
+|Generate|TOK:C20|Drake|||DrakeToken|
+|Generate|TOK:C20|Elemental|1||ElementalTokenWithHaste|
+|Generate|TOK:C20|Elemental|2||WhiteElementalToken|
+|Generate|TOK:C20|Goblin Warrior|||GoblinWarriorToken|
+|Generate|TOK:C20|Human|||HumanToken|
+|Generate|TOK:C20|Hydra|||ZaxaraTheExemplaryHydraToken|
+|Generate|TOK:C20|Insect|1||HornetQueenInsectToken|
+|Generate|TOK:C20|Insect|2||TheLocustGodInsectToken|
+|Generate|TOK:C20|Saproling|||SaprolingToken|
+|Generate|TOK:C20|Snake|||SnakeToken|
+|Generate|TOK:C20|Soldier|||SoldierToken|
+|Generate|TOK:C20|Spirit|||SpiritWhiteToken|
+|Generate|TOK:C20|Treasure|||TreasureToken|
+|Generate|TOK:C20|Zombie|||ZombieToken|
+
+# JMP
+|Generate|TOK:JMP|Unicorn|||UnicornToken|
\ No newline at end of file
diff --git a/Mage.Common/pom.xml b/Mage.Common/pom.xml
index 79575ccf255..23a14eed639 100644
--- a/Mage.Common/pom.xml
+++ b/Mage.Common/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-root
- 1.4.42
+ 1.4.43
mage-common
diff --git a/Mage.Common/src/main/java/mage/interfaces/MageServer.java b/Mage.Common/src/main/java/mage/interfaces/MageServer.java
index 52c95550c58..059f21ce63e 100644
--- a/Mage.Common/src/main/java/mage/interfaces/MageServer.java
+++ b/Mage.Common/src/main/java/mage/interfaces/MageServer.java
@@ -16,7 +16,6 @@ import mage.utils.MageVersion;
import mage.view.*;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@@ -84,7 +83,7 @@ public interface MageServer {
boolean isTableOwner(String sessionId, UUID roomId, UUID tableId) throws MageException;
- Optional getTable(UUID roomId, UUID tableId) throws MageException;
+ TableView getTable(UUID roomId, UUID tableId) throws MageException;
List getTables(UUID roomId) throws MageException;
@@ -95,13 +94,13 @@ public interface MageServer {
void leaveChat(UUID chatId, String sessionId) throws MageException;
- Optional getTableChatId(UUID tableId) throws MageException;
+ UUID getTableChatId(UUID tableId) throws MageException;
- Optional getGameChatId(UUID gameId) throws MageException;
+ UUID getGameChatId(UUID gameId) throws MageException;
- Optional getRoomChatId(UUID roomId) throws MageException;
+ UUID getRoomChatId(UUID roomId) throws MageException;
- Optional getTournamentChatId(UUID tournamentId) throws MageException;
+ UUID getTournamentChatId(UUID tournamentId) throws MageException;
//room methods
UUID getMainRoomId() throws MageException;
diff --git a/Mage.Common/src/main/java/mage/remote/Connection.java b/Mage.Common/src/main/java/mage/remote/Connection.java
index ecc7dd44166..f3bf4296ee0 100644
--- a/Mage.Common/src/main/java/mage/remote/Connection.java
+++ b/Mage.Common/src/main/java/mage/remote/Connection.java
@@ -42,6 +42,7 @@ public class Connection {
// private UserSkipPrioritySteps userSkipPrioritySteps;
private static final String serialization = "?serializationtype=jboss";
private static final String transport = "bisocket";
+ private static final String threadpool = "onewayThreadPool=mage.remote.CustomThreadPool";
private final String parameter;
@@ -78,13 +79,13 @@ public class Connection {
try {
InetAddress inet = getLocalAddress();
if (inet != null) {
- return transport + "://" + inet.getHostAddress() + ':' + port + '/' + serialization + parameter;
+ return transport + "://" + inet.getHostAddress() + ':' + port + '/' + serialization + "&" + threadpool + parameter;
}
} catch (SocketException ex) {
// just use localhost if can't find local ip
}
}
- return transport + "://" + host + ':' + port + '/' + serialization + parameter;
+ return transport + "://" + host + ':' + port + '/' + serialization + "&" + threadpool + parameter;
}
public ProxyType getProxyType() {
diff --git a/Mage.Common/src/main/java/mage/remote/CustomThreadPool.java b/Mage.Common/src/main/java/mage/remote/CustomThreadPool.java
new file mode 100644
index 00000000000..456f47bcd7d
--- /dev/null
+++ b/Mage.Common/src/main/java/mage/remote/CustomThreadPool.java
@@ -0,0 +1,32 @@
+package mage.remote;
+
+import java.lang.reflect.Field;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.apache.log4j.Logger;
+import org.jboss.util.threadpool.BasicThreadPool;
+
+public class CustomThreadPool extends BasicThreadPool {
+ private static final Logger logger = Logger.getLogger(SessionImpl.class);
+
+ @Override
+ public void setMaximumPoolSize(int size) {
+ /*
+ * I really don't want to implement a whole new threadpool
+ * just to fix this and the executor is private
+ */
+ try {
+ Field executorField = BasicThreadPool.class.getField("executor");
+ executorField.setAccessible(true);
+ ThreadPoolExecutor executor = (ThreadPoolExecutor) executorField.get(this);
+ synchronized (executor) {
+ executor.setMaximumPoolSize(size);
+ executor.setCorePoolSize(size);
+ }
+ } catch (NoSuchFieldException | SecurityException e) {
+ logger.error("Failed to get field executor from BasicThreadPool", e);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ logger.error("Failed to get executor object from BasicThreadPool", e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mage.Common/src/main/java/mage/remote/SessionImpl.java b/Mage.Common/src/main/java/mage/remote/SessionImpl.java
index dd073af9a99..861ad752ec9 100644
--- a/Mage.Common/src/main/java/mage/remote/SessionImpl.java
+++ b/Mage.Common/src/main/java/mage/remote/SessionImpl.java
@@ -647,7 +647,7 @@ public class SessionImpl implements Session {
public Optional getRoomChatId(UUID roomId) {
try {
if (isConnected()) {
- return server.getRoomChatId(roomId);
+ return Optional.of(server.getRoomChatId(roomId));
}
} catch (MageException ex) {
handleMageException(ex);
@@ -659,7 +659,7 @@ public class SessionImpl implements Session {
public Optional getTableChatId(UUID tableId) {
try {
if (isConnected()) {
- return server.getTableChatId(tableId);
+ return Optional.of(server.getTableChatId(tableId));
}
} catch (MageException ex) {
handleMageException(ex);
@@ -671,7 +671,7 @@ public class SessionImpl implements Session {
public Optional getGameChatId(UUID gameId) {
try {
if (isConnected()) {
- return server.getGameChatId(gameId);
+ return Optional.of(server.getGameChatId(gameId));
}
} catch (MageException ex) {
handleMageException(ex);
@@ -685,7 +685,7 @@ public class SessionImpl implements Session {
public Optional getTable(UUID roomId, UUID tableId) {
try {
if (isConnected()) {
- return server.getTable(roomId, tableId);
+ return Optional.of(server.getTable(roomId, tableId));
}
} catch (MageException ex) {
handleMageException(ex);
@@ -829,7 +829,7 @@ public class SessionImpl implements Session {
public Optional getTournamentChatId(UUID tournamentId) {
try {
if (isConnected()) {
- return server.getTournamentChatId(tournamentId);
+ return Optional.of(server.getTournamentChatId(tournamentId));
}
} catch (MageException ex) {
handleMageException(ex);
diff --git a/Mage.Common/src/main/java/mage/utils/MageVersion.java b/Mage.Common/src/main/java/mage/utils/MageVersion.java
index 6aebdad1fb6..a2322ca0106 100644
--- a/Mage.Common/src/main/java/mage/utils/MageVersion.java
+++ b/Mage.Common/src/main/java/mage/utils/MageVersion.java
@@ -11,11 +11,11 @@ public class MageVersion implements Serializable, Comparable {
public static final int MAGE_VERSION_MAJOR = 1;
public static final int MAGE_VERSION_MINOR = 4;
- public static final int MAGE_VERSION_PATCH = 42;
+ public static final int MAGE_VERSION_PATCH = 43;
public static final String MAGE_EDITION_INFO = ""; // set "-beta2" for 1.4.32V1-beta2
- public static final String MAGE_VERSION_MINOR_PATCH = "V7"; // default
+ public static final String MAGE_VERSION_MINOR_PATCH = "V0"; // default
// strict mode
- private static final boolean MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME = true; // set true on uncompatible github changes, set false after new major release (after MAGE_VERSION_PATCH changes)
+ private static final boolean MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME = false; // set true on uncompatible github changes, set false after new major release (after MAGE_VERSION_PATCH changes)
public static final boolean MAGE_VERSION_SHOW_BUILD_TIME = true;
private final int major;
diff --git a/Mage.Common/src/main/java/mage/view/AbilityPickerView.java b/Mage.Common/src/main/java/mage/view/AbilityPickerView.java
index 8ea265aee03..d4ae6a0c231 100644
--- a/Mage.Common/src/main/java/mage/view/AbilityPickerView.java
+++ b/Mage.Common/src/main/java/mage/view/AbilityPickerView.java
@@ -1,6 +1,7 @@
package mage.view;
import mage.abilities.Ability;
+import mage.abilities.SpellAbility;
import java.io.Serializable;
import java.util.LinkedHashMap;
@@ -28,15 +29,32 @@ public class AbilityPickerView implements Serializable {
if (objectName == null) {
rule = ability.getRule(true);
} else {
- rule = ability.getRule(objectName);
- if (rule.isEmpty()) {
- rule = ability.toString();
+ // spell abilities must start with "Cast name" (split cards have different names for each spell part)
+ if (ability instanceof SpellAbility) {
+ SpellAbility spell = (SpellAbility) ability;
+ rule = getAbilityRules(spell, spell.getCardName());
+ if (!rule.startsWith("Cast ")) {
+ rule = spell.toString() + ": " + rule; // spell.toString() must return this.name (example: Cast Armed)
+ }
+ } else {
+ rule = getAbilityRules(ability, objectName);
}
}
choices.put(ability.getId(), num + ". " + rule);
}
}
+ private String getAbilityRules(Ability ability, String objectName) {
+ String rule = ability.getRule(objectName);
+ if (rule.isEmpty()) {
+ rule = ability.toString();
+ }
+ if (!rule.isEmpty()) {
+ rule = Character.toUpperCase(rule.charAt(0)) + rule.substring(1);
+ }
+ return rule;
+ }
+
public AbilityPickerView(Map modes, String message) {
this.choices = modes;
this.message = message;
diff --git a/Mage.Common/src/main/java/mage/view/AbilityView.java b/Mage.Common/src/main/java/mage/view/AbilityView.java
index 77e767d7afd..e01a7d54047 100644
--- a/Mage.Common/src/main/java/mage/view/AbilityView.java
+++ b/Mage.Common/src/main/java/mage/view/AbilityView.java
@@ -1,14 +1,13 @@
package mage.view;
+import java.util.ArrayList;
+import java.util.EnumSet;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.constants.CardType;
import mage.constants.SuperType;
import mage.util.SubTypeList;
-import java.util.ArrayList;
-import java.util.EnumSet;
-
/**
* @author BetaSteward_at_googlemail.com
*/
@@ -29,7 +28,7 @@ public class AbilityView extends CardView {
this.power = "";
this.toughness = "";
this.loyalty = "";
- this.cardTypes = EnumSet.noneOf(CardType.class);
+ this.cardTypes = new ArrayList();
this.subTypes = new SubTypeList();
this.superTypes = EnumSet.noneOf(SuperType.class);
this.color = new ObjectColor();
@@ -45,5 +44,4 @@ public class AbilityView extends CardView {
this.name = name;
}
-
}
diff --git a/Mage.Common/src/main/java/mage/view/CardView.java b/Mage.Common/src/main/java/mage/view/CardView.java
index 5dc0de29e32..4b71867d570 100644
--- a/Mage.Common/src/main/java/mage/view/CardView.java
+++ b/Mage.Common/src/main/java/mage/view/CardView.java
@@ -1,6 +1,8 @@
package mage.view;
import com.google.gson.annotations.Expose;
+import java.util.*;
+import java.util.stream.Collectors;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Abilities;
@@ -29,9 +31,6 @@ import mage.target.Targets;
import mage.util.CardUtil;
import mage.util.SubTypeList;
-import java.util.*;
-import java.util.stream.Collectors;
-
/**
* @author BetaSteward_at_googlemail.com
*/
@@ -55,7 +54,7 @@ public class CardView extends SimpleCardView {
@Expose
protected String loyalty = "";
protected String startingLoyalty;
- protected Set cardTypes;
+ protected ArrayList cardTypes;
protected SubTypeList subTypes;
protected Set superTypes;
protected ObjectColor color;
@@ -151,7 +150,7 @@ public class CardView extends SimpleCardView {
this.toughness = cardView.toughness;
this.loyalty = cardView.loyalty;
this.startingLoyalty = cardView.startingLoyalty;
- this.cardTypes = new HashSet<>(cardView.cardTypes);
+ this.cardTypes = new ArrayList<>(cardView.cardTypes);
this.subTypes = new SubTypeList(cardView.subTypes);
this.superTypes = cardView.superTypes;
@@ -213,8 +212,8 @@ public class CardView extends SimpleCardView {
* @param card
* @param game
* @param controlled is the card view created for the card controller - used
- * for morph / face down cards to know which player may see information for
- * the card
+ * for morph / face down cards to know which player may see information for
+ * the card
*/
public CardView(Card card, Game game, boolean controlled) {
this(card, game, controlled, false, false);
@@ -240,12 +239,12 @@ public class CardView extends SimpleCardView {
/**
* @param card
* @param game
- * @param controlled is the card view created for the card controller - used
- * for morph / face down cards to know which player may see information for
- * the card
+ * @param controlled is the card view created for the card controller - used
+ * for morph / face down cards to know which player may see information for
+ * the card
* @param showFaceDownCard if true and the card is not on the battlefield,
- * also a face down card is shown in the view, face down cards will be shown
- * @param storeZone if true the card zone will be set in the zone attribute.
+ * also a face down card is shown in the view, face down cards will be shown
+ * @param storeZone if true the card zone will be set in the zone attribute.
*/
public CardView(Card card, Game game, boolean controlled, boolean showFaceDownCard, boolean storeZone) {
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), card.getTokenSetCode(), game != null, card.getTokenDescriptor());
@@ -318,13 +317,6 @@ public class CardView extends SimpleCardView {
}
}
- AdventureCard adventureCard = null;
- AdventureCardSpell adventureCardSpell = null;
- if (card instanceof AdventureCard) {
- adventureCard = (AdventureCard) card;
- adventureCardSpell = (AdventureCardSpell) adventureCard.getSpellCard();
- }
-
String fullCardName;
if (splitCard != null) {
this.isSplitCard = true;
@@ -340,7 +332,9 @@ public class CardView extends SimpleCardView {
fullCardName = card.getName(); // split card contains full name as normal
this.manaCostLeft = splitCard.getLeftHalfCard().getManaCost().getSymbols();
this.manaCostRight = splitCard.getRightHalfCard().getManaCost().getSymbols();
- } else if (adventureCard != null) {
+ } else if (card instanceof AdventureCard) {
+ AdventureCard adventureCard = ((AdventureCard) card);
+ AdventureCardSpell adventureCardSpell = ((AdventureCardSpell) adventureCard.getSpellCard());
fullCardName = adventureCard.getName() + MockCard.ADVENTURE_NAME_SEPARATOR + adventureCardSpell.getName();
this.manaCostLeft = adventureCardSpell.getManaCost().getSymbols();
this.manaCostRight = adventureCard.getManaCost().getSymbols();
@@ -467,7 +461,7 @@ public class CardView extends SimpleCardView {
} else if (spell.getCard() != null) {
SplitCard wholeCard = ((SplitCardHalf) spell.getCard()).getParentCard();
Abilities aftermathHalfAbilities = wholeCard.getRightHalfCard().getAbilities(game);
- if (aftermathHalfAbilities.stream().anyMatch(ability -> ability instanceof AftermathAbility)) {
+ if (aftermathHalfAbilities.stream().anyMatch(halfAbility -> halfAbility instanceof AftermathAbility)) {
if (ty == SpellAbilityType.SPLIT_RIGHT) {
artRect = ArtRect.AFTERMATH_BOTTOM;
} else {
@@ -636,7 +630,7 @@ public class CardView extends SimpleCardView {
this.toughness = "";
this.loyalty = "";
this.startingLoyalty = "";
- this.cardTypes = EnumSet.noneOf(CardType.class);
+ this.cardTypes = new ArrayList<>();
this.subTypes = new SubTypeList();
this.superTypes = EnumSet.noneOf(SuperType.class);
this.color = new ObjectColor();
@@ -764,7 +758,7 @@ public class CardView extends SimpleCardView {
return startingLoyalty;
}
- public Set getCardTypes() {
+ public ArrayList getCardTypes() {
return cardTypes;
}
@@ -1030,26 +1024,25 @@ public class CardView extends SimpleCardView {
}
public String getColorText() {
-
- String color = getColor().getDescription();
- return color.substring(0, 1).toUpperCase(Locale.ENGLISH) + color.substring(1);
+ String colorText = getColor().getDescription();
+ return colorText.substring(0, 1).toUpperCase(Locale.ENGLISH) + colorText.substring(1);
}
public String getTypeText() {
- StringBuilder type = new StringBuilder();
+ StringBuilder typeText = new StringBuilder();
if (!getSuperTypes().isEmpty()) {
- type.append(String.join(" ", getSuperTypes().stream().map(SuperType::toString).collect(Collectors.toList())));
- type.append(" ");
+ typeText.append(String.join(" ", getSuperTypes().stream().map(SuperType::toString).collect(Collectors.toList())));
+ typeText.append(" ");
}
if (!getCardTypes().isEmpty()) {
- type.append(String.join(" ", getCardTypes().stream().map(CardType::toString).collect(Collectors.toList())));
- type.append(" ");
+ typeText.append(String.join(" ", getCardTypes().stream().map(CardType::toString).collect(Collectors.toList())));
+ typeText.append(" ");
}
if (!getSubTypes().isEmpty()) {
- type.append(" - ");
- type.append(String.join(" ", getSubTypes().stream().map(SubType::toString).collect(Collectors.toList())));
+ typeText.append(" - ");
+ typeText.append(String.join(" ", getSubTypes().stream().map(SubType::toString).collect(Collectors.toList())));
}
- return type.toString();
+ return typeText.toString();
}
public boolean isLand() {
diff --git a/Mage.Common/src/main/java/mage/view/PermanentView.java b/Mage.Common/src/main/java/mage/view/PermanentView.java
index 840011f45c1..312e1c9e8f2 100644
--- a/Mage.Common/src/main/java/mage/view/PermanentView.java
+++ b/Mage.Common/src/main/java/mage/view/PermanentView.java
@@ -95,10 +95,9 @@ public class PermanentView extends CardView {
if (controlled) {
// must be a morphed or manifested card
for (Ability permanentAbility : permanent.getAbilities()) {
- if (permanentAbility instanceof TurnFaceUpAbility && !permanentAbility.getRuleVisible()) {
- this.rules.add(permanentAbility.getRule(true));
- }
if (permanentAbility.getWorksFaceDown()) {
+ this.rules.add(permanentAbility.getRule(true));
+ } else if (permanentAbility instanceof TurnFaceUpAbility && !permanentAbility.getRuleVisible()) {
this.rules.add(permanentAbility.getRule());
}
}
diff --git a/Mage.Common/src/main/java/mage/view/TournamentTypeView.java b/Mage.Common/src/main/java/mage/view/TournamentTypeView.java
index 8bd4d8c3ccb..22d7ecf9bca 100644
--- a/Mage.Common/src/main/java/mage/view/TournamentTypeView.java
+++ b/Mage.Common/src/main/java/mage/view/TournamentTypeView.java
@@ -22,6 +22,7 @@ public class TournamentTypeView implements Serializable {
private final boolean elimination;
private final boolean random;
private final boolean richMan;
+ private final boolean jumpstart;
public TournamentTypeView(TournamentType tournamentType) {
this.name = tournamentType.getName();
@@ -34,6 +35,7 @@ public class TournamentTypeView implements Serializable {
this.elimination = tournamentType.isElimination();
this.random = tournamentType.isRandom();
this.richMan = tournamentType.isRichMan();
+ this.jumpstart = tournamentType.isJumpstart();
}
@Override
@@ -80,4 +82,9 @@ public class TournamentTypeView implements Serializable {
public boolean isRichMan() {
return richMan;
}
+
+ public boolean isJumpstart() {
+ return jumpstart;
+ }
+
}
diff --git a/Mage.Plugins/Mage.Counter.Plugin/pom.xml b/Mage.Plugins/Mage.Counter.Plugin/pom.xml
index 813af4df7e2..cc8dfb00754 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.42
+ 1.4.43
mage-counter-plugin
diff --git a/Mage.Plugins/pom.xml b/Mage.Plugins/pom.xml
index 7ec674a8625..41f63af7984 100644
--- a/Mage.Plugins/pom.xml
+++ b/Mage.Plugins/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-root
- 1.4.42
+ 1.4.43
mage-plugins
diff --git a/Mage.Server.Console/pom.xml b/Mage.Server.Console/pom.xml
index 4102763af4a..0861e001161 100644
--- a/Mage.Server.Console/pom.xml
+++ b/Mage.Server.Console/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-root
- 1.4.42
+ 1.4.43
mage.server.console
diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.java b/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.java
index df46fb279ee..4ed3d543a17 100644
--- a/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.java
+++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsoleFrame.java
@@ -60,7 +60,7 @@ public class ConsoleFrame extends javax.swing.JFrame implements MageClient {
initComponents();
try {
- UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
+ UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
session = new SessionImpl(this);
connectDialog = new ConnectDialog();
} catch (Exception ex) {
diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Deck.Constructed/pom.xml
index 05f4f1e9bee..aade95e9b61 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.42
+ 1.4.43
mage-deck-constructed
diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Brawl.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Brawl.java
index e656b53d870..2fd9250d66e 100644
--- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Brawl.java
+++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Brawl.java
@@ -25,9 +25,11 @@ public class Brawl extends Constructed {
setCodes.addAll(Standard.makeLegalSets());
banned.add("Golos, Tireless Pilgrim");
+ banned.add("Drannith Magistrate");
banned.add("Lutri, the Spellchaser");
banned.add("Oko, Thief of Crowns");
banned.add("Sorcerous Spyglass");
+ banned.add("Winota, Joiner of Forces");
}
public Brawl(String name) {
diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java
index 53b287527f7..0cb9b35241d 100644
--- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java
+++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/DuelCommander.java
@@ -13,24 +13,31 @@ public class DuelCommander extends Commander {
banned.add("Ancient Tomb");
banned.add("Back to Basics");
banned.add("Black Lotus");
+ banned.add("Capture of Jingzhou");
+ banned.add("Cavern of Souls");
banned.add("Channel");
banned.add("Chrome Mox");
+ banned.add("Deflecting Swat");
banned.add("Dig Through Time");
banned.add("Eidolon of the Great Revel");
banned.add("Emrakul, the Aeons Torn");
banned.add("Entomb");
banned.add("Fastbond");
+ banned.add("Field of the Dead");
+ banned.add("Fierce Guardianship");
banned.add("Fireblast");
banned.add("Food Chain");
banned.add("Gaea's Cradle");
- banned.add("Gifts Ungiven");
banned.add("Grim Monolith");
banned.add("Hermit Druid");
+ banned.add("High Tide");
banned.add("Humility");
banned.add("Imperial Seal");
banned.add("Karakas");
banned.add("Library of Alexandria");
+ banned.add("Lion's Eye Diamond");
banned.add("Loyal Retainers");
+ banned.add("Lutri, the Spellchaser");
banned.add("Mana Crypt");
banned.add("Mana Drain");
banned.add("Mana Vault");
@@ -53,15 +60,18 @@ public class DuelCommander extends Commander {
banned.add("Sensei's Divining Top");
banned.add("Sol Ring");
banned.add("Strip Mine");
+ banned.add("Temporal Manipulation");
banned.add("Thassa's Oracle");
banned.add("The Tabernacle at Pendrell Vale");
banned.add("Time Vault");
banned.add("Time Walk");
banned.add("Timetwister");
+ banned.add("Time Warp");
banned.add("Tinker");
banned.add("Tolarian Academy");
banned.add("Treasure Cruise");
banned.add("Vampiric Tutor");
+ banned.add("Wasteland");
bannedCommander.add("Arahbo, Roar of the World");
bannedCommander.add("Baral, Chief of Compliance");
@@ -72,7 +82,6 @@ public class DuelCommander extends Commander {
bannedCommander.add("Edric, Spymaster of Trest");
bannedCommander.add("Emry, Lurker of the Loch");
bannedCommander.add("Geist of Saint Traft");
- bannedCommander.add("Jace, Vryn's Prodigy");
bannedCommander.add("Marath, Will of the Wild");
bannedCommander.add("Najeela, the Blade-Blossom");
bannedCommander.add("Oloro, Ageless Ascetic");
diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java
index 47abc0531b2..d297bdfb8e6 100644
--- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java
+++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Legacy.java
@@ -49,6 +49,7 @@ public class Legacy extends Constructed {
banned.add("Iterative Analysis");
banned.add("Jeweled Bird");
banned.add("Library of Alexandria");
+ banned.add("Lurrus of the Dream-Den");
banned.add("Mana Crypt");
banned.add("Mana Drain");
banned.add("Mana Vault");
@@ -94,6 +95,6 @@ public class Legacy extends Constructed {
banned.add("Wrenn and Six");
banned.add("Yawgmoth's Bargain");
banned.add("Yawgmoth's Will");
-
+ banned.add("Zirda, the Dawnwaker");
}
}
diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java
index 86cc46d2b22..8316e2de021 100644
--- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java
+++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java
@@ -17,7 +17,9 @@ public class Standard extends Constructed {
setCodes.addAll(makeLegalSets());
+ banned.add("Agent of Treachery");
banned.add("Field of the Dead");
+ banned.add("Fires of Invention");
banned.add("Oko, Thief of Crowns");
banned.add("Once Upon a Time");
banned.add("Veil of Summer");
diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java
index a01a05ced37..a6cacdf8559 100644
--- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java
+++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java
@@ -30,6 +30,7 @@ public class Vintage extends Constructed {
banned.add("Immediate Action");
banned.add("Iterative Analysis");
banned.add("Jeweled Bird");
+ banned.add("Lurrus of the Dream-Den");
banned.add("Muzzio's Preparations");
banned.add("Power Play");
banned.add("Rebirth");
diff --git a/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml b/Mage.Server.Plugins/Mage.Deck.Limited/pom.xml
index 2c925c27b62..f9dd5c88774 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.42
+ 1.4.43
mage-deck-limited
diff --git a/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml
index 7c67eda5fcc..84886ebf373 100644
--- a/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.BrawlDuel/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-brawlduel
diff --git a/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml
index 82682897fb1..18e0a90e946 100644
--- a/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-brawlfreeforall
diff --git a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml
index 374960f5672..4659a5482cd 100644
--- a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-canadianhighlanderduel
diff --git a/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderDuel/pom.xml
index cc12a371a1a..2afdd233c17 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.42
+ 1.4.43
mage-game-commanderduel
diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/pom.xml
index d7433f0e552..1f1e952ee95 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.42
+ 1.4.43
mage-game-commanderfreeforall
diff --git a/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeForAll/pom.xml
index c515dde4d96..0dc77912dce 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.42
+ 1.4.43
mage-game-freeforall
diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/pom.xml
index 8e37dc51154..b6aee93e90d 100644
--- a/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-freeformcommanderduel
diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml
index d2fd9950d94..ec78b087ef8 100644
--- a/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-freeformcommanderfreeforall
diff --git a/Mage.Server.Plugins/Mage.Game.FreeformUnlimitedCommander/pom.xml b/Mage.Server.Plugins/Mage.Game.FreeformUnlimitedCommander/pom.xml
index 249c124fa26..d9994d430ae 100644
--- a/Mage.Server.Plugins/Mage.Game.FreeformUnlimitedCommander/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.FreeformUnlimitedCommander/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-freeformunlimitedcommander
@@ -23,7 +23,7 @@
org.mage
mage-game-freeformcommanderfreeforall
- 1.4.42
+ 1.4.43
compile
diff --git a/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml
index f82f22af9d0..2d77de5a0c7 100644
--- a/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.MomirDuel/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-momirduel
diff --git a/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml b/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml
index 845d6409905..e5badb6ddd5 100644
--- a/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.MomirGame/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-momirfreeforall
diff --git a/Mage.Server.Plugins/Mage.Game.OathbreakerDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.OathbreakerDuel/pom.xml
index 269f85d71b1..24e0fe00b04 100644
--- a/Mage.Server.Plugins/Mage.Game.OathbreakerDuel/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.OathbreakerDuel/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-oathbreakerduel
@@ -22,7 +22,7 @@
org.mage
mage-game-oathbreakerfreeforall
- 1.4.42
+ 1.4.43
compile
diff --git a/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/pom.xml
index 30bcec9cba9..73bbd699bfd 100644
--- a/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-oathbreakerfreeforall
diff --git a/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/src/mage/game/OathbreakerFreeForAll.java b/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/src/mage/game/OathbreakerFreeForAll.java
index 90f673c200e..9c517d03610 100644
--- a/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/src/mage/game/OathbreakerFreeForAll.java
+++ b/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/src/mage/game/OathbreakerFreeForAll.java
@@ -25,8 +25,8 @@ import java.util.*;
public class OathbreakerFreeForAll extends GameCommanderImpl {
private int numPlayers;
- private Map> playerSignatureSpells = new HashMap<>();
- private Map> playerOathbreakers = new HashMap<>();
+ private final Map> playerSignatureSpells = new HashMap<>();
+ private final Map> playerOathbreakers = new HashMap<>();
private static final String COMMANDER_NAME_OATHBREAKER = "Oathbreaker";
private static final String COMMANDER_NAME_SIGNATURE_SPELL = "Signature Spell";
@@ -122,19 +122,19 @@ public class OathbreakerFreeForAll extends GameCommanderImpl {
if (player != null) {
Set commanders = this.playerOathbreakers.getOrDefault(player.getId(), new HashSet<>());
Set spells = this.playerSignatureSpells.getOrDefault(player.getId(), new HashSet<>());
- for (UUID id : player.getCommandersIds()) {
+ for (UUID commanderId : super.getCommandersIds(player, commanderCardType)) {
switch (commanderCardType) {
case ANY:
- res.add(id);
+ res.add(commanderId);
break;
case COMMANDER_OR_OATHBREAKER:
- if (commanders.contains(id)) {
- res.add(id);
+ if (commanders.contains(commanderId)) {
+ res.add(commanderId);
}
break;
case SIGNATURE_SPELL:
- if (spells.contains(id)) {
- res.add(id);
+ if (spells.contains(commanderId)) {
+ res.add(commanderId);
}
break;
default:
diff --git a/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml b/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml
index 4790c78bea0..de80e55deaf 100644
--- a/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml
+++ b/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-server-plugins
- 1.4.42
+ 1.4.43
mage-game-pennydreadfulcommanderfreeforall
diff --git a/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TinyLeadersDuel/pom.xml
index 1ae9001fe46..81774dffc70 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.42
+ 1.4.43
mage-game-tinyleadersduel
diff --git a/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.TwoPlayerDuel/pom.xml
index c8e14f96873..3a6ed3b173e 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.42
+ 1.4.43
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 b46e30e798a..c2d00d51504 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.42
+ 1.4.43
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 b25b4bbeab1..0c278dc99d5 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.42
+ 1.4.43
mage-player-ai-ma
diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java
index 54ac89b928e..771dc4afcd1 100644
--- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java
+++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java
@@ -3,6 +3,7 @@ package mage.player.ai;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.AbilityImpl;
+import mage.abilities.ActivatedAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.PassAbility;
import mage.abilities.costs.mana.ManaCost;
@@ -94,9 +95,9 @@ public class SimulatedPlayer2 extends ComputerPlayer {
}
protected void simulateOptions(Game game) {
- List playables = game.getPlayer(playerId).getPlayable(game, isSimulatedPlayer);
+ List playables = game.getPlayer(playerId).getPlayable(game, isSimulatedPlayer);
playables = filterAbilities(game, playables, suggested);
- for (Ability ability : playables) {
+ for (ActivatedAbility ability : playables) {
if (ability.getAbilityType() == AbilityType.MANA) {
continue;
}
@@ -186,15 +187,15 @@ public class SimulatedPlayer2 extends ComputerPlayer {
* @param suggested
* @return
*/
- protected List filterAbilities(Game game, List playables, List suggested) {
+ protected List filterAbilities(Game game, List playables, List suggested) {
if (playables.isEmpty()) {
return playables;
}
if (suggested == null || suggested.isEmpty()) {
return playables;
}
- List filtered = new ArrayList<>();
- for (Ability ability : playables) {
+ List filtered = new ArrayList<>();
+ for (ActivatedAbility ability : playables) {
Card card = game.getCard(ability.getSourceId());
if (card != null) {
for (String s : suggested) {
@@ -212,7 +213,7 @@ public class SimulatedPlayer2 extends ComputerPlayer {
return playables;
}
- protected List filterOptions(Game game, List options, Ability ability, List suggested) {
+ protected List filterOptions(Game game, List options, ActivatedAbility ability, List suggested) {
if (options.isEmpty()) {
return options;
}
diff --git a/Mage.Server.Plugins/Mage.Player.AI/pom.xml b/Mage.Server.Plugins/Mage.Player.AI/pom.xml
index aa2e2c2d44a..1a32f8a06b0 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.42
+ 1.4.43
mage-player-ai
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 d1c17c24666..e097b62393c 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
@@ -396,12 +396,16 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
- while ((outcome.isGood() ? target.getTargets().size() < target.getMaxNumberOfTargets() : !target.isChosen())
+ // exile cost workaround: exile is bad, but exile from graveyard in most cases is good (more exiled -- more good things you get, e.g. delve's pay)
+ boolean isRealGood = outcome.isGood() || outcome == Outcome.Exile;
+ while ((isRealGood ? target.getTargets().size() < target.getMaxNumberOfTargets() : !target.isChosen())
&& !cards.isEmpty()) {
Card pick = pickTarget(abilityControllerId, cards, outcome, target, null, game);
if (pick != null) {
target.addTarget(pick.getId(), null, game);
cards.remove(pick);
+ } else {
+ break;
}
}
@@ -1267,7 +1271,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//play a land that will allow us to play an unplayable
for (Mana mana : unplayable.keySet()) {
for (Card card : lands) {
- for (ActivatedManaAbilityImpl ability : card.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD)) {
+ for (ActivatedManaAbilityImpl ability : card.getAbilities(game).getActivatedManaAbilities(Zone.BATTLEFIELD)) {
for (Mana netMana : ability.getNetMana(game)) {
if (netMana.enough(mana)) {
this.playLand(card, game, false);
@@ -1281,7 +1285,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
//play a land that will get us closer to playing an unplayable
for (Mana mana : unplayable.keySet()) {
for (Card card : lands) {
- for (ActivatedManaAbilityImpl ability : card.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD)) {
+ for (ActivatedManaAbilityImpl ability : card.getAbilities(game).getActivatedManaAbilities(Zone.BATTLEFIELD)) {
for (Mana netMana : ability.getNetMana(game)) {
if (mana.contains(netMana)) {
this.playLand(card, game, false);
@@ -1321,7 +1325,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
if (ability != null && ability.canActivate(playerId, game).canActivate()
&& !game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getSourceId(), ability.getSourceId(), playerId), ability, game, true)) {
if (card.getCardType().contains(CardType.INSTANT)
- || card.hasAbility(FlashAbility.getInstance().getId(), game)) {
+ || card.hasAbility(FlashAbility.getInstance(), game)) {
playableInstant.add(card);
} else {
playableNonInstant.add(card);
@@ -1362,7 +1366,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
for (Card card : graveyard.getCards(game)) {
- for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.GRAVEYARD)) {
+ for (ActivatedAbility ability : card.getAbilities(game).getActivatedAbilities(Zone.GRAVEYARD)) {
if (ability.canActivate(playerId, game).canActivate()) {
ManaOptions abilityOptions = ability.getManaCosts().getOptions();
if (abilityOptions.isEmpty()) {
@@ -1529,10 +1533,34 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
}
}
+
// pay phyrexian life costs
if (cost instanceof PhyrexianManaCost) {
return cost.pay(null, game, null, playerId, false, null) || permittingObject != null;
}
+
+ // pay special mana like convoke cost (tap for pay)
+ // GUI: user see "special" button while pay spell's cost
+ // TODO: AI can't prioritize special mana types to pay, e.g. it will use first available
+ SpecialAction specialAction = game.getState().getSpecialActions().getControlledBy(this.getId(), true)
+ .values().stream().findFirst().orElse(null);
+ ManaOptions specialMana = specialAction == null ? null : specialAction.getManaOptions(ability, game, unpaid);
+ if (specialMana != null) {
+ for (Mana netMana : specialMana) {
+ if (cost.testPay(netMana) || permittingObject != null) {
+ if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) {
+ continue;
+ }
+ specialAction.setUnpaidMana(unpaid);
+ if (activateAbility(specialAction, game)) {
+ return true;
+ }
+ // only one time try to pay
+ break;
+ }
+ }
+ }
+
return false;
}
@@ -1895,27 +1923,6 @@ public class ComputerPlayer extends PlayerImpl implements Player {
return 0;
}
- @Override
- public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
- switch (ability.getSpellAbilityType()) {
- case SPLIT:
- case SPLIT_FUSED:
- case SPLIT_AFTERMATH:
- MageObject object = game.getObject(ability.getSourceId());
- if (object != null) {
- LinkedHashMap useableAbilities = getSpellAbilities(playerId, object, game.getState().getZone(object.getId()), game);
- if (useableAbilities != null && !useableAbilities.isEmpty()) {
- // game.fireGetChoiceEvent(playerId, name, object, new ArrayList<>(useableAbilities.values()));
- // TODO: Improve this
- return (SpellAbility) useableAbilities.values().iterator().next();
- }
- }
- return null;
- default:
- return ability;
- }
- }
-
@Override
public Mode chooseMode(Modes modes, Ability source, Game game) {
log.debug("chooseMode");
diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMCTS/pom.xml
index cbaf2a5aad3..c7fccdb2f2a 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.42
+ 1.4.43
mage-player-ai-mcts
diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSPlayer.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSPlayer.java
index 5dedfe41d73..bdd731ffc40 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSPlayer.java
+++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSPlayer.java
@@ -2,6 +2,7 @@
package mage.player.ai;
import mage.abilities.Ability;
+import mage.abilities.ActivatedAbility;
import mage.abilities.SpellAbility;
import mage.abilities.common.PassAbility;
import mage.abilities.costs.mana.GenericManaCost;
@@ -45,16 +46,16 @@ public class MCTSPlayer extends ComputerPlayer {
return new MCTSPlayer(this);
}
- protected List getPlayableAbilities(Game game) {
- List playables = getPlayable(game, true);
+ protected List getPlayableAbilities(Game game) {
+ List playables = getPlayable(game, true);
playables.add(pass);
return playables;
}
public List getPlayableOptions(Game game) {
List all = new ArrayList<>();
- List playables = getPlayableAbilities(game);
- for (Ability ability: playables) {
+ List playables = getPlayableAbilities(game);
+ for (ActivatedAbility ability: playables) {
List options = game.getPlayer(playerId).getPlayableOptions(ability, game);
if (options.isEmpty()) {
if (!ability.getManaCosts().getVariableCosts().isEmpty()) {
diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java
index 0b3c44f268b..957f43e5ac1 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java
+++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java
@@ -73,7 +73,7 @@ public class SimulatedPlayerMCTS extends MCTSPlayer {
}
private Ability getAction(Game game) {
- List playables = getPlayableAbilities(game);
+ List playables = getPlayableAbilities(game);
Ability ability;
while (true) {
if (playables.size() == 1) {
diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml
index 619b2d17ad1..029acd82d34 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.42
+ 1.4.43
mage-player-aiminimax
diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java
index 3bc58353c73..4b141ec80a5 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java
+++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java
@@ -3,6 +3,7 @@
package mage.player.ai;
import mage.abilities.Ability;
+import mage.abilities.ActivatedAbility;
import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.PassAbility;
@@ -59,10 +60,10 @@ public class SimulatedPlayer extends ComputerPlayer {
return list;
}
- protected void simulateOptions(Game game, Ability previousActions) {
+ protected void simulateOptions(Game game, ActivatedAbility previousActions) {
allActions.add(previousActions);
- List playables = game.getPlayer(playerId).getPlayable(game, isSimulatedPlayer);
- for (Ability ability: playables) {
+ List playables = game.getPlayer(playerId).getPlayable(game, isSimulatedPlayer);
+ for (ActivatedAbility ability: playables) {
List options = game.getPlayer(playerId).getPlayableOptions(ability, game);
if (options.isEmpty()) {
if (!ability.getManaCosts().getVariableCosts().isEmpty()) {
diff --git a/Mage.Server.Plugins/Mage.Player.Human/pom.xml b/Mage.Server.Plugins/Mage.Player.Human/pom.xml
index ab624dec8c6..ff5d7e2649c 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.42
+ 1.4.43
mage-player-human
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 bc08e0aa8d0..e38c162e8d6 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
@@ -10,6 +10,7 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.RequirementEffect;
import mage.abilities.hint.HintUtils;
import mage.abilities.mana.ActivatedManaAbilityImpl;
+import mage.abilities.mana.ManaAbility;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.decks.Deck;
@@ -61,6 +62,8 @@ import static mage.constants.PlayerAction.TRIGGER_AUTO_ORDER_RESET_ALL;
*/
public class HumanPlayer extends PlayerImpl {
+ private static final boolean ALLOW_USERS_TO_PUT_NON_PLAYABLE_SPELLS_ON_STACK_WORKAROUND = false; // warning, see workaround's info on usage
+
private transient Boolean responseOpenedForAnswer = false; // can't get response until prepared target (e.g. until send all fire events to all players)
private final transient PlayerResponse response = new PlayerResponse();
@@ -1039,7 +1042,7 @@ public class HumanPlayer extends PlayerImpl {
if (response.getString() != null
&& response.getString().equals("special")) {
- specialAction(game);
+ activateSpecialAction(game, null);
} else if (response.getUUID() != null) {
boolean result = false;
MageObject object = game.getObject(response.getUUID());
@@ -1047,24 +1050,42 @@ public class HumanPlayer extends PlayerImpl {
Zone zone = game.getState().getZone(object.getId());
if (zone != null) {
// look at card or try to cast/activate abilities
+ LinkedHashMap useableAbilities = new LinkedHashMap<>();
+
Player actingPlayer = null;
- LinkedHashMap useableAbilities = null;
if (playerId.equals(game.getPriorityPlayerId())) {
actingPlayer = this;
} else if (getPlayersUnderYourControl().contains(game.getPriorityPlayerId())) {
actingPlayer = game.getPlayer(game.getPriorityPlayerId());
}
if (actingPlayer != null) {
- useableAbilities = actingPlayer.getUseableActivatedAbilities(object, zone, game);
+ useableAbilities = actingPlayer.getPlayableActivatedAbilities(object, zone, game);
+
+ // GUI: workaround to enable users to put spells on stack without real available mana
+ // (without highlighting, like it was in old versions before June 2020)
+ // Reason: some gain ability adds cost modification and other things to spells on stack only,
+ // e.g. xmage can't find playable ability before put that spell on stack (wtf example: Chief Engineer,
+ // see ConvokeTest)
+ // TODO: it's a BAD workaround -- users can't see that card/ability is broken and will not report to us, AI can't play that ability too
+ // Enable it on massive broken cards/abilities only or for manual tests
+ if (ALLOW_USERS_TO_PUT_NON_PLAYABLE_SPELLS_ON_STACK_WORKAROUND) {
+ if (object instanceof Card) {
+ for (Ability ability : ((Card) object).getAbilities(game)) {
+ if (ability instanceof SpellAbility && ((SpellAbility) ability).canActivate(actingPlayer.getId(), game).canActivate()
+ || ability instanceof PlayLandAbility) {
+ useableAbilities.putIfAbsent(ability.getId(), (ActivatedAbility) ability);
+ }
+ }
+ }
+ }
}
if (object instanceof Card
&& ((Card) object).isFaceDown(game)
- && lookAtFaceDownCard((Card) object, game, useableAbilities == null ? 0 : useableAbilities.size())) {
+ && lookAtFaceDownCard((Card) object, game, useableAbilities.size())) {
result = true;
} else {
- if (useableAbilities != null
- && !useableAbilities.isEmpty()) {
+ if (!useableAbilities.isEmpty()) {
activateAbility(useableAbilities, object, game);
result = true;
}
@@ -1221,7 +1242,7 @@ public class HumanPlayer extends PlayerImpl {
} else if (response.getString() != null
&& response.getString().equals("special")) {
if (unpaid instanceof ManaCostsImpl) {
- specialManaAction(unpaid, game);
+ activateSpecialAction(game, unpaid);
}
} else if (response.getManaType() != null) {
// this mana type can be paid once from pool
@@ -1336,19 +1357,30 @@ public class HumanPlayer extends PlayerImpl {
if (object == null) {
return;
}
- if (AbilityType.SPELL.equals(abilityToCast.getAbilityType())) {
+
+ // GUI: for user's information only - check if mana abilities allows to use here (getUseableManaAbilities already filter it)
+ // Reason: when you use special mana ability then normal mana abilities will be restricted to pay. Users
+ // can't see lands as playable and must know the reason (if they click on land then they get that message)
+ if (abilityToCast.getAbilityType() == AbilityType.SPELL) {
Spell spell = game.getStack().getSpell(abilityToCast.getSourceId());
- if (spell != null && !spell.isResolving()
- && spell.isDoneActivatingManaAbilities()) {
- game.informPlayer(this, "You can no longer use activated mana abilities to pay for the current spell. Cancel and recast the spell and activate mana abilities first.");
- return;
+ boolean haveManaAbilities = object.getAbilities().stream().anyMatch(a -> a instanceof ManaAbility);
+ if (spell != null && !spell.isResolving() && haveManaAbilities) {
+ switch (spell.getCurrentActivatingManaAbilitiesStep()) {
+ // if you used special mana ability like convoke then normal mana abilities will be restricted to use, see Convoke for details
+ case BEFORE:
+ case NORMAL:
+ break;
+ case AFTER:
+ game.informPlayer(this, "You can no longer use activated mana abilities to pay for the current spell (special mana pay already used). Cancel and recast the spell to activate mana abilities first.");
+ return;
+ }
}
}
+
Zone zone = game.getState().getZone(object.getId());
if (zone != null) {
LinkedHashMap useableAbilities = getUseableManaAbilities(object, zone, game);
- if (useableAbilities != null
- && !useableAbilities.isEmpty()) {
+ if (!useableAbilities.isEmpty()) {
useableAbilities = ManaUtil.tryToAutoPay(unpaid, useableAbilities); // eliminates other abilities if one fits perfectly
currentlyUnpaidMana = unpaid;
activateAbility(useableAbilities, object, game);
@@ -1845,7 +1877,13 @@ public class HumanPlayer extends PlayerImpl {
draft.firePickCardEvent(playerId);
}
- protected void specialAction(Game game) {
+ /**
+ * Activate special action (normal or mana)
+ *
+ * @param game
+ * @param unpaidForManaAction - set unpaid for mana actions like convoke
+ */
+ protected void activateSpecialAction(Game game, ManaCost unpaidForManaAction) {
if (gameInCheckPlayableState(game)) {
return;
}
@@ -1854,7 +1892,7 @@ public class HumanPlayer extends PlayerImpl {
return;
}
- Map specialActions = game.getState().getSpecialActions().getControlledBy(playerId, false);
+ Map specialActions = game.getState().getSpecialActions().getControlledBy(playerId, unpaidForManaAction != null);
if (!specialActions.isEmpty()) {
updateGameStatePriority("specialAction", game);
@@ -1864,39 +1902,13 @@ public class HumanPlayer extends PlayerImpl {
}
waitForResponse(game);
- if (response.getUUID() != null) {
- if (specialActions.containsKey(response.getUUID())) {
- activateAbility(specialActions.get(response.getUUID()), game);
- }
- }
- }
- }
-
- protected void specialManaAction(ManaCost unpaid, Game game) {
- if (gameInCheckPlayableState(game)) {
- return;
- }
-
- if (!canRespond()) {
- return;
- }
-
- Map specialActions = game.getState().getSpecialActions().getControlledBy(playerId, true);
- if (!specialActions.isEmpty()) {
- updateGameStatePriority("specialAction", game);
- prepareForResponse(game);
- if (!isExecutingMacro()) {
- game.fireGetChoiceEvent(playerId, name, null, new ArrayList<>(specialActions.values()));
- }
- waitForResponse(game);
-
if (response.getUUID() != null) {
if (specialActions.containsKey(response.getUUID())) {
SpecialAction specialAction = specialActions.get(response.getUUID());
- if (specialAction != null) {
- specialAction.setUnpaidMana(unpaid);
- activateAbility(specialActions.get(response.getUUID()), game);
+ if (unpaidForManaAction != null) {
+ specialAction.setUnpaidMana(unpaidForManaAction);
}
+ activateAbility(specialAction, game);
}
}
}
@@ -1973,51 +1985,6 @@ public class HumanPlayer extends PlayerImpl {
return true;
}
- @Override
- public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
- if (gameInCheckPlayableState(game)) {
- return null;
- }
-
- // TODO: add canRespond cycle?
- if (!canRespond()) {
- return null;
- }
-
- switch (ability.getSpellAbilityType()) {
- case SPLIT:
- case SPLIT_FUSED:
- case SPLIT_AFTERMATH:
- MageObject object = game.getObject(ability.getSourceId());
- if (object != null) {
- String message = "Choose ability to cast" + (noMana ? " for FREE" : "") + "
" + object.getLogName();
- LinkedHashMap useableAbilities = getSpellAbilities(playerId, object, game.getState().getZone(object.getId()), game);
- if (useableAbilities != null
- && useableAbilities.size() == 1) {
- return (SpellAbility) useableAbilities.values().iterator().next();
- } else if (useableAbilities != null
- && !useableAbilities.isEmpty()) {
-
- updateGameStatePriority("chooseSpellAbilityForCast", game);
- prepareForResponse(game);
- if (!isExecutingMacro()) {
- game.fireGetChoiceEvent(playerId, message, object, new ArrayList<>(useableAbilities.values()));
- }
- waitForResponse(game);
-
- if (response.getUUID() != null) {
- if (useableAbilities.containsKey(response.getUUID())) {
- return (SpellAbility) useableAbilities.get(response.getUUID());
- }
- }
- }
- }
- return null;
- default:
- return ability;
- }
- }
-
@Override
public SpellAbility chooseAbilityForCast(Card card, Game game, boolean nonMana) {
if (gameInCheckPlayableState(game)) {
@@ -2096,6 +2063,9 @@ public class HumanPlayer extends PlayerImpl {
modeText = "(selected " + timesSelected + "x) " + modeText;
}
}
+ if (!modeText.isEmpty()) {
+ modeText = Character.toUpperCase(modeText.charAt(0)) + modeText.substring(1);
+ }
modeMap.put(mode.getId(), modeIndex + ". " + modeText);
}
}
@@ -2141,13 +2111,14 @@ public class HumanPlayer extends PlayerImpl {
// cancel choice (remove all selections)
if (Modes.CHOOSE_OPTION_CANCEL_ID.equals(response.getUUID())) {
modes.getSelectedModes().clear();
- return null;
}
} else if (canEndChoice) {
// end choice by done button in feedback panel
// disable after done option implemented
// done = true;
}
+
+ // triggered abilities can't be skipped by cancel or wrong answer
if (source.getAbilityType() != AbilityType.TRIGGERED) {
done = true;
}
diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/pom.xml
index 32f5eadeb11..ee04e76d777 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.42
+ 1.4.43
mage-tournament-boosterdraft
diff --git a/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/VintageCubeApril2020.java b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/VintageCubeApril2020.java
new file mode 100644
index 00000000000..762f3922920
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Tournament.BoosterDraft/src/mage/tournament/cubes/VintageCubeApril2020.java
@@ -0,0 +1,552 @@
+package mage.tournament.cubes;
+
+import mage.game.draft.DraftCube;
+
+public class VintageCubeApril2020 extends DraftCube {
+
+ public VintageCubeApril2020() {
+ super("MTGO Vintage Cube April 2020");
+
+ cubeCards.add(new CardIdentity("Kytheon, Hero of Akros", ""));
+ cubeCards.add(new CardIdentity("Mother of Runes", ""));
+ cubeCards.add(new CardIdentity("Student of Warfare", ""));
+ cubeCards.add(new CardIdentity("Adanto Vanguard", ""));
+ cubeCards.add(new CardIdentity("Containment Priest", ""));
+ cubeCards.add(new CardIdentity("Leonin Relic-Warder", ""));
+ cubeCards.add(new CardIdentity("Porcelain Legionnaire", ""));
+ cubeCards.add(new CardIdentity("Selfless Spirit", ""));
+ cubeCards.add(new CardIdentity("Soulfire Grand Master", ""));
+ cubeCards.add(new CardIdentity("Stoneforge Mystic", ""));
+ cubeCards.add(new CardIdentity("Thalia, Guardian of Thraben", ""));
+ cubeCards.add(new CardIdentity("Tithe Taker", ""));
+ cubeCards.add(new CardIdentity("Wall of Omens", ""));
+ cubeCards.add(new CardIdentity("Blade Splicer", ""));
+ cubeCards.add(new CardIdentity("Brightling", ""));
+ cubeCards.add(new CardIdentity("Brimaz, King of Oreskos", ""));
+ cubeCards.add(new CardIdentity("Fairgrounds Warden", ""));
+ cubeCards.add(new CardIdentity("Flickerwisp", ""));
+ cubeCards.add(new CardIdentity("Monastery Mentor", ""));
+ cubeCards.add(new CardIdentity("Recruiter of the Guard", ""));
+ cubeCards.add(new CardIdentity("Silverblade Paladin", ""));
+ cubeCards.add(new CardIdentity("Emeria Angel", ""));
+ cubeCards.add(new CardIdentity("Hero of Bladehold", ""));
+ cubeCards.add(new CardIdentity("Linvala, Keeper of Silence", ""));
+ cubeCards.add(new CardIdentity("Restoration Angel", ""));
+ cubeCards.add(new CardIdentity("Angel of Invention", ""));
+ cubeCards.add(new CardIdentity("Elspeth Conquers Death", ""));
+ cubeCards.add(new CardIdentity("Archangel Avacyn", ""));
+ cubeCards.add(new CardIdentity("Baneslayer Angel", ""));
+ cubeCards.add(new CardIdentity("Lyra Dawnbringer", ""));
+ cubeCards.add(new CardIdentity("Reveillark", ""));
+ cubeCards.add(new CardIdentity("Sun Titan", ""));
+ cubeCards.add(new CardIdentity("Angel of Serenity", ""));
+ cubeCards.add(new CardIdentity("Elesh Norn, Grand Cenobite", ""));
+ cubeCards.add(new CardIdentity("Iona, Shield of Emeria", ""));
+ cubeCards.add(new CardIdentity("Gideon Blackblade", ""));
+ cubeCards.add(new CardIdentity("Elspeth, Sun's Nemesis", ""));
+ cubeCards.add(new CardIdentity("Gideon, Ally of Zendikar", ""));
+ cubeCards.add(new CardIdentity("Gideon Jura", ""));
+ cubeCards.add(new CardIdentity("Elspeth, Sun's Champion", ""));
+ cubeCards.add(new CardIdentity("Condemn", ""));
+ cubeCards.add(new CardIdentity("Enlightened Tutor", ""));
+ cubeCards.add(new CardIdentity("Mana Tithe", ""));
+ cubeCards.add(new CardIdentity("Path to Exile", ""));
+ cubeCards.add(new CardIdentity("Swords to Plowshares", ""));
+ cubeCards.add(new CardIdentity("Disenchant", ""));
+ cubeCards.add(new CardIdentity("Unexpectedly Absent", ""));
+ cubeCards.add(new CardIdentity("Balance", ""));
+ cubeCards.add(new CardIdentity("Council's Judgment", ""));
+ cubeCards.add(new CardIdentity("Spectral Procession", ""));
+ cubeCards.add(new CardIdentity("Armageddon", ""));
+ cubeCards.add(new CardIdentity("Day of Judgment", ""));
+ cubeCards.add(new CardIdentity("Ravages of War", ""));
+ cubeCards.add(new CardIdentity("Wrath of God", ""));
+ cubeCards.add(new CardIdentity("Terminus", ""));
+ cubeCards.add(new CardIdentity("Land Tax", ""));
+ cubeCards.add(new CardIdentity("Legion's Landing", ""));
+ cubeCards.add(new CardIdentity("Honor of the Pure", ""));
+ cubeCards.add(new CardIdentity("Banishing Light", ""));
+ cubeCards.add(new CardIdentity("Oblivion Ring", ""));
+ cubeCards.add(new CardIdentity("Faith's Fetters", ""));
+ cubeCards.add(new CardIdentity("Moat", ""));
+ cubeCards.add(new CardIdentity("Parallax Wave", ""));
+ cubeCards.add(new CardIdentity("Spear of Heliod", ""));
+ cubeCards.add(new CardIdentity("Karakas", ""));
+ cubeCards.add(new CardIdentity("Thassa's Oracle", ""));
+ cubeCards.add(new CardIdentity("Baral, Chief of Compliance", ""));
+ cubeCards.add(new CardIdentity("Jace, Vryn's Prodigy", ""));
+ cubeCards.add(new CardIdentity("Looter il-Kor", ""));
+ cubeCards.add(new CardIdentity("Phantasmal Image", ""));
+ cubeCards.add(new CardIdentity("Snapcaster Mage", ""));
+ cubeCards.add(new CardIdentity("Thing in the Ice", ""));
+ cubeCards.add(new CardIdentity("Arcane Artisan", ""));
+ cubeCards.add(new CardIdentity("Deceiver Exarch", ""));
+ cubeCards.add(new CardIdentity("Pestermite", ""));
+ cubeCards.add(new CardIdentity("Spellseeker", ""));
+ cubeCards.add(new CardIdentity("Trinket Mage", ""));
+ cubeCards.add(new CardIdentity("Vendilion Clique", ""));
+ cubeCards.add(new CardIdentity("Glen Elendra Archmage", ""));
+ cubeCards.add(new CardIdentity("Phyrexian Metamorph", ""));
+ cubeCards.add(new CardIdentity("Sower of Temptation", ""));
+ cubeCards.add(new CardIdentity("Venser, Shaper Savant", ""));
+ cubeCards.add(new CardIdentity("Mulldrifter", ""));
+ cubeCards.add(new CardIdentity("Riftwing Cloudskate", ""));
+ cubeCards.add(new CardIdentity("Consecrated Sphinx", ""));
+ cubeCards.add(new CardIdentity("Frost Titan", ""));
+ cubeCards.add(new CardIdentity("Torrential Gearhulk", ""));
+ cubeCards.add(new CardIdentity("Palinchron", ""));
+ cubeCards.add(new CardIdentity("Inkwell Leviathan", ""));
+ cubeCards.add(new CardIdentity("Jace Beleren", ""));
+ cubeCards.add(new CardIdentity("Jace, the Mind Sculptor", ""));
+ cubeCards.add(new CardIdentity("Tezzeret the Seeker", ""));
+ cubeCards.add(new CardIdentity("Ancestral Recall", ""));
+ cubeCards.add(new CardIdentity("Brainstorm", ""));
+ cubeCards.add(new CardIdentity("High Tide", ""));
+ cubeCards.add(new CardIdentity("Mystical Tutor", ""));
+ cubeCards.add(new CardIdentity("Spell Pierce", ""));
+ cubeCards.add(new CardIdentity("Brain Freeze", ""));
+ cubeCards.add(new CardIdentity("Counterspell", ""));
+ cubeCards.add(new CardIdentity("Daze", ""));
+ cubeCards.add(new CardIdentity("Impulse", ""));
+ cubeCards.add(new CardIdentity("Mana Drain", ""));
+ cubeCards.add(new CardIdentity("Mana Leak", ""));
+ cubeCards.add(new CardIdentity("Miscalculation", ""));
+ cubeCards.add(new CardIdentity("Remand", ""));
+ cubeCards.add(new CardIdentity("Frantic Search", ""));
+ cubeCards.add(new CardIdentity("Thirst for Knowledge", ""));
+ cubeCards.add(new CardIdentity("Cryptic Command", ""));
+ cubeCards.add(new CardIdentity("Fact or Fiction", ""));
+ cubeCards.add(new CardIdentity("Gifts Ungiven", ""));
+ cubeCards.add(new CardIdentity("Turnabout", ""));
+ cubeCards.add(new CardIdentity("Force of Will", ""));
+ cubeCards.add(new CardIdentity("Gush", ""));
+ cubeCards.add(new CardIdentity("Mystic Confluence", ""));
+ cubeCards.add(new CardIdentity("Repeal", ""));
+ cubeCards.add(new CardIdentity("Dig Through Time", ""));
+ cubeCards.add(new CardIdentity("Ancestral Vision", ""));
+ cubeCards.add(new CardIdentity("Gitaxian Probe", ""));
+ cubeCards.add(new CardIdentity("Ponder", ""));
+ cubeCards.add(new CardIdentity("Preordain", ""));
+ cubeCards.add(new CardIdentity("Chart a Course", ""));
+ cubeCards.add(new CardIdentity("Time Walk", ""));
+ cubeCards.add(new CardIdentity("Show and Tell", ""));
+ cubeCards.add(new CardIdentity("Timetwister", ""));
+ cubeCards.add(new CardIdentity("Tinker", ""));
+ cubeCards.add(new CardIdentity("Bribery", ""));
+ cubeCards.add(new CardIdentity("Time Warp", ""));
+ cubeCards.add(new CardIdentity("Mind's Desire", ""));
+ cubeCards.add(new CardIdentity("Time Spiral", ""));
+ cubeCards.add(new CardIdentity("Upheaval", ""));
+ cubeCards.add(new CardIdentity("Treasure Cruise", ""));
+ cubeCards.add(new CardIdentity("Search for Azcanta", ""));
+ cubeCards.add(new CardIdentity("Control Magic", ""));
+ cubeCards.add(new CardIdentity("Opposition", ""));
+ cubeCards.add(new CardIdentity("Treachery", ""));
+ cubeCards.add(new CardIdentity("Shelldock Isle", ""));
+ cubeCards.add(new CardIdentity("Tolarian Academy", ""));
+ cubeCards.add(new CardIdentity("Putrid Imp", ""));
+ cubeCards.add(new CardIdentity("Dark Confidant", ""));
+ cubeCards.add(new CardIdentity("Kitesail Freebooter", ""));
+ cubeCards.add(new CardIdentity("Mesmeric Fiend", ""));
+ cubeCards.add(new CardIdentity("Oona's Prowler", ""));
+ cubeCards.add(new CardIdentity("Pack Rat", ""));
+ cubeCards.add(new CardIdentity("Vampire Hexmage", ""));
+ cubeCards.add(new CardIdentity("Bone Shredder", ""));
+ cubeCards.add(new CardIdentity("Hypnotic Specter", ""));
+ cubeCards.add(new CardIdentity("Ophiomancer", ""));
+ cubeCards.add(new CardIdentity("Plaguecrafter", ""));
+ cubeCards.add(new CardIdentity("Vampire Nighthawk", ""));
+ cubeCards.add(new CardIdentity("Gonti, Lord of Luxury", ""));
+ cubeCards.add(new CardIdentity("Nekrataal", ""));
+ cubeCards.add(new CardIdentity("Ravenous Chupacabra", ""));
+ cubeCards.add(new CardIdentity("Shriekmaw", ""));
+ cubeCards.add(new CardIdentity("Grave Titan", ""));
+ cubeCards.add(new CardIdentity("Ink-Eyes, Servant of Oni", ""));
+ cubeCards.add(new CardIdentity("Massacre Wurm", ""));
+ cubeCards.add(new CardIdentity("Tasigur, the Golden Fang", ""));
+ cubeCards.add(new CardIdentity("Sheoldred, Whispering One", ""));
+ cubeCards.add(new CardIdentity("Griselbrand", ""));
+ cubeCards.add(new CardIdentity("Liliana of the Veil", ""));
+ cubeCards.add(new CardIdentity("Liliana, Death's Majesty", ""));
+ cubeCards.add(new CardIdentity("Dark Ritual", ""));
+ cubeCards.add(new CardIdentity("Entomb", ""));
+ cubeCards.add(new CardIdentity("Fatal Push", ""));
+ cubeCards.add(new CardIdentity("Vampiric Tutor", ""));
+ cubeCards.add(new CardIdentity("Cabal Ritual", ""));
+ cubeCards.add(new CardIdentity("Go for the Throat", ""));
+ cubeCards.add(new CardIdentity("Liliana's Triumph", ""));
+ cubeCards.add(new CardIdentity("Shallow Grave", ""));
+ cubeCards.add(new CardIdentity("Ultimate Price", ""));
+ cubeCards.add(new CardIdentity("Corpse Dance", ""));
+ cubeCards.add(new CardIdentity("Dismember", ""));
+ cubeCards.add(new CardIdentity("Hero's Downfall", ""));
+ cubeCards.add(new CardIdentity("Makeshift Mannequin", ""));
+ cubeCards.add(new CardIdentity("Duress", ""));
+ cubeCards.add(new CardIdentity("Imperial Seal", ""));
+ cubeCards.add(new CardIdentity("Inquisition of Kozilek", ""));
+ cubeCards.add(new CardIdentity("Reanimate", ""));
+ cubeCards.add(new CardIdentity("Thoughtseize", ""));
+ cubeCards.add(new CardIdentity("Collective Brutality", ""));
+ cubeCards.add(new CardIdentity("Demonic Tutor", ""));
+ cubeCards.add(new CardIdentity("Exhume", ""));
+ cubeCards.add(new CardIdentity("Hymn to Tourach", ""));
+ cubeCards.add(new CardIdentity("Night's Whisper", ""));
+ cubeCards.add(new CardIdentity("Buried Alive", ""));
+ cubeCards.add(new CardIdentity("Toxic Deluge", ""));
+ cubeCards.add(new CardIdentity("Yawgmoth's Will", ""));
+ cubeCards.add(new CardIdentity("Damnation", ""));
+ cubeCards.add(new CardIdentity("Languish", ""));
+ cubeCards.add(new CardIdentity("Mastermind's Acquisition", ""));
+ cubeCards.add(new CardIdentity("Tendrils of Agony", ""));
+ cubeCards.add(new CardIdentity("Dark Petition", ""));
+ cubeCards.add(new CardIdentity("Living Death", ""));
+ cubeCards.add(new CardIdentity("Mind Twist", ""));
+ cubeCards.add(new CardIdentity("Animate Dead", ""));
+ cubeCards.add(new CardIdentity("Bitterblossom", ""));
+ cubeCards.add(new CardIdentity("Necromancy", ""));
+ cubeCards.add(new CardIdentity("Phyrexian Arena", ""));
+ cubeCards.add(new CardIdentity("Recurring Nightmare", ""));
+ cubeCards.add(new CardIdentity("Yawgmoth's Bargain", ""));
+ cubeCards.add(new CardIdentity("Goblin Guide", ""));
+ cubeCards.add(new CardIdentity("Goblin Welder", ""));
+ cubeCards.add(new CardIdentity("Grim Lavamancer", ""));
+ cubeCards.add(new CardIdentity("Jackal Pup", ""));
+ cubeCards.add(new CardIdentity("Monastery Swiftspear", ""));
+ cubeCards.add(new CardIdentity("Zurgo Bellstriker", ""));
+ cubeCards.add(new CardIdentity("Abbot of Keral Keep", ""));
+ cubeCards.add(new CardIdentity("Dire Fleet Daredevil", ""));
+ cubeCards.add(new CardIdentity("Eidolon of the Great Revel", ""));
+ cubeCards.add(new CardIdentity("Runaway Steam-Kin", ""));
+ cubeCards.add(new CardIdentity("Young Pyromancer", ""));
+ cubeCards.add(new CardIdentity("Goblin Rabblemaster", ""));
+ cubeCards.add(new CardIdentity("Imperial Recruiter", ""));
+ cubeCards.add(new CardIdentity("Magus of the Moon", ""));
+ cubeCards.add(new CardIdentity("Avalanche Riders", ""));
+ cubeCards.add(new CardIdentity("Flametongue Kavu", ""));
+ cubeCards.add(new CardIdentity("Hazoret the Fervent", ""));
+ cubeCards.add(new CardIdentity("Hellrider", ""));
+ cubeCards.add(new CardIdentity("Pia and Kiran Nalaar", ""));
+ cubeCards.add(new CardIdentity("Rekindling Phoenix", ""));
+ cubeCards.add(new CardIdentity("Glorybringer", ""));
+ cubeCards.add(new CardIdentity("Goblin Dark-Dwellers", ""));
+ cubeCards.add(new CardIdentity("Kiki-Jiki, Mirror Breaker", ""));
+ cubeCards.add(new CardIdentity("Siege-Gang Commander", ""));
+ cubeCards.add(new CardIdentity("Thundermaw Hellkite", ""));
+ cubeCards.add(new CardIdentity("Zealous Conscripts", ""));
+ cubeCards.add(new CardIdentity("Inferno Titan", ""));
+ cubeCards.add(new CardIdentity("Chandra, Torch of Defiance", ""));
+ cubeCards.add(new CardIdentity("Daretti, Scrap Savant", ""));
+ cubeCards.add(new CardIdentity("Koth of the Hammer", ""));
+ cubeCards.add(new CardIdentity("Burst Lightning", ""));
+ cubeCards.add(new CardIdentity("Lightning Bolt", ""));
+ cubeCards.add(new CardIdentity("Abrade", ""));
+ cubeCards.add(new CardIdentity("Ancient Grudge", ""));
+ cubeCards.add(new CardIdentity("Desperate Ritual", ""));
+ cubeCards.add(new CardIdentity("Fire // Ice", ""));
+ cubeCards.add(new CardIdentity("Incinerate", ""));
+ cubeCards.add(new CardIdentity("Lightning Strike", ""));
+ cubeCards.add(new CardIdentity("Pyretic Ritual", ""));
+ cubeCards.add(new CardIdentity("Char", ""));
+ cubeCards.add(new CardIdentity("Seething Song", ""));
+ cubeCards.add(new CardIdentity("Through the Breach", ""));
+ cubeCards.add(new CardIdentity("Fireblast", ""));
+ cubeCards.add(new CardIdentity("Chain Lightning", ""));
+ cubeCards.add(new CardIdentity("Faithless Looting", ""));
+ cubeCards.add(new CardIdentity("Firebolt", ""));
+ cubeCards.add(new CardIdentity("Flame Slash", ""));
+ cubeCards.add(new CardIdentity("Mizzium Mortars", ""));
+ cubeCards.add(new CardIdentity("Pyroclasm", ""));
+ cubeCards.add(new CardIdentity("Light Up the Stage", ""));
+ cubeCards.add(new CardIdentity("Underworld Breach", ""));
+ cubeCards.add(new CardIdentity("Wheel of Fortune", ""));
+ cubeCards.add(new CardIdentity("Empty the Warrens", ""));
+ cubeCards.add(new CardIdentity("Fiery Confluence", ""));
+ cubeCards.add(new CardIdentity("Past in Flames", ""));
+ cubeCards.add(new CardIdentity("Banefire", ""));
+ cubeCards.add(new CardIdentity("Burning of Xinye", ""));
+ cubeCards.add(new CardIdentity("Wildfire", ""));
+ cubeCards.add(new CardIdentity("Bonfire of the Damned", ""));
+ cubeCards.add(new CardIdentity("Mana Flare", ""));
+ cubeCards.add(new CardIdentity("Sulfuric Vortex", ""));
+ cubeCards.add(new CardIdentity("Sneak Attack", ""));
+ cubeCards.add(new CardIdentity("Splinter Twin", ""));
+ cubeCards.add(new CardIdentity("Arbor Elf", ""));
+ cubeCards.add(new CardIdentity("Avacyn's Pilgrim", ""));
+ cubeCards.add(new CardIdentity("Birds of Paradise", ""));
+ cubeCards.add(new CardIdentity("Elves of Deep Shadow", ""));
+ cubeCards.add(new CardIdentity("Elvish Mystic", ""));
+ cubeCards.add(new CardIdentity("Fyndhorn Elves", ""));
+ cubeCards.add(new CardIdentity("Joraga Treespeaker", ""));
+ cubeCards.add(new CardIdentity("Llanowar Elves", ""));
+ cubeCards.add(new CardIdentity("Noble Hierarch", ""));
+ cubeCards.add(new CardIdentity("Den Protector", ""));
+ cubeCards.add(new CardIdentity("Devoted Druid", ""));
+ cubeCards.add(new CardIdentity("Fauna Shaman", ""));
+ cubeCards.add(new CardIdentity("Gilded Goose", ""));
+ cubeCards.add(new CardIdentity("Lotus Cobra", ""));
+ cubeCards.add(new CardIdentity("Rofellos, Llanowar Emissary", ""));
+ cubeCards.add(new CardIdentity("Sakura-Tribe Elder", ""));
+ cubeCards.add(new CardIdentity("Scavenging Ooze", ""));
+ cubeCards.add(new CardIdentity("Sylvan Caryatid", ""));
+ cubeCards.add(new CardIdentity("Wall of Blossoms", ""));
+ cubeCards.add(new CardIdentity("Wall of Roots", ""));
+ cubeCards.add(new CardIdentity("Courser of Kruphix", ""));
+ cubeCards.add(new CardIdentity("Eternal Witness", ""));
+ cubeCards.add(new CardIdentity("Ramunap Excavator", ""));
+ cubeCards.add(new CardIdentity("Reclamation Sage", ""));
+ cubeCards.add(new CardIdentity("Tireless Tracker", ""));
+ cubeCards.add(new CardIdentity("Yavimaya Elder", ""));
+ cubeCards.add(new CardIdentity("Master of the Wild Hunt", ""));
+ cubeCards.add(new CardIdentity("Oracle of Mul Daya", ""));
+ cubeCards.add(new CardIdentity("Polukranos, World Eater", ""));
+ cubeCards.add(new CardIdentity("Acidic Slime", ""));
+ cubeCards.add(new CardIdentity("Biogenic Ooze", ""));
+ cubeCards.add(new CardIdentity("Deranged Hermit", ""));
+ cubeCards.add(new CardIdentity("Thragtusk", ""));
+ cubeCards.add(new CardIdentity("Whisperwood Elemental", ""));
+ cubeCards.add(new CardIdentity("Carnage Tyrant", ""));
+ cubeCards.add(new CardIdentity("Primeval Titan", ""));
+ cubeCards.add(new CardIdentity("Avenger of Zendikar", ""));
+ cubeCards.add(new CardIdentity("Craterhoof Behemoth", ""));
+ cubeCards.add(new CardIdentity("Terastodon", ""));
+ cubeCards.add(new CardIdentity("Woodfall Primus", ""));
+ cubeCards.add(new CardIdentity("Dryad of the Ilysian Grove", ""));
+ cubeCards.add(new CardIdentity("Garruk Relentless", ""));
+ cubeCards.add(new CardIdentity("Garruk Wildspeaker", ""));
+ cubeCards.add(new CardIdentity("Garruk, Primal Hunter", ""));
+ cubeCards.add(new CardIdentity("Vivien Reid", ""));
+ cubeCards.add(new CardIdentity("Nature's Claim", ""));
+ cubeCards.add(new CardIdentity("Beast Within", ""));
+ cubeCards.add(new CardIdentity("Channel", ""));
+ cubeCards.add(new CardIdentity("Regrowth", ""));
+ cubeCards.add(new CardIdentity("Kodama's Reach", ""));
+ cubeCards.add(new CardIdentity("Search for Tomorrow", ""));
+ cubeCards.add(new CardIdentity("Eureka", ""));
+ cubeCards.add(new CardIdentity("Harmonize", ""));
+ cubeCards.add(new CardIdentity("Natural Order", ""));
+ cubeCards.add(new CardIdentity("Plow Under", ""));
+ cubeCards.add(new CardIdentity("Primal Command", ""));
+ cubeCards.add(new CardIdentity("Green Sun's Zenith", ""));
+ cubeCards.add(new CardIdentity("Finale of Devastation", ""));
+ cubeCards.add(new CardIdentity("Tooth and Nail", ""));
+ cubeCards.add(new CardIdentity("Fastbond", ""));
+ cubeCards.add(new CardIdentity("Oath of Druids", ""));
+ cubeCards.add(new CardIdentity("Survival of the Fittest", ""));
+ cubeCards.add(new CardIdentity("Sylvan Library", ""));
+ cubeCards.add(new CardIdentity("Heartbeat of Spring", ""));
+ cubeCards.add(new CardIdentity("Wilderness Reclamation", ""));
+ cubeCards.add(new CardIdentity("Gaea's Cradle", ""));
+ cubeCards.add(new CardIdentity("Geist of Saint Traft", ""));
+ cubeCards.add(new CardIdentity("Teferi, Hero of Dominaria", ""));
+ cubeCards.add(new CardIdentity("Sphinx's Revelation", ""));
+ cubeCards.add(new CardIdentity("Fractured Identity", ""));
+ cubeCards.add(new CardIdentity("Celestial Colonnade", ""));
+ cubeCards.add(new CardIdentity("Flooded Strand", ""));
+ cubeCards.add(new CardIdentity("Hallowed Fountain", ""));
+ cubeCards.add(new CardIdentity("Seachrome Coast", ""));
+ cubeCards.add(new CardIdentity("Tundra", ""));
+ cubeCards.add(new CardIdentity("Thief of Sanity", ""));
+ cubeCards.add(new CardIdentity("The Scarab God", ""));
+ cubeCards.add(new CardIdentity("Ashiok, Nightmare Weaver", ""));
+ cubeCards.add(new CardIdentity("Baleful Strix", ""));
+ cubeCards.add(new CardIdentity("Creeping Tar Pit", ""));
+ cubeCards.add(new CardIdentity("Darkslick Shores", ""));
+ cubeCards.add(new CardIdentity("Polluted Delta", ""));
+ cubeCards.add(new CardIdentity("Underground Sea", ""));
+ cubeCards.add(new CardIdentity("Watery Grave", ""));
+ cubeCards.add(new CardIdentity("Daretti, Ingenious Iconoclast", ""));
+ cubeCards.add(new CardIdentity("Kroxa, Titan of Death's Hunger", ""));
+ cubeCards.add(new CardIdentity("Kolaghan's Command", ""));
+ cubeCards.add(new CardIdentity("Rakdos's Return", ""));
+ cubeCards.add(new CardIdentity("Badlands", ""));
+ cubeCards.add(new CardIdentity("Blackcleave Cliffs", ""));
+ cubeCards.add(new CardIdentity("Blood Crypt", ""));
+ cubeCards.add(new CardIdentity("Bloodstained Mire", ""));
+ cubeCards.add(new CardIdentity("Lavaclaw Reaches", ""));
+ cubeCards.add(new CardIdentity("Bloodbraid Elf", ""));
+ cubeCards.add(new CardIdentity("Huntmaster of the Fells", ""));
+ cubeCards.add(new CardIdentity("Dragonlord Atarka", ""));
+ cubeCards.add(new CardIdentity("Manamorphose", ""));
+ cubeCards.add(new CardIdentity("Copperline Gorge", ""));
+ cubeCards.add(new CardIdentity("Raging Ravine", ""));
+ cubeCards.add(new CardIdentity("Stomping Ground", ""));
+ cubeCards.add(new CardIdentity("Taiga", ""));
+ cubeCards.add(new CardIdentity("Wooded Foothills", ""));
+ cubeCards.add(new CardIdentity("Kitchen Finks", ""));
+ cubeCards.add(new CardIdentity("Knight of Autumn", ""));
+ cubeCards.add(new CardIdentity("Knight of the Reliquary", ""));
+ cubeCards.add(new CardIdentity("Trostani Discordant", ""));
+ cubeCards.add(new CardIdentity("Mirari's Wake", ""));
+ cubeCards.add(new CardIdentity("Razorverge Thicket", ""));
+ cubeCards.add(new CardIdentity("Savannah", ""));
+ cubeCards.add(new CardIdentity("Stirring Wildwood", ""));
+ cubeCards.add(new CardIdentity("Temple Garden", ""));
+ cubeCards.add(new CardIdentity("Windswept Heath", ""));
+ cubeCards.add(new CardIdentity("Ashen Rider", ""));
+ cubeCards.add(new CardIdentity("Kaya, Orzhov Usurper", ""));
+ cubeCards.add(new CardIdentity("Tidehollow Sculler", ""));
+ cubeCards.add(new CardIdentity("Anguished Unmaking", ""));
+ cubeCards.add(new CardIdentity("Lingering Souls", ""));
+ cubeCards.add(new CardIdentity("Vindicate", ""));
+ cubeCards.add(new CardIdentity("Unburial Rites", ""));
+ cubeCards.add(new CardIdentity("Concealed Courtyard", ""));
+ cubeCards.add(new CardIdentity("Godless Shrine", ""));
+ cubeCards.add(new CardIdentity("Marsh Flats", ""));
+ cubeCards.add(new CardIdentity("Scrubland", ""));
+ cubeCards.add(new CardIdentity("Shambling Vent", ""));
+ cubeCards.add(new CardIdentity("Vraska, Golgari Queen", ""));
+ cubeCards.add(new CardIdentity("Assassin's Trophy", ""));
+ cubeCards.add(new CardIdentity("Maelstrom Pulse", ""));
+ cubeCards.add(new CardIdentity("Pernicious Deed", ""));
+ cubeCards.add(new CardIdentity("Bayou", ""));
+ cubeCards.add(new CardIdentity("Blooming Marsh", ""));
+ cubeCards.add(new CardIdentity("Hissing Quagmire", ""));
+ cubeCards.add(new CardIdentity("Overgrown Tomb", ""));
+ cubeCards.add(new CardIdentity("Verdant Catacombs", ""));
+ cubeCards.add(new CardIdentity("Edric, Spymaster of Trest", ""));
+ cubeCards.add(new CardIdentity("Trygon Predator", ""));
+ cubeCards.add(new CardIdentity("Hydroid Krasis", ""));
+ cubeCards.add(new CardIdentity("Uro, Titan of Nature's Wrath", ""));
+ cubeCards.add(new CardIdentity("Botanical Sanctum", ""));
+ cubeCards.add(new CardIdentity("Breeding Pool", ""));
+ cubeCards.add(new CardIdentity("Lumbering Falls", ""));
+ cubeCards.add(new CardIdentity("Misty Rainforest", ""));
+ cubeCards.add(new CardIdentity("Tropical Island", ""));
+ cubeCards.add(new CardIdentity("Goblin Electromancer", ""));
+ cubeCards.add(new CardIdentity("Dack Fayden", ""));
+ cubeCards.add(new CardIdentity("Thousand-Year Storm", ""));
+ cubeCards.add(new CardIdentity("Scalding Tarn", ""));
+ cubeCards.add(new CardIdentity("Spirebluff Canal", ""));
+ cubeCards.add(new CardIdentity("Steam Vents", ""));
+ cubeCards.add(new CardIdentity("Volcanic Island", ""));
+ cubeCards.add(new CardIdentity("Wandering Fumarole", ""));
+ cubeCards.add(new CardIdentity("Figure of Destiny", ""));
+ cubeCards.add(new CardIdentity("Ajani Vengeant", ""));
+ cubeCards.add(new CardIdentity("Nahiri, the Harbinger", ""));
+ cubeCards.add(new CardIdentity("Wear // Tear", ""));
+ cubeCards.add(new CardIdentity("Lightning Helix", ""));
+ cubeCards.add(new CardIdentity("Arid Mesa", ""));
+ cubeCards.add(new CardIdentity("Inspiring Vantage", ""));
+ cubeCards.add(new CardIdentity("Needle Spires", ""));
+ cubeCards.add(new CardIdentity("Plateau", ""));
+ cubeCards.add(new CardIdentity("Sacred Foundry", ""));
+ cubeCards.add(new CardIdentity("Sphinx of the Steel Wind", ""));
+ cubeCards.add(new CardIdentity("Nicol Bolas, Dragon-God", ""));
+ cubeCards.add(new CardIdentity("Leovold, Emissary of Trest", ""));
+ cubeCards.add(new CardIdentity("Progenitus", ""));
+ cubeCards.add(new CardIdentity("Kozilek, Butcher of Truth", ""));
+ cubeCards.add(new CardIdentity("Ulamog, the Ceaseless Hunger", ""));
+ cubeCards.add(new CardIdentity("Ulamog, the Infinite Gyre", ""));
+ cubeCards.add(new CardIdentity("Emrakul, the Promised End", ""));
+ cubeCards.add(new CardIdentity("Emrakul, the Aeons Torn", ""));
+ cubeCards.add(new CardIdentity("Karn, Scion of Urza", ""));
+ cubeCards.add(new CardIdentity("Karn Liberated", ""));
+ cubeCards.add(new CardIdentity("Ugin, the Spirit Dragon", ""));
+ cubeCards.add(new CardIdentity("Bomat Courier", ""));
+ cubeCards.add(new CardIdentity("Hangarback Walker", ""));
+ cubeCards.add(new CardIdentity("Phyrexian Revoker", ""));
+ cubeCards.add(new CardIdentity("Metalworker", ""));
+ cubeCards.add(new CardIdentity("Lodestone Golem", ""));
+ cubeCards.add(new CardIdentity("Solemn Simulacrum", ""));
+ cubeCards.add(new CardIdentity("Kuldotha Forgemaster", ""));
+ cubeCards.add(new CardIdentity("Wurmcoil Engine", ""));
+ cubeCards.add(new CardIdentity("Myr Battlesphere", ""));
+ cubeCards.add(new CardIdentity("Sundering Titan", ""));
+ cubeCards.add(new CardIdentity("Walking Ballista", ""));
+ cubeCards.add(new CardIdentity("Blightsteel Colossus", ""));
+ cubeCards.add(new CardIdentity("Black Lotus", ""));
+ cubeCards.add(new CardIdentity("Chrome Mox", ""));
+ cubeCards.add(new CardIdentity("Everflowing Chalice", ""));
+ cubeCards.add(new CardIdentity("Lion's Eye Diamond", ""));
+ cubeCards.add(new CardIdentity("Lotus Bloom", ""));
+ cubeCards.add(new CardIdentity("Mana Crypt", ""));
+ cubeCards.add(new CardIdentity("Mox Diamond", ""));
+ cubeCards.add(new CardIdentity("Mox Emerald", ""));
+ cubeCards.add(new CardIdentity("Mox Jet", ""));
+ cubeCards.add(new CardIdentity("Mox Pearl", ""));
+ cubeCards.add(new CardIdentity("Mox Ruby", ""));
+ cubeCards.add(new CardIdentity("Mox Sapphire", ""));
+ cubeCards.add(new CardIdentity("Mana Vault", ""));
+ cubeCards.add(new CardIdentity("Relic of Progenitus", ""));
+ cubeCards.add(new CardIdentity("Sensei's Divining Top", ""));
+ cubeCards.add(new CardIdentity("Skullclamp", ""));
+ cubeCards.add(new CardIdentity("Sol Ring", ""));
+ cubeCards.add(new CardIdentity("Azorius Signet", ""));
+ cubeCards.add(new CardIdentity("Boros Signet", ""));
+ cubeCards.add(new CardIdentity("Dimir Signet", ""));
+ cubeCards.add(new CardIdentity("Golgari Signet", ""));
+ cubeCards.add(new CardIdentity("Grim Monolith", ""));
+ cubeCards.add(new CardIdentity("Gruul Signet", ""));
+ cubeCards.add(new CardIdentity("Izzet Signet", ""));
+ cubeCards.add(new CardIdentity("Lightning Greaves", ""));
+ cubeCards.add(new CardIdentity("Orzhov Signet", ""));
+ cubeCards.add(new CardIdentity("Rakdos Signet", ""));
+ cubeCards.add(new CardIdentity("Selesnya Signet", ""));
+ cubeCards.add(new CardIdentity("Shrine of Burning Rage", ""));
+ cubeCards.add(new CardIdentity("Simic Signet", ""));
+ cubeCards.add(new CardIdentity("Smuggler's Copter", ""));
+ cubeCards.add(new CardIdentity("Umezawa's Jitte", ""));
+ cubeCards.add(new CardIdentity("Winter Orb", ""));
+ cubeCards.add(new CardIdentity("Basalt Monolith", ""));
+ cubeCards.add(new CardIdentity("Coalition Relic", ""));
+ cubeCards.add(new CardIdentity("Crucible of Worlds", ""));
+ cubeCards.add(new CardIdentity("Oblivion Stone", ""));
+ cubeCards.add(new CardIdentity("Sword of Body and Mind", ""));
+ cubeCards.add(new CardIdentity("Sword of Feast and Famine", ""));
+ cubeCards.add(new CardIdentity("Sword of Fire and Ice", ""));
+ cubeCards.add(new CardIdentity("Sword of Light and Shadow", ""));
+ cubeCards.add(new CardIdentity("Sword of War and Peace", ""));
+ cubeCards.add(new CardIdentity("Tangle Wire", ""));
+ cubeCards.add(new CardIdentity("Worn Powerstone", ""));
+ cubeCards.add(new CardIdentity("Coercive Portal", ""));
+ cubeCards.add(new CardIdentity("Smokestack", ""));
+ cubeCards.add(new CardIdentity("Thran Dynamo", ""));
+ cubeCards.add(new CardIdentity("Batterskull", ""));
+ cubeCards.add(new CardIdentity("Memory Jar", ""));
+ cubeCards.add(new CardIdentity("Mindslaver", ""));
+ cubeCards.add(new CardIdentity("Academy Ruins", ""));
+ cubeCards.add(new CardIdentity("Ancient Tomb", ""));
+ cubeCards.add(new CardIdentity("Bazaar of Baghdad", ""));
+ cubeCards.add(new CardIdentity("Blast Zone", ""));
+ cubeCards.add(new CardIdentity("Field of Ruin", ""));
+ cubeCards.add(new CardIdentity("Library of Alexandria", ""));
+ cubeCards.add(new CardIdentity("Maze of Ith", ""));
+ cubeCards.add(new CardIdentity("Mishra's Factory", ""));
+ cubeCards.add(new CardIdentity("Mishra's Workshop", ""));
+ cubeCards.add(new CardIdentity("Mutavault", ""));
+ cubeCards.add(new CardIdentity("Nykthos, Shrine to Nyx", ""));
+ cubeCards.add(new CardIdentity("Rishadan Port", ""));
+ cubeCards.add(new CardIdentity("Strip Mine", ""));
+ cubeCards.add(new CardIdentity("Wasteland", ""));
+ cubeCards.add(new CardIdentity("Expansion // Explosion", ""));
+ cubeCards.add(new CardIdentity("Giver of Runes", ""));
+ cubeCards.add(new CardIdentity("Winds of Abandon", ""));
+ cubeCards.add(new CardIdentity("Hallowed Spiritkeeper", ""));
+ cubeCards.add(new CardIdentity("Thraben Inspector", ""));
+ cubeCards.add(new CardIdentity("Narset, Parter of Veils", ""));
+ cubeCards.add(new CardIdentity("Force of Negation", ""));
+ cubeCards.add(new CardIdentity("Urza, Lord High Artificer", ""));
+ cubeCards.add(new CardIdentity("Emry, Lurker of the Loch", ""));
+ cubeCards.add(new CardIdentity("Brazen Borrower", ""));
+ cubeCards.add(new CardIdentity("Bolas's Citadel", ""));
+ cubeCards.add(new CardIdentity("Yawgmoth, Thran Physician", ""));
+ cubeCards.add(new CardIdentity("Rotting Regisaur", ""));
+ cubeCards.add(new CardIdentity("Murderous Rider", ""));
+ cubeCards.add(new CardIdentity("Wishclaw Talisman", ""));
+ cubeCards.add(new CardIdentity("Dreadhorde Arcanist", ""));
+ cubeCards.add(new CardIdentity("Seasoned Pyromancer", ""));
+ cubeCards.add(new CardIdentity("Embereth Shieldbreaker", ""));
+ cubeCards.add(new CardIdentity("Nissa, Who Shakes the World", ""));
+ cubeCards.add(new CardIdentity("Questing Beast", ""));
+ cubeCards.add(new CardIdentity("Teferi, Time Raveler", ""));
+ cubeCards.add(new CardIdentity("Angrath's Rampage", ""));
+ cubeCards.add(new CardIdentity("Fallen Shinobi", ""));
+ cubeCards.add(new CardIdentity("Wrenn and Six", ""));
+ cubeCards.add(new CardIdentity("Oko, Thief of Crowns", ""));
+ cubeCards.add(new CardIdentity("Garruk, Cursed Huntsman", ""));
+ cubeCards.add(new CardIdentity("Prismatic Vista", ""));
+ cubeCards.add(new CardIdentity("Golos, Tireless Pilgrim", ""));
+ cubeCards.add(new CardIdentity("Stonecoil Serpent", ""));
+ }
+}
+
diff --git a/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Constructed/pom.xml
index 8fa3ceae299..826e1af68d4 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.42
+ 1.4.43
mage-tournament-constructed
diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml b/Mage.Server.Plugins/Mage.Tournament.Sealed/pom.xml
index 3530951a0d8..aa062a8a455 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.42
+ 1.4.43
mage-tournament-sealed
diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartEliminationTournament.java b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartEliminationTournament.java
new file mode 100644
index 00000000000..d65634936af
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartEliminationTournament.java
@@ -0,0 +1,44 @@
+
+
+package mage.tournament;
+
+import mage.game.tournament.TournamentOptions;
+import mage.game.tournament.TournamentSingleElimination;
+
+public class JumpstartEliminationTournament extends TournamentSingleElimination {
+
+ protected enum TournamentStep {
+ START, OPEN_BOOSTERS, CONSTRUCT, COMPETE, WINNERS
+ }
+
+ protected TournamentStep currentStep;
+
+ public JumpstartEliminationTournament(TournamentOptions options) {
+ super(options);
+ currentStep = TournamentStep.START;
+ }
+
+ @Override
+ public void nextStep() {
+ switch (currentStep) {
+ case START:
+ currentStep = TournamentStep.OPEN_BOOSTERS;
+ openBoosters();
+ break;
+ case OPEN_BOOSTERS:
+ currentStep = TournamentStep.CONSTRUCT;
+ construct();
+ break;
+ case CONSTRUCT:
+ currentStep = TournamentStep.COMPETE;
+ runTournament();
+ break;
+ case COMPETE:
+ currentStep = TournamentStep.WINNERS;
+ winners();
+ end();
+ break;
+ }
+ }
+
+}
diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartEliminationTournamentType.java b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartEliminationTournamentType.java
new file mode 100644
index 00000000000..858588e4415
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartEliminationTournamentType.java
@@ -0,0 +1,19 @@
+
+
+package mage.tournament;
+
+import mage.game.tournament.TournamentType;
+
+public class JumpstartEliminationTournamentType extends TournamentType {
+
+ public JumpstartEliminationTournamentType() {
+ this.name = "Jumpstart Elimination";
+ this.maxPlayers = 16;
+ this.minPlayers = 2;
+ this.numBoosters = 0;
+ this.isJumpstart = true;
+ this.elimination = true;
+ this.limited = true;
+ }
+
+}
diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartSwissTournament.java b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartSwissTournament.java
new file mode 100644
index 00000000000..f0e7f34bc9f
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartSwissTournament.java
@@ -0,0 +1,44 @@
+
+
+package mage.tournament;
+
+import mage.game.tournament.TournamentOptions;
+import mage.game.tournament.TournamentSwiss;
+
+public class JumpstartSwissTournament extends TournamentSwiss {
+
+ protected enum TournamentStep {
+ START, OPEN_BOOSTERS, CONSTRUCT, COMPETE, WINNERS
+ }
+
+ protected TournamentStep currentStep;
+
+ public JumpstartSwissTournament(TournamentOptions options) {
+ super(options);
+ currentStep = TournamentStep.START;
+ }
+
+ @Override
+ public void nextStep() {
+ switch (currentStep) {
+ case START:
+ currentStep = TournamentStep.OPEN_BOOSTERS;
+ openBoosters();
+ break;
+ case OPEN_BOOSTERS:
+ currentStep = TournamentStep.CONSTRUCT;
+ construct();
+ break;
+ case CONSTRUCT:
+ currentStep = TournamentStep.COMPETE;
+ runTournament();
+ break;
+ case COMPETE:
+ currentStep = TournamentStep.WINNERS;
+ winners();
+ end();
+ break;
+ }
+ }
+
+}
diff --git a/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartSwissTournamentType.java b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartSwissTournamentType.java
new file mode 100644
index 00000000000..bf5328ed52d
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Tournament.Sealed/src/mage/tournament/JumpstartSwissTournamentType.java
@@ -0,0 +1,18 @@
+
+
+package mage.tournament;
+
+import mage.game.tournament.TournamentType;
+
+public class JumpstartSwissTournamentType extends TournamentType {
+
+ public JumpstartSwissTournamentType() {
+ this.name = "Jumpstart Swiss";
+ this.maxPlayers = 16;
+ this.minPlayers = 2;
+ this.numBoosters = 0;
+ this.isJumpstart = true;
+ this.limited = true;
+ }
+
+}
diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml
index c449b61d49b..bc32dd37241 100644
--- a/Mage.Server.Plugins/pom.xml
+++ b/Mage.Server.Plugins/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-root
- 1.4.42
+ 1.4.43
mage-server-plugins
diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml
index 884dd9ebe2e..6ee2e095469 100644
--- a/Mage.Server/config/config.xml
+++ b/Mage.Server/config/config.xml
@@ -56,13 +56,13 @@
saveGameActivated="false"
authenticationActivated="false"
googleAccount=""
- mailgunApiKey="key-d93e81f19a9c9ed243ebb7cc9381385c"
- mailgunDomain="sandbox401a433f30d445309a5e86b6c53f7812.mailgun.org"
- mailSmtpHost="smtp.1und1.de"
- mailSmtpPort="465"
- mailUser="xmageserver@online.de"
- mailPassword="24wrsfxv"
- mailFromAddress="xmageserver@online.de"
+ mailgunApiKey=""
+ mailgunDomain=""
+ mailSmtpHost=""
+ mailSmtpPort=""
+ mailUser=""
+ mailPassword=""
+ mailFromAddress=""
/>
@@ -104,6 +104,8 @@
+
+
@@ -143,6 +145,7 @@
+
diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml
index 318db625ade..dfb4fb958ab 100644
--- a/Mage.Server/pom.xml
+++ b/Mage.Server/pom.xml
@@ -6,7 +6,7 @@
org.mage
mage-root
- 1.4.42
+ 1.4.43
mage-server
diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml
index d6eb9c8884f..a4337f70d4c 100644
--- a/Mage.Server/release/config/config.xml
+++ b/Mage.Server/release/config/config.xml
@@ -98,6 +98,8 @@
+
+
@@ -137,6 +139,7 @@
+
diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java
index 386c8c2a662..93872312566 100644
--- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java
+++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java
@@ -397,15 +397,15 @@ public class MageServerImpl implements MageServer {
@Override
//FIXME: why no sessionId here???
- public Optional getTable(UUID roomId, UUID tableId) throws MageException {
+ public TableView getTable(UUID roomId, UUID tableId) throws MageException {
try {
Optional room = GamesRoomManager.instance.getRoom(roomId);
- return room.flatMap(r -> r.getTable(tableId));
+ return room.flatMap(r -> r.getTable(tableId)).orElse(null);
} catch (Exception ex) {
handleException(ex);
}
- return Optional.empty();
+ return null;
}
@Override
@@ -536,18 +536,18 @@ public class MageServerImpl implements MageServer {
@Override
//FIXME: why no sessionId here???
- public Optional getRoomChatId(UUID roomId) throws MageException {
+ public UUID getRoomChatId(UUID roomId) throws MageException {
try {
Optional room = GamesRoomManager.instance.getRoom(roomId);
if (!room.isPresent()) {
logger.error("roomId not found : " + roomId);
- return Optional.empty();
+ return null;
}
- return Optional.of(room.get().getChatId());
+ return room.get().getChatId();
} catch (Exception ex) {
handleException(ex);
}
- return Optional.empty();
+ return null;
}
@Override
@@ -602,13 +602,13 @@ public class MageServerImpl implements MageServer {
@Override
//FIXME: why no sessionId here???
- public Optional getTableChatId(UUID tableId) throws MageException {
+ public UUID getTableChatId(UUID tableId) throws MageException {
try {
- return TableManager.instance.getChatId(tableId);
+ return TableManager.instance.getChatId(tableId).orElse(null);
} catch (Exception ex) {
handleException(ex);
}
- return Optional.empty();
+ return null;
}
@Override
@@ -646,24 +646,24 @@ public class MageServerImpl implements MageServer {
@Override
//FIXME: why no sessionId here???
- public Optional getGameChatId(UUID gameId) throws MageException {
+ public UUID getGameChatId(UUID gameId) throws MageException {
try {
- return GameManager.instance.getChatId(gameId);
+ return GameManager.instance.getChatId(gameId).orElse(null);
} catch (Exception ex) {
handleException(ex);
}
- return Optional.empty();
+ return null;
}
@Override
//FIXME: why no sessionId here???
- public Optional getTournamentChatId(UUID tournamentId) throws MageException {
+ public UUID getTournamentChatId(UUID tournamentId) throws MageException {
try {
- return TournamentManager.instance.getChatId(tournamentId);
+ return TournamentManager.instance.getChatId(tournamentId).orElse(null);
} catch (Exception ex) {
handleException(ex);
}
- return Optional.empty();
+ return null;
}
@Override
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 a1963f587c1..883df510da6 100644
--- a/Mage.Server/src/main/java/mage/server/game/GameController.java
+++ b/Mage.Server/src/main/java/mage/server/game/GameController.java
@@ -1259,10 +1259,10 @@ public class GameController implements GameCallback {
.collect(Collectors.joining(", ")));
StringBuilder sb = new StringBuilder();
- sb.append("FIX command called by " + user.getName() + "");
+ sb.append("FIX command called by ").append(user.getName()).append("");
sb.append(""); // font resize start for all next logs
- sb.append("
Game ID: " + game.getId());
-
+ sb.append("
Game ID: ").append(game.getId());
+ sb.append("
Phase: ").append(game.getTurn().getPhaseType().toString()).append(" Step: ").append(game.getTurn().getStepType().toString());
// pings info
sb.append("
");
sb.append(getPingsInfo());
@@ -1272,7 +1272,7 @@ public class GameController implements GameCallback {
// fix active
Player playerActive = game.getPlayer(state.getActivePlayerId());
- sb.append("
Fixing active player: " + getName(playerActive));
+ sb.append("
Fixing active player: ").append(getName(playerActive));
if (playerActive != null && !playerActive.canRespond()) {
fixActions.add("active player fix");
@@ -1280,16 +1280,16 @@ public class GameController implements GameCallback {
sb.append("
Try to concede...");
playerActive.concede(game);
playerActive.leave(); // abort any wait response actions
- sb.append(" (" + asWarning("OK") + ", concede done)");
+ sb.append(" (").append(asWarning("OK")).append(", concede done)");
sb.append("
Try to skip step...");
Phase currentPhase = game.getPhase();
if (currentPhase != null) {
currentPhase.getStep().skipStep(game, state.getActivePlayerId());
fixedAlready = true;
- sb.append(" (" + asWarning("OK") + ", skip step done)");
+ sb.append(" (").append(asWarning("OK")).append(", skip step done)");
} else {
- sb.append(" (" + asBad("FAIL") + ", step is null)");
+ sb.append(" (").append(asBad("FAIL")).append(", step is null)");
}
} else {
sb.append(playerActive != null ? " (" + asGood("OK") + ", can respond)" : " (" + asGood("OK") + ", no player)");
@@ -1297,7 +1297,7 @@ public class GameController implements GameCallback {
// fix lost choosing dialog
Player choosingPlayer = game.getPlayer(state.getChoosingPlayerId());
- sb.append("
Fixing choosing player: " + getName(choosingPlayer));
+ sb.append("
Fixing choosing player: ").append(getName(choosingPlayer));
if (choosingPlayer != null && !choosingPlayer.canRespond()) {
fixActions.add("choosing player fix");
@@ -1305,7 +1305,7 @@ public class GameController implements GameCallback {
sb.append("
Try to concede...");
choosingPlayer.concede(game);
choosingPlayer.leave(); // abort any wait response actions
- sb.append(" (" + asWarning("OK") + ", concede done)");
+ sb.append(" (").append(asWarning("OK")).append(", concede done)");
sb.append("
Try to skip step...");
if (fixedAlready) {
@@ -1315,9 +1315,9 @@ public class GameController implements GameCallback {
if (currentPhase != null) {
currentPhase.getStep().skipStep(game, state.getActivePlayerId());
fixedAlready = true;
- sb.append(" (" + asWarning("OK") + ", skip step done)");
+ sb.append(" (").append(asWarning("OK")).append(", skip step done)");
} else {
- sb.append(" (" + asBad("FAIL") + ", step is null)");
+ sb.append(" (").append(asBad("FAIL")).append(", step is null)");
}
}
} else {
@@ -1326,7 +1326,7 @@ public class GameController implements GameCallback {
// fix lost priority
Player priorityPlayer = game.getPlayer(state.getPriorityPlayerId());
- sb.append("
Fixing priority player: " + getName(priorityPlayer));
+ sb.append("
Fixing priority player: ").append(getName(priorityPlayer));
if (priorityPlayer != null && !priorityPlayer.canRespond()) {
fixActions.add("priority player fix");
@@ -1334,19 +1334,19 @@ public class GameController implements GameCallback {
sb.append("
Try to concede...");
priorityPlayer.concede(game);
priorityPlayer.leave(); // abort any wait response actions
- sb.append(" (" + asWarning("OK") + ", concede done)");
+ sb.append(" (").append(asWarning("OK")).append(", concede done)");
sb.append("
Try to skip step...");
if (fixedAlready) {
- sb.append(" (" + asWarning("OK") + ", already skipped before)");
+ sb.append(" (").append(asWarning("OK")).append(", already skipped before)");
} else {
Phase currentPhase = game.getPhase();
if (currentPhase != null) {
currentPhase.getStep().skipStep(game, state.getActivePlayerId());
fixedAlready = true;
- sb.append(" (" + asWarning("OK") + ", skip step done)");
+ sb.append(" (").append(asWarning("OK")).append(", skip step done)");
} else {
- sb.append(" (" + asBad("FAIL") + ", step is null)");
+ sb.append(" (").append(asBad("FAIL")).append(", step is null)");
}
}
} else {
@@ -1356,10 +1356,10 @@ public class GameController implements GameCallback {
// fix timeout
sb.append("
Fixing future timeout: ");
if (futureTimeout != null) {
- sb.append("cancelled?=" + futureTimeout.isCancelled());
- sb.append("...done?=" + futureTimeout.isDone());
+ sb.append("cancelled?=").append(futureTimeout.isCancelled());
+ sb.append("...done?=").append(futureTimeout.isDone());
int delay = (int) futureTimeout.getDelay(TimeUnit.SECONDS);
- sb.append("...getDelay?=" + delay);
+ sb.append("...getDelay?=").append(delay);
if (delay < 25) {
fixActions.add("future timeout fix");
@@ -1367,12 +1367,12 @@ public class GameController implements GameCallback {
sb.append("
Try to pass...");
PassAbility pass = new PassAbility();
game.endTurn(pass);
- sb.append(" (" + asWarning("OK") + ", pass done)");
+ sb.append(" (").append(asWarning("OK")).append(", pass done)");
} else {
- sb.append(" (" + asGood("OK") + ", delay > 25)");
+ sb.append(" (").append(asGood("OK")).append(", delay > 25)");
}
} else {
- sb.append(" (" + asGood("OK") + ", timeout is not using)");
+ sb.append(" (").append(asGood("OK")).append(", timeout is not using)");
}
// TODO: fix non started game (send game started event to user?)
@@ -1382,7 +1382,7 @@ public class GameController implements GameCallback {
fixActions.add("none");
}
String appliedFixes = fixActions.stream().collect(Collectors.joining(", "));
- sb.append("
Applied fixes: " + appliedFixes);
+ sb.append("
Applied fixes: ").append(appliedFixes);
sb.append(""); // font resize end
sb.append("
");
diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java
index 58f8feb130c..dec5a49741f 100644
--- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java
+++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java
@@ -82,7 +82,7 @@ public final class SystemUtil {
}
private static final Pattern patternGroup = Pattern.compile("\\[(.+)\\]"); // [test new card]
- private static final Pattern patternCommand = Pattern.compile("([\\w]+):([\\S]+?):([\\S ]+):([\\d]+)"); // battlefield:Human:Island:10
+ private static final Pattern patternCommand = Pattern.compile("([\\w]+):([\\S ]+?):([\\S ]+):([\\d]+)"); // battlefield:Human:Island:10
private static final Pattern patternCardInfo = Pattern.compile("([\\S ]+):([\\S ]+)"); // Island:XLN
// show ext info for special commands
@@ -425,7 +425,7 @@ public final class SystemUtil {
game.firePriorityEvent(opponent.getId());
}
- List abilities = opponent.getPlayable(game, true);
+ List abilities = opponent.getPlayable(game, true);
Map choices = new HashMap<>();
abilities.forEach(ability -> {
MageObject object = ability.getSourceObject(game);
@@ -437,10 +437,10 @@ public final class SystemUtil {
choice.setKeyChoices(choices);
if (feedbackPlayer.choose(Outcome.Detriment, choice, game) && choice.getChoiceKey() != null) {
String needId = choice.getChoiceKey();
- Optional ability = abilities.stream().filter(a -> a.getId().toString().equals(needId)).findFirst();
+ Optional ability = abilities.stream().filter(a -> a.getId().toString().equals(needId)).findFirst();
if (ability.isPresent()) {
// TODO: set priority for player?
- ActivatedAbility activatedAbility = (ActivatedAbility) ability.get();
+ ActivatedAbility activatedAbility = ability.get();
game.informPlayers(feedbackPlayer.getLogName() + " as another player " + opponent.getLogName()
+ " trying to force an activate ability: " + activatedAbility.getGameLogMessage(game));
if (opponent.activateAbility(activatedAbility, game)) {
diff --git a/Mage.Sets/pom.xml b/Mage.Sets/pom.xml
index e6bb3dc4679..e80b1051b4f 100644
--- a/Mage.Sets/pom.xml
+++ b/Mage.Sets/pom.xml
@@ -7,7 +7,7 @@
org.mage
mage-root
- 1.4.42
+ 1.4.43
mage-sets
diff --git a/Mage.Sets/src/mage/cards/a/AbandonHope.java b/Mage.Sets/src/mage/cards/a/AbandonHope.java
index 635917a8982..3c3e6e538c9 100644
--- a/Mage.Sets/src/mage/cards/a/AbandonHope.java
+++ b/Mage.Sets/src/mage/cards/a/AbandonHope.java
@@ -1,4 +1,3 @@
-
package mage.cards.a;
import mage.abilities.Ability;
@@ -15,8 +14,8 @@ import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
-import mage.target.TargetPlayer;
import mage.target.common.TargetCardInHand;
+import mage.target.common.TargetOpponent;
import java.util.UUID;
@@ -29,18 +28,21 @@ public final class AbandonHope extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{1}{B}");
// As an additional cost to cast Abandon Hope, discard X cards.
- Ability ability = new SimpleStaticAbility(Zone.ALL, new InfoEffect("As an additional cost to cast this spell, discard X cards"));
+ Ability ability = new SimpleStaticAbility(
+ Zone.ALL, new InfoEffect("As an additional cost to cast this spell, discard X cards")
+ );
ability.setRuleAtTheTop(true);
this.addAbility(ability);
// Look at target opponent's hand and choose X cards from it. That player discards those cards.
- ManacostVariableValue manaX = ManacostVariableValue.instance;
- this.getSpellAbility().addEffect(new DiscardCardYouChooseTargetEffect(manaX, TargetController.ANY));
- this.getSpellAbility().addTarget(new TargetPlayer());
+ this.getSpellAbility().addEffect(
+ new DiscardCardYouChooseTargetEffect(ManacostVariableValue.instance, TargetController.ANY)
+ .setText("Look at target opponent's hand and choose X cards from it. That player discards those cards"));
+ this.getSpellAbility().addTarget(new TargetOpponent());
this.getSpellAbility().setCostAdjuster(AbandonHopeAdjuster.instance);
}
- public AbandonHope(final AbandonHope card) {
+ private AbandonHope(final AbandonHope card) {
super(card);
}
@@ -60,4 +62,4 @@ enum AbandonHopeAdjuster implements CostAdjuster {
ability.addCost(new DiscardTargetCost(new TargetCardInHand(xValue, xValue, StaticFilters.FILTER_CARD_CARDS)));
}
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/a/AberrantResearcher.java b/Mage.Sets/src/mage/cards/a/AberrantResearcher.java
index 54c1bd42d4d..c83c8588673 100644
--- a/Mage.Sets/src/mage/cards/a/AberrantResearcher.java
+++ b/Mage.Sets/src/mage/cards/a/AberrantResearcher.java
@@ -1,22 +1,22 @@
package mage.cards.a;
-import java.util.UUID;
-
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TransformAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
* @author fireshoes
*/
@@ -54,7 +54,7 @@ class AberrantResearcherEffect extends OneShotEffect {
public AberrantResearcherEffect() {
super(Outcome.Benefit);
- staticText = "put the top card of your library into your graveyard. If it's an instant or sorcery card, transform {this}";
+ staticText = "mill a card. If an instant or sorcery card was milled this way, transform {this}";
}
public AberrantResearcherEffect(final AberrantResearcherEffect effect) {
@@ -64,15 +64,16 @@ class AberrantResearcherEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null && controller.getLibrary().hasCards()) {
- Card card = controller.getLibrary().getFromTop(game);
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- if (card.isInstant() || card.isSorcery()) {
- new TransformSourceEffect(true).apply(game, source);
- }
- return true;
+ if (controller == null
+ || controller
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .noneMatch(MageObject::isInstantOrSorcery)) {
+ return false;
}
- return false;
+ new TransformSourceEffect(true).apply(game, source);
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/a/AbnormalEndurance.java b/Mage.Sets/src/mage/cards/a/AbnormalEndurance.java
index 847823acadc..1aa6c118264 100644
--- a/Mage.Sets/src/mage/cards/a/AbnormalEndurance.java
+++ b/Mage.Sets/src/mage/cards/a/AbnormalEndurance.java
@@ -1,7 +1,7 @@
package mage.cards.a;
import java.util.UUID;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
@@ -26,7 +26,7 @@ public final class AbnormalEndurance extends CardImpl {
.setText("Until end of turn, target creature gets +2/+0")
);
getSpellAbility().addEffect(new GainAbilityTargetEffect(
- new DiesTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect(true, true), false),
+ new DiesSourceTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect(true, true), false),
Duration.EndOfTurn,
"and gains \"When this creature dies, return it to the battlefield tapped under its owner's control.\""
));
diff --git a/Mage.Sets/src/mage/cards/a/Abolish.java b/Mage.Sets/src/mage/cards/a/Abolish.java
index 47d2170ba01..e619b5c4aed 100644
--- a/Mage.Sets/src/mage/cards/a/Abolish.java
+++ b/Mage.Sets/src/mage/cards/a/Abolish.java
@@ -1,4 +1,3 @@
-
package mage.cards.a;
import mage.abilities.costs.AlternativeCostSourceAbility;
@@ -16,7 +15,6 @@ import mage.target.common.TargetCardInHand;
import java.util.UUID;
/**
- *
* @author Backfir3
*/
public final class Abolish extends CardImpl {
@@ -28,8 +26,7 @@ public final class Abolish extends CardImpl {
}
public Abolish(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}{W}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}{W}");
// You may discard a Plains card rather than pay Abolish's mana cost.
this.addAbility(new AlternativeCostSourceAbility(new DiscardTargetCost(new TargetCardInHand(filterCost))));
diff --git a/Mage.Sets/src/mage/cards/a/Abomination.java b/Mage.Sets/src/mage/cards/a/Abomination.java
index 167f58ad8e5..e9b37fb3366 100644
--- a/Mage.Sets/src/mage/cards/a/Abomination.java
+++ b/Mage.Sets/src/mage/cards/a/Abomination.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -39,7 +39,7 @@ public final class Abomination extends CardImpl {
// Whenever Abomination blocks or becomes blocked by a green or white creature, destroy that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true);
effect.setText("destroy that creature at end of combat");
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, filter, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, filter, false));
}
public Abomination(final Abomination card) {
diff --git a/Mage.Sets/src/mage/cards/a/AbuJafar.java b/Mage.Sets/src/mage/cards/a/AbuJafar.java
index 1435c02087f..b83054c00e1 100644
--- a/Mage.Sets/src/mage/cards/a/AbuJafar.java
+++ b/Mage.Sets/src/mage/cards/a/AbuJafar.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -31,7 +31,7 @@ public final class AbuJafar extends CardImpl {
new BlockingAttackerIdPredicate(this.getId())));
// When Abu Ja'far dies, destroy all creatures blocking or blocked by it. They can't be regenerated.
- this.addAbility(new DiesTriggeredAbility(new DestroyAllEffect(filter, true), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DestroyAllEffect(filter, true), false));
}
public AbuJafar(final AbuJafar card) {
diff --git a/Mage.Sets/src/mage/cards/a/AbundantMaw.java b/Mage.Sets/src/mage/cards/a/AbundantMaw.java
index 3d558b74981..8892b9070cd 100644
--- a/Mage.Sets/src/mage/cards/a/AbundantMaw.java
+++ b/Mage.Sets/src/mage/cards/a/AbundantMaw.java
@@ -1,7 +1,5 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -15,14 +13,15 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public final class AbundantMaw extends CardImpl {
public AbundantMaw(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{8}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{8}");
this.subtype.add(SubType.ELDRAZI);
this.subtype.add(SubType.LEECH);
this.power = new MageInt(6);
@@ -30,11 +29,11 @@ public final class AbundantMaw extends CardImpl {
// Emerge {6}{B}
this.addAbility(new EmergeAbility(this, new ManaCostsImpl<>("{6}{B}")));
-
+
// When you cast Abundant Maw, target opponent loses 3 life and you gain 3 life.
Ability ability = new CastSourceTriggeredAbility(new GainLifeEffect(3));
+ ability.addEffect(new LoseLifeTargetEffect(3).concatBy("and"));
ability.addTarget(new TargetOpponent());
- ability.addEffect(new LoseLifeTargetEffect(3));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/a/AbyssalGatekeeper.java b/Mage.Sets/src/mage/cards/a/AbyssalGatekeeper.java
index cb8017787d4..2219dcb20ee 100644
--- a/Mage.Sets/src/mage/cards/a/AbyssalGatekeeper.java
+++ b/Mage.Sets/src/mage/cards/a/AbyssalGatekeeper.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.SacrificeAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class AbyssalGatekeeper extends CardImpl {
this.toughness = new MageInt(1);
// When Abyssal Gatekeeper dies, each player sacrifices a creature.
- this.addAbility(new DiesTriggeredAbility(new SacrificeAllEffect(1, new FilterControlledCreaturePermanent("creature"))));
+ this.addAbility(new DiesSourceTriggeredAbility(new SacrificeAllEffect(1, new FilterControlledCreaturePermanent("creature"))));
}
public AbyssalGatekeeper(final AbyssalGatekeeper card) {
diff --git a/Mage.Sets/src/mage/cards/a/AbzanAscendancy.java b/Mage.Sets/src/mage/cards/a/AbzanAscendancy.java
index 558cfe42418..ffea394e3d3 100644
--- a/Mage.Sets/src/mage/cards/a/AbzanAscendancy.java
+++ b/Mage.Sets/src/mage/cards/a/AbzanAscendancy.java
@@ -1,7 +1,5 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -17,8 +15,9 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.permanent.token.SpiritWhiteToken;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class AbzanAscendancy extends CardImpl {
@@ -37,7 +36,7 @@ public final class AbzanAscendancy extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new AddCountersAllEffect(CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE), false));
// Whenever a nontoken creature you control dies, create a 1/1 white Spirit creature token with flying.
- this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken("KTK")), false, filter));
+ this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken()), false, filter));
}
diff --git a/Mage.Sets/src/mage/cards/a/AbzanBeastmaster.java b/Mage.Sets/src/mage/cards/a/AbzanBeastmaster.java
index e0503095188..76707204e81 100644
--- a/Mage.Sets/src/mage/cards/a/AbzanBeastmaster.java
+++ b/Mage.Sets/src/mage/cards/a/AbzanBeastmaster.java
@@ -21,7 +21,7 @@ public final class AbzanBeastmaster extends CardImpl {
public AbzanBeastmaster(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/a/AbzanSkycaptain.java b/Mage.Sets/src/mage/cards/a/AbzanSkycaptain.java
index 72dd6ba0110..50faba04dbd 100644
--- a/Mage.Sets/src/mage/cards/a/AbzanSkycaptain.java
+++ b/Mage.Sets/src/mage/cards/a/AbzanSkycaptain.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.keyword.BolsterEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class AbzanSkycaptain extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Abzan Captain dies, bolster 2.
- this.addAbility(new DiesTriggeredAbility(new BolsterEffect(2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new BolsterEffect(2)));
}
public AbzanSkycaptain(final AbzanSkycaptain card) {
diff --git a/Mage.Sets/src/mage/cards/a/AcademyJourneymage.java b/Mage.Sets/src/mage/cards/a/AcademyJourneymage.java
index cb65e5f8f57..7036d80a8ff 100644
--- a/Mage.Sets/src/mage/cards/a/AcademyJourneymage.java
+++ b/Mage.Sets/src/mage/cards/a/AcademyJourneymage.java
@@ -1,25 +1,26 @@
-
package mage.cards.a;
-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.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
-import mage.constants.SubType;
+import mage.abilities.hint.ConditionHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author JRHerlehy
*/
public final class AcademyJourneymage extends CardImpl {
@@ -32,14 +33,16 @@ public final class AcademyJourneymage extends CardImpl {
public AcademyJourneymage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}");
-
+
this.subtype.add(SubType.HUMAN, SubType.WIZARD);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// This spell costs {1} less to cast if you control a Wizard.
- Ability ability = new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(1, new PermanentsOnTheBattlefieldCondition(filter)));
+ Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(1, condition));
ability.setRuleAtTheTop(true);
+ ability.addHint(new ConditionHint(condition, "You control a Wizard"));
this.addAbility(ability);
// When Academy Journeymage enters the battlefield, return target creature an opponent controls to its owner's hand.
diff --git a/Mage.Sets/src/mage/cards/a/AcademyRector.java b/Mage.Sets/src/mage/cards/a/AcademyRector.java
index e20df2f5ed9..2c519616d39 100644
--- a/Mage.Sets/src/mage/cards/a/AcademyRector.java
+++ b/Mage.Sets/src/mage/cards/a/AcademyRector.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
@@ -29,7 +29,7 @@ public final class AcademyRector extends CardImpl {
this.toughness = new MageInt(2);
// When Academy Rector dies, you may exile it. If you do, search your library for an enchantment card, put that card onto the battlefield, then shuffle your library.
- this.addAbility(new DiesTriggeredAbility(
+ this.addAbility(new DiesSourceTriggeredAbility(
new DoIfCostPaid(
new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(new FilterEnchantmentCard())),
new ExileSourceFromGraveCost(),
diff --git a/Mage.Sets/src/mage/cards/a/AccursedWitch.java b/Mage.Sets/src/mage/cards/a/AccursedWitch.java
index bcde8821e6b..0bc6e8d72a2 100644
--- a/Mage.Sets/src/mage/cards/a/AccursedWitch.java
+++ b/Mage.Sets/src/mage/cards/a/AccursedWitch.java
@@ -1,25 +1,20 @@
-
package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.SpellAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
+import mage.filter.FilterCard;
import mage.game.Game;
-import mage.game.permanent.Permanent;
import mage.players.Player;
-import mage.target.Target;
import mage.target.common.TargetOpponent;
-import mage.util.CardUtil;
import java.util.UUID;
@@ -39,10 +34,13 @@ public final class AccursedWitch extends CardImpl {
this.secondSideCardClazz = mage.cards.i.InfectiousCurse.class;
// Spells your opponents cast that target Accursed Witch cost {1} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AccursedWitchSpellsCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(-1, new FilterCard("Spells"), TargetController.OPPONENT))
+ );
+
// When Accursed Witch dies, return it to the battlefield transformed under your control attached to target opponent.
this.addAbility(new TransformAbility());
- Ability ability = new DiesTriggeredAbility(new AccursedWitchReturnTransformedEffect());
+ Ability ability = new DiesSourceTriggeredAbility(new AccursedWitchReturnTransformedEffect());
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
@@ -93,45 +91,3 @@ class AccursedWitchReturnTransformedEffect extends OneShotEffect {
return true;
}
}
-
-class AccursedWitchSpellsCostReductionEffect extends CostModificationEffectImpl {
-
- AccursedWitchSpellsCostReductionEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Detriment, CostModificationType.REDUCE_COST);
- this.staticText = "Spells your opponents cast that target {this} cost {1} less to cast.";
- }
-
- private AccursedWitchSpellsCostReductionEffect(AccursedWitchSpellsCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- CardUtil.reduceCost(abilityToModify, 1);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (!(abilityToModify instanceof SpellAbility) || !game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- return false;
- }
- for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
- Mode mode = abilityToModify.getModes().get(modeId);
- for (Target target : mode.getTargets()) {
- for (UUID targetUUID : target.getTargets()) {
- Permanent permanent = game.getPermanent(targetUUID);
- if (permanent != null && permanent.getId().equals(source.getSourceId())) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- @Override
- public AccursedWitchSpellsCostReductionEffect copy() {
- return new AccursedWitchSpellsCostReductionEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/a/AcolyteOfAffliction.java b/Mage.Sets/src/mage/cards/a/AcolyteOfAffliction.java
index 3a158f77787..58791c6deb2 100644
--- a/Mage.Sets/src/mage/cards/a/AcolyteOfAffliction.java
+++ b/Mage.Sets/src/mage/cards/a/AcolyteOfAffliction.java
@@ -53,8 +53,7 @@ class AcolyteOfAfflictionEffect extends OneShotEffect {
AcolyteOfAfflictionEffect() {
super(Outcome.Benefit);
- staticText = "put the top two cards of your library into your graveyard, " +
- "then you may return a permanent card from your graveyard to your hand.";
+ staticText = "mill two cards, then you may return a permanent card from your graveyard to your hand.";
}
private AcolyteOfAfflictionEffect(final AcolyteOfAfflictionEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/a/ActOnImpulse.java b/Mage.Sets/src/mage/cards/a/ActOnImpulse.java
index a2f44ab166f..0f7dfa3ff87 100644
--- a/Mage.Sets/src/mage/cards/a/ActOnImpulse.java
+++ b/Mage.Sets/src/mage/cards/a/ActOnImpulse.java
@@ -1,20 +1,11 @@
package mage.cards.a;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
-import mage.MageObject;
-import mage.abilities.Ability;
-import mage.abilities.effects.ContinuousEffect;
-import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
-import mage.cards.Card;
+import mage.abilities.effects.common.ExileTop3MayPlayUntilEndOfTurnEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.players.Player;
-import mage.target.targetpointer.FixedTargets;
+import mage.constants.CardType;
+
+import java.util.UUID;
/**
*
@@ -26,7 +17,7 @@ public final class ActOnImpulse extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
// Exile the top three cards of your library. Until end of turn, you may play cards exiled this way.
- this.getSpellAbility().addEffect(new ActOnImpulseExileEffect());
+ this.getSpellAbility().addEffect(new ExileTop3MayPlayUntilEndOfTurnEffect());
}
public ActOnImpulse(final ActOnImpulse card) {
@@ -39,45 +30,3 @@ public final class ActOnImpulse extends CardImpl {
}
}
-class ActOnImpulseExileEffect extends OneShotEffect {
-
- public ActOnImpulseExileEffect() {
- super(Outcome.Benefit);
- this.staticText = "Exile the top three cards of your library. Until end of turn, you may play cards exiled this way";
- }
-
- public ActOnImpulseExileEffect(final ActOnImpulseExileEffect effect) {
- super(effect);
- }
-
- @Override
- public ActOnImpulseExileEffect copy() {
- return new ActOnImpulseExileEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- MageObject sourceObject = game.getObject(source.getSourceId());
- if (controller != null && sourceObject != null) {
- Set cards = new HashSet<>(controller.getLibrary().getTopCards(game, 3));
- if (!cards.isEmpty()) {
- controller.moveCardsToExile(cards, source, game, true, source.getSourceId(), sourceObject.getIdName());
- // remove cards that could not be moved to exile
- for (Card card : cards) {
- if (!Zone.EXILED.equals(game.getState().getZone(card.getId()))) {
- cards.remove(card);
- }
- }
- if (!cards.isEmpty()) {
- ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
- effect.setTargetPointer(new FixedTargets(cards, game));
- game.addEffect(effect, source);
- }
- }
- return true;
- }
- return false;
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/a/AdherentOfHope.java b/Mage.Sets/src/mage/cards/a/AdherentOfHope.java
new file mode 100644
index 00000000000..be05c2aaaf5
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/AdherentOfHope.java
@@ -0,0 +1,54 @@
+package mage.cards.a;
+
+import mage.MageInt;
+import mage.abilities.common.BeginningOfCombatTriggeredAbility;
+import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.counter.AddCountersSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.counters.CounterType;
+import mage.filter.common.FilterControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class AdherentOfHope extends CardImpl {
+
+ private static final FilterControlledPermanent filter = new FilterControlledPermanent();
+
+ static {
+ filter.add(CardType.PLANESWALKER.getPredicate());
+ filter.add(SubType.BASRI.getPredicate());
+ }
+
+ public AdherentOfHope(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.SOLDIER);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // At the beginning of combat on your turn, if you control a Basri planeswalker, put a +1/+1 counter on Adherent of Hope.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfCombatTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), TargetController.YOU, false),
+ new PermanentsOnTheBattlefieldCondition(filter),
+ "At the beginning of combat on your turn, if you control a Basri planeswalker, put a +1/+1 counter on {this}."));
+ }
+
+ private AdherentOfHope(final AdherentOfHope card) {
+ super(card);
+ }
+
+ @Override
+ public AdherentOfHope copy() {
+ return new AdherentOfHope(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/a/AdventOfTheWurm.java b/Mage.Sets/src/mage/cards/a/AdventOfTheWurm.java
index e00ee2edd2f..88295ecad2c 100644
--- a/Mage.Sets/src/mage/cards/a/AdventOfTheWurm.java
+++ b/Mage.Sets/src/mage/cards/a/AdventOfTheWurm.java
@@ -1,16 +1,14 @@
-
-
package mage.cards.a;
-import java.util.UUID;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.game.permanent.token.WurmToken2;
+import mage.game.permanent.token.WurmWithTrampleToken;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
@@ -18,10 +16,10 @@ import mage.game.permanent.token.WurmToken2;
public final class AdventOfTheWurm extends CardImpl {
public AdventOfTheWurm(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}{G}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}{G}{W}");
// Create a 5/5 green Wurm creature token with trample.
- this.getSpellAbility().addEffect(new CreateTokenEffect(new WurmToken2()));
+ this.getSpellAbility().addEffect(new CreateTokenEffect(new WurmWithTrampleToken()));
}
public AdventOfTheWurm(final AdventOfTheWurm card) {
diff --git a/Mage.Sets/src/mage/cards/a/AegisAngel.java b/Mage.Sets/src/mage/cards/a/AegisAngel.java
index 7222995d67c..bef99e72eaa 100644
--- a/Mage.Sets/src/mage/cards/a/AegisAngel.java
+++ b/Mage.Sets/src/mage/cards/a/AegisAngel.java
@@ -1,4 +1,3 @@
-
package mage.cards.a;
import java.util.UUID;
@@ -18,6 +17,7 @@ import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.target.TargetPermanent;
+import mage.watchers.common.LostControlWatcher;
/**
* @author Loki
@@ -47,6 +47,7 @@ public final class AegisAngel extends CardImpl {
"another target permanent is indestructible for as long as you control Aegis Angel");
Ability ability = new EntersBattlefieldTriggeredAbility(effect, false);
ability.addTarget(new TargetPermanent(filter));
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/a/AerieBowmasters.java b/Mage.Sets/src/mage/cards/a/AerieBowmasters.java
index 8d4f11ce502..baac41ba679 100644
--- a/Mage.Sets/src/mage/cards/a/AerieBowmasters.java
+++ b/Mage.Sets/src/mage/cards/a/AerieBowmasters.java
@@ -19,7 +19,7 @@ public final class AerieBowmasters extends CardImpl {
public AerieBowmasters(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.ARCHER);
this.power = new MageInt(3);
this.toughness = new MageInt(4);
diff --git a/Mage.Sets/src/mage/cards/a/AetherStorm.java b/Mage.Sets/src/mage/cards/a/AetherStorm.java
index a2298fa7be1..3bc436ae309 100644
--- a/Mage.Sets/src/mage/cards/a/AetherStorm.java
+++ b/Mage.Sets/src/mage/cards/a/AetherStorm.java
@@ -50,7 +50,7 @@ class AetherStormReplacementEffect extends ContinuousRuleModifyingEffectImpl {
public AetherStormReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
- staticText = "Creature spells can't be cast.";
+ staticText = "Creature spells can't be cast";
}
private AetherStormReplacementEffect(final AetherStormReplacementEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/a/AetherstormRoc.java b/Mage.Sets/src/mage/cards/a/AetherstormRoc.java
index aff1bf10b00..a476bfef1a1 100644
--- a/Mage.Sets/src/mage/cards/a/AetherstormRoc.java
+++ b/Mage.Sets/src/mage/cards/a/AetherstormRoc.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.costs.common.PayEnergyCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.TapTargetEffect;
@@ -16,11 +16,11 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
+import mage.filter.FilterPermanent;
+import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
-import mage.filter.predicate.permanent.ControllerIdPredicate;
-import mage.game.Game;
-import mage.target.common.TargetCreaturePermanent;
-import mage.target.targetadjustment.TargetAdjuster;
+import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate;
+import mage.target.TargetPermanent;
import java.util.UUID;
@@ -29,6 +29,13 @@ import java.util.UUID;
*/
public final class AetherstormRoc extends CardImpl {
+ private static final FilterPermanent filter
+ = new FilterCreaturePermanent("creature defending player controls");
+
+ static {
+ filter.add(DefendingPlayerControlsPredicate.instance);
+ }
+
public AetherstormRoc(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
this.subtype.add(SubType.BIRD);
@@ -37,21 +44,24 @@ public final class AetherstormRoc extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
+
// Whenever Aetherstorm Roc or another creature enters the battlefield under your control, you get {E}.
- this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new GetEnergyCountersControllerEffect(1), new FilterCreaturePermanent("{this} or another creature")));
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new GetEnergyCountersControllerEffect(1),
+ StaticFilters.FILTER_PERMANENT_CREATURE, false, true
+ ));
// Whenever Aetherstorm Roc attacks, you may pay {E}{E}. If you do, put a +1/+1 counter on it and tap up to one target creature defending player controls.
- DoIfCostPaid doIfCostPaidEffect = new DoIfCostPaid(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new PayEnergyCost(2));
- doIfCostPaidEffect.addEffect(new TapTargetEffect());
- Ability ability = new AttacksTriggeredAbility(doIfCostPaidEffect, false,
- "Whenever {this} attacks you may pay {E}{E}. If you do, put a +1/+1 counter on it and tap up to one target creature defending player controls.");
- ability.addTarget(new TargetCreaturePermanent(0, 1, new FilterCreaturePermanent("creature defending player controls"), false));
- ability.setTargetAdjuster(AetherstormRocAdjuster.instance);
+ Ability ability = new AttacksTriggeredAbility(new DoIfCostPaid(
+ new AddCountersSourceEffect(CounterType.P1P1.createInstance())
+ .setText("put a +1/+1 counter on it"),
+ new PayEnergyCost(2)
+ ).addEffect(new TapTargetEffect().concatBy("and")), false);
+ ability.addTarget(new TargetPermanent(0, 1, filter, false));
this.addAbility(ability);
-
}
- public AetherstormRoc(final AetherstormRoc card) {
+ private AetherstormRoc(final AetherstormRoc card) {
super(card);
}
@@ -61,17 +71,3 @@ public final class AetherstormRoc extends CardImpl {
return new AetherstormRoc(this);
}
}
-
-enum AetherstormRocAdjuster implements TargetAdjuster {
- instance;
-
- @Override
- public void adjustTargets(Ability ability, Game game) {
- ability.getTargets().clear();
- FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls");
- UUID defenderId = game.getCombat().getDefenderId(ability.getSourceId());
- filter.add(new ControllerIdPredicate(defenderId));
- TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false);
- ability.addTarget(target);
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/a/Aethertow.java b/Mage.Sets/src/mage/cards/a/Aethertow.java
index d2c060a9bba..4922cb71427 100644
--- a/Mage.Sets/src/mage/cards/a/Aethertow.java
+++ b/Mage.Sets/src/mage/cards/a/Aethertow.java
@@ -7,12 +7,14 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.ConspireAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterAttackingOrBlockingCreature;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
/**
@@ -58,9 +60,9 @@ class AethertowEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent targetCreature = game.getPermanent(targetPointer.getFirst(game, source));
+ Player controller = game.getPlayer(source.getControllerId());
if (targetCreature != null) {
- targetCreature.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- return true;
+ return controller.putCardsOnTopOfLibrary(targetCreature, game, source, true);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/a/AetherwindBasker.java b/Mage.Sets/src/mage/cards/a/AetherwindBasker.java
index e2bc62492da..3ca50e87661 100644
--- a/Mage.Sets/src/mage/cards/a/AetherwindBasker.java
+++ b/Mage.Sets/src/mage/cards/a/AetherwindBasker.java
@@ -17,7 +17,6 @@ import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
-import mage.filter.common.FilterControlledCreaturePermanent;
/**
*
diff --git a/Mage.Sets/src/mage/cards/a/AffaGuardHound.java b/Mage.Sets/src/mage/cards/a/AffaGuardHound.java
index a5415096b09..419bf0c33ed 100644
--- a/Mage.Sets/src/mage/cards/a/AffaGuardHound.java
+++ b/Mage.Sets/src/mage/cards/a/AffaGuardHound.java
@@ -23,7 +23,7 @@ public final class AffaGuardHound extends CardImpl {
public AffaGuardHound (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/a/AinokArtillerist.java b/Mage.Sets/src/mage/cards/a/AinokArtillerist.java
index 589990f025b..ffb54011776 100644
--- a/Mage.Sets/src/mage/cards/a/AinokArtillerist.java
+++ b/Mage.Sets/src/mage/cards/a/AinokArtillerist.java
@@ -23,7 +23,7 @@ public final class AinokArtillerist extends CardImpl {
public AinokArtillerist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.ARCHER);
this.power = new MageInt(4);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/a/AinokBondKin.java b/Mage.Sets/src/mage/cards/a/AinokBondKin.java
index ccec3c06fcf..5c0aea14cf2 100644
--- a/Mage.Sets/src/mage/cards/a/AinokBondKin.java
+++ b/Mage.Sets/src/mage/cards/a/AinokBondKin.java
@@ -33,7 +33,7 @@ public final class AinokBondKin extends CardImpl {
public AinokBondKin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SOLDIER);
this.power = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/a/AinokGuide.java b/Mage.Sets/src/mage/cards/a/AinokGuide.java
index 2136d4f9769..b59cd42b1b7 100644
--- a/Mage.Sets/src/mage/cards/a/AinokGuide.java
+++ b/Mage.Sets/src/mage/cards/a/AinokGuide.java
@@ -25,7 +25,7 @@ public final class AinokGuide extends CardImpl {
public AinokGuide(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/a/AinokSurvivalist.java b/Mage.Sets/src/mage/cards/a/AinokSurvivalist.java
index 0a406fc3434..aa812a835d7 100644
--- a/Mage.Sets/src/mage/cards/a/AinokSurvivalist.java
+++ b/Mage.Sets/src/mage/cards/a/AinokSurvivalist.java
@@ -31,7 +31,7 @@ public final class AinokSurvivalist extends CardImpl {
public AinokSurvivalist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/a/AinokTracker.java b/Mage.Sets/src/mage/cards/a/AinokTracker.java
index 1c3d8b14754..c4909ef07ef 100644
--- a/Mage.Sets/src/mage/cards/a/AinokTracker.java
+++ b/Mage.Sets/src/mage/cards/a/AinokTracker.java
@@ -19,7 +19,7 @@ public final class AinokTracker extends CardImpl {
public AinokTracker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/a/AislingLeprechaun.java b/Mage.Sets/src/mage/cards/a/AislingLeprechaun.java
index 94dc8009757..b1bee8438df 100644
--- a/Mage.Sets/src/mage/cards/a/AislingLeprechaun.java
+++ b/Mage.Sets/src/mage/cards/a/AislingLeprechaun.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BecomesColorTargetEffect;
import mage.cards.CardImpl;
@@ -29,7 +29,7 @@ public final class AislingLeprechaun extends CardImpl {
// Whenever Aisling Leprechaun blocks or becomes blocked by a creature, that creature becomes green.
Effect effect = new BecomesColorTargetEffect(ObjectColor.GREEN, Duration.EndOfGame);
effect.setText("that creature becomes green");
- Ability ability = new BlocksOrBecomesBlockedTriggeredAbility(effect, false);
+ Ability ability = new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, false);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/a/AkiriLineSlinger.java b/Mage.Sets/src/mage/cards/a/AkiriLineSlinger.java
index 5cd997b7e0e..507e6796b02 100644
--- a/Mage.Sets/src/mage/cards/a/AkiriLineSlinger.java
+++ b/Mage.Sets/src/mage/cards/a/AkiriLineSlinger.java
@@ -1,36 +1,29 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.PartnerAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
-import mage.filter.common.FilterControlledPermanent;
+
+import java.util.UUID;
/**
- *
* @author spjspj
*/
public final class AkiriLineSlinger extends CardImpl {
- private static final FilterControlledPermanent filter = new FilterControlledPermanent("artifact you control");
-
- static {
- filter.add(CardType.ARTIFACT.getPredicate());
- }
-
public AkiriLineSlinger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}");
-
+
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.KOR);
this.subtype.add(SubType.SOLDIER);
@@ -45,9 +38,10 @@ public final class AkiriLineSlinger extends CardImpl {
this.addAbility(VigilanceAbility.getInstance());
// Akiri, Line-Slinger gets +1/+0 for each artifact you control.
- Effect effect = new BoostSourceEffect(new PermanentsOnBattlefieldCount(filter), StaticValue.get(0), Duration.WhileOnBattlefield);
+ Effect effect = new BoostSourceEffect(ArtifactYouControlCount.instance, StaticValue.get(0), Duration.WhileOnBattlefield);
effect.setText("{this} gets +1/+0 for each artifact you control");
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)
+ .addHint(ArtifactYouControlHint.instance));
// Partner
this.addAbility(PartnerAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/a/AkkiBlizzardHerder.java b/Mage.Sets/src/mage/cards/a/AkkiBlizzardHerder.java
index 41eb809c1d3..03a30612529 100644
--- a/Mage.Sets/src/mage/cards/a/AkkiBlizzardHerder.java
+++ b/Mage.Sets/src/mage/cards/a/AkkiBlizzardHerder.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.SacrificeAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -29,7 +29,7 @@ public final class AkkiBlizzardHerder extends CardImpl {
this.toughness = new MageInt(1);
// When Akki Blizzard-Herder dies, each player sacrifices a land.
- this.addAbility(new DiesTriggeredAbility(new SacrificeAllEffect(filter)));
+ this.addAbility(new DiesSourceTriggeredAbility(new SacrificeAllEffect(filter)));
}
public AkkiBlizzardHerder(final AkkiBlizzardHerder card) {
diff --git a/Mage.Sets/src/mage/cards/a/AkroanMastiff.java b/Mage.Sets/src/mage/cards/a/AkroanMastiff.java
index f1e385cde98..7b61b400b2e 100644
--- a/Mage.Sets/src/mage/cards/a/AkroanMastiff.java
+++ b/Mage.Sets/src/mage/cards/a/AkroanMastiff.java
@@ -23,7 +23,7 @@ public final class AkroanMastiff extends CardImpl {
public AkroanMastiff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/a/AkromaAngelOfFury.java b/Mage.Sets/src/mage/cards/a/AkromaAngelOfFury.java
index 6e65dda3ce4..42aaaa5096b 100644
--- a/Mage.Sets/src/mage/cards/a/AkromaAngelOfFury.java
+++ b/Mage.Sets/src/mage/cards/a/AkromaAngelOfFury.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
@@ -31,7 +31,7 @@ public final class AkromaAngelOfFury extends CardImpl {
this.toughness = new MageInt(6);
// Akroma, Angel of Fury can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Flying
this.addAbility(FlyingAbility.getInstance());
// Trample
diff --git a/Mage.Sets/src/mage/cards/a/AlabasterDragon.java b/Mage.Sets/src/mage/cards/a/AlabasterDragon.java
index 49843f304a9..62fbda2d27f 100644
--- a/Mage.Sets/src/mage/cards/a/AlabasterDragon.java
+++ b/Mage.Sets/src/mage/cards/a/AlabasterDragon.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -26,7 +26,7 @@ public final class AlabasterDragon extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Alabaster Dragon dies, shuffle it into its owner's library.
- this.addAbility(new DiesTriggeredAbility(new ShuffleIntoLibrarySourceEffect())); }
+ this.addAbility(new DiesSourceTriggeredAbility(new ShuffleIntoLibrarySourceEffect())); }
public AlabasterDragon(final AlabasterDragon card) {
super(card);
diff --git a/Mage.Sets/src/mage/cards/a/AlabasterLeech.java b/Mage.Sets/src/mage/cards/a/AlabasterLeech.java
index 63e2ad4d6a2..cfdf0d916e9 100644
--- a/Mage.Sets/src/mage/cards/a/AlabasterLeech.java
+++ b/Mage.Sets/src/mage/cards/a/AlabasterLeech.java
@@ -1,22 +1,22 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementControllerEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author LoneFox
*/
public final class AlabasterLeech extends CardImpl {
@@ -28,14 +28,14 @@ public final class AlabasterLeech extends CardImpl {
}
public AlabasterLeech(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.LEECH);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// White spells you cast cost {W} more to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
- new SpellsCostIncreasementControllerEffect(filter, new ManaCostsImpl("{W}"))));
+ new SpellsCostIncreasingAllEffect(new ManaCostsImpl("{W}"), filter, TargetController.YOU)));
}
public AlabasterLeech(final AlabasterLeech card) {
diff --git a/Mage.Sets/src/mage/cards/a/Aladdin.java b/Mage.Sets/src/mage/cards/a/Aladdin.java
index 74564226216..58b44e3ae82 100644
--- a/Mage.Sets/src/mage/cards/a/Aladdin.java
+++ b/Mage.Sets/src/mage/cards/a/Aladdin.java
@@ -1,4 +1,3 @@
-
package mage.cards.a;
import java.util.UUID;
@@ -17,6 +16,7 @@ import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.target.common.TargetArtifactPermanent;
+import mage.watchers.common.LostControlWatcher;
/**
*
@@ -25,7 +25,7 @@ import mage.target.common.TargetArtifactPermanent;
public final class Aladdin extends CardImpl {
public Aladdin(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ROGUE);
this.power = new MageInt(1);
@@ -39,6 +39,7 @@ public final class Aladdin extends CardImpl {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{R}{R}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetArtifactPermanent());
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/a/AladdinsLamp.java b/Mage.Sets/src/mage/cards/a/AladdinsLamp.java
index e020079b682..5fb6e9b43cb 100644
--- a/Mage.Sets/src/mage/cards/a/AladdinsLamp.java
+++ b/Mage.Sets/src/mage/cards/a/AladdinsLamp.java
@@ -74,7 +74,7 @@ class AladdinsLampEffect extends ReplacementEffectImpl {
cards.remove(target.getFirstTarget());
}
controller.putCardsOnBottomOfLibrary(cards, game, source, false);
- game.applyEffects();
+ game.getState().processAction(game);
controller.drawCards(1, event.getSourceId(), game, event.getAppliedEffects());
discard();
return true;
diff --git a/Mage.Sets/src/mage/cards/a/AlchemistsGift.java b/Mage.Sets/src/mage/cards/a/AlchemistsGift.java
new file mode 100644
index 00000000000..0c3ee91bcf1
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/AlchemistsGift.java
@@ -0,0 +1,73 @@
+package mage.cards.a;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.keyword.DeathtouchAbility;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class AlchemistsGift extends CardImpl {
+
+ public AlchemistsGift(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
+
+ // Target creature gets +1/+1 and gains your choice of deathtouch or lifelink until end of turn.
+ this.getSpellAbility().addEffect(new AlchemistsGiftEffect());
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent());
+ }
+
+ private AlchemistsGift(final AlchemistsGift card) {
+ super(card);
+ }
+
+ @Override
+ public AlchemistsGift copy() {
+ return new AlchemistsGift(this);
+ }
+}
+
+class AlchemistsGiftEffect extends OneShotEffect {
+
+ AlchemistsGiftEffect() {
+ super(Outcome.Benefit);
+ staticText = "Target creature gets +1/+1 and gains your choice of deathtouch or lifelink until end of turn.";
+ }
+
+ private AlchemistsGiftEffect(final AlchemistsGiftEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public AlchemistsGiftEffect copy() {
+ return new AlchemistsGiftEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null) {
+ return false;
+ }
+ Ability ability = player.chooseUse(
+ outcome, "Deathtouch or lifelink?", null,
+ "Deathtouch", "Lifelink", source, game
+ ) ? DeathtouchAbility.getInstance() : LifelinkAbility.getInstance();
+ game.addEffect(new BoostTargetEffect(1, 1, Duration.EndOfTurn), source);
+ game.addEffect(new GainAbilityTargetEffect(ability, Duration.EndOfTurn), source);
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/a/AlexiZephyrMage.java b/Mage.Sets/src/mage/cards/a/AlexiZephyrMage.java
index 3d9f281655f..05df4833271 100644
--- a/Mage.Sets/src/mage/cards/a/AlexiZephyrMage.java
+++ b/Mage.Sets/src/mage/cards/a/AlexiZephyrMage.java
@@ -7,6 +7,7 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -35,7 +36,9 @@ public final class AlexiZephyrMage extends CardImpl {
this.toughness = new MageInt(3);
// {X}{U}, {tap}, Discard two cards: Return X target creatures to their owners' hands.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl("{X}{U}"));
+ Effect effect = new ReturnToHandTargetEffect();
+ effect.setText("Return X target creatures to their owner's hands");
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{X}{U}"));
ability.addCost(new TapSourceCost());
ability.addCost(new DiscardTargetCost(new TargetCardInHand(2, new FilterCard("two cards"))));
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_CREATURES));
diff --git a/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java b/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java
index 383d20fc2c0..b410035bf33 100644
--- a/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java
+++ b/Mage.Sets/src/mage/cards/a/AlhammarretsArchive.java
@@ -1,7 +1,5 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
@@ -13,14 +11,15 @@ import mage.game.events.GameEvent;
import mage.players.Player;
import mage.watchers.common.CardsDrawnDuringDrawStepWatcher;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class AlhammarretsArchive extends CardImpl {
public AlhammarretsArchive(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
addSuperType(SuperType.LEGENDARY);
// If you would gain life, you gain twice that much life instead.
@@ -30,7 +29,7 @@ public final class AlhammarretsArchive extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AlhammarretsArchiveReplacementEffect()), new CardsDrawnDuringDrawStepWatcher());
}
- public AlhammarretsArchive(final AlhammarretsArchive card) {
+ private AlhammarretsArchive(final AlhammarretsArchive card) {
super(card);
}
@@ -42,12 +41,12 @@ public final class AlhammarretsArchive extends CardImpl {
class AlhammarretsArchiveEffect extends ReplacementEffectImpl {
- public AlhammarretsArchiveEffect() {
+ AlhammarretsArchiveEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "If you would gain life, you gain twice that much life instead";
}
- public AlhammarretsArchiveEffect(final AlhammarretsArchiveEffect effect) {
+ private AlhammarretsArchiveEffect(final AlhammarretsArchiveEffect effect) {
super(effect);
}
@@ -75,12 +74,12 @@ class AlhammarretsArchiveEffect extends ReplacementEffectImpl {
class AlhammarretsArchiveReplacementEffect extends ReplacementEffectImpl {
- public AlhammarretsArchiveReplacementEffect() {
+ AlhammarretsArchiveReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
staticText = "If you draw a card except the first one you draw in each of your draw steps, draw two cards instead";
}
- public AlhammarretsArchiveReplacementEffect(final AlhammarretsArchiveReplacementEffect effect) {
+ private AlhammarretsArchiveReplacementEffect(final AlhammarretsArchiveReplacementEffect effect) {
super(effect);
}
@@ -110,17 +109,14 @@ class AlhammarretsArchiveReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
- if (event.getPlayerId().equals(source.getControllerId())) {
- if (game.isActivePlayer(event.getPlayerId())
- && game.getPhase().getStep().getType() == PhaseStep.DRAW) {
- CardsDrawnDuringDrawStepWatcher watcher = game.getState().getWatcher(CardsDrawnDuringDrawStepWatcher.class);
- if (watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) > 0) {
- return true;
- }
- } else {
- return true;
- }
+ if (!event.getPlayerId().equals(source.getControllerId())) {
+ return false;
}
- return false;
+ if (!game.isActivePlayer(event.getPlayerId())
+ || game.getPhase().getStep().getType() != PhaseStep.DRAW) {
+ return true;
+ }
+ CardsDrawnDuringDrawStepWatcher watcher = game.getState().getWatcher(CardsDrawnDuringDrawStepWatcher.class);
+ return watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) > 0;
}
}
diff --git a/Mage.Sets/src/mage/cards/a/AlleyGrifters.java b/Mage.Sets/src/mage/cards/a/AlleyGrifters.java
index 88483704b92..bb0bbe0f547 100644
--- a/Mage.Sets/src/mage/cards/a/AlleyGrifters.java
+++ b/Mage.Sets/src/mage/cards/a/AlleyGrifters.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -29,7 +29,7 @@ public final class AlleyGrifters extends CardImpl {
this.toughness = new MageInt(2);
// Whenever Alley Grifters becomes blocked, defending player discards a card.
- this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(new AlleyGriftersDiscardEffect(), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new AlleyGriftersDiscardEffect(), false));
}
public AlleyGrifters(final AlleyGrifters card) {
diff --git a/Mage.Sets/src/mage/cards/a/AllosaurusShepherd.java b/Mage.Sets/src/mage/cards/a/AllosaurusShepherd.java
new file mode 100644
index 00000000000..dc32fd4fd62
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/AllosaurusShepherd.java
@@ -0,0 +1,69 @@
+package mage.cards.a;
+
+import mage.MageInt;
+import mage.ObjectColor;
+import mage.abilities.Ability;
+import mage.abilities.common.CantBeCounteredSourceAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.CantBeCounteredControlledEffect;
+import mage.abilities.effects.common.continuous.CreaturesBecomeOtherTypeEffect;
+import mage.abilities.effects.common.continuous.SetPowerToughnessAllEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.mageobject.ColorPredicate;
+
+import java.util.UUID;
+import mage.filter.FilterSpell;
+
+public class AllosaurusShepherd extends CardImpl {
+
+ private static final FilterSpell greenSpellsFilter = new FilterSpell("Green spells you control");
+ private static final FilterPermanent elvesFilter = new FilterControlledCreaturePermanent("each Elf creature you control");
+
+ static {
+ greenSpellsFilter.add(new ColorPredicate(ObjectColor.GREEN));
+ elvesFilter.add(SubType.ELF.getPredicate());
+ }
+
+ public AllosaurusShepherd(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}");
+ this.subtype.add(SubType.ELF);
+ this.subtype.add(SubType.SHAMAN);
+
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ //Allosaurus Shepherd can't be countered.
+ this.addAbility(new CantBeCounteredSourceAbility());
+
+ //Green spells you control can't be countered.
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new CantBeCounteredControlledEffect(greenSpellsFilter, null, Duration.WhileOnBattlefield)));
+
+ //4GG: Until end of turn, each Elf creature you control has base power and toughness 5/5
+ // and becomes a Dinosaur in addition to its other creature types.
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
+ new SetPowerToughnessAllEffect(5, 5, Duration.EndOfTurn, elvesFilter, true)
+ .setText("Until end of turn, each Elf creature you control has base power and toughness 5/5"),
+ new ManaCostsImpl("{4}{G}{G}"));
+ ability.addEffect(new CreaturesBecomeOtherTypeEffect(elvesFilter, SubType.DINOSAUR, Duration.EndOfTurn)
+ .setText("and becomes a Dinosaur in addition to its other creature types"));
+ this.addAbility(ability);
+
+ }
+
+ public AllosaurusShepherd(final AllosaurusShepherd card) {
+ super(card);
+ }
+
+ @Override
+ public AllosaurusShepherd copy() {
+ return new AllosaurusShepherd(this);
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/a/AlmsOfTheVein.java b/Mage.Sets/src/mage/cards/a/AlmsOfTheVein.java
index bca4bcfbdb5..6b337a6bf0a 100644
--- a/Mage.Sets/src/mage/cards/a/AlmsOfTheVein.java
+++ b/Mage.Sets/src/mage/cards/a/AlmsOfTheVein.java
@@ -1,9 +1,6 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.keyword.MadnessAbility;
@@ -12,23 +9,20 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class AlmsOfTheVein extends CardImpl {
public AlmsOfTheVein(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
// Target opponent loses 3 life and you gain 3 life.
- Effect effect = new LoseLifeTargetEffect(3);
- effect.setText("Target opponent loses 3 life");
- this.getSpellAbility().addEffect(effect);
+ this.getSpellAbility().addEffect(new LoseLifeTargetEffect(3));
+ this.getSpellAbility().addEffect(new GainLifeEffect(3).concatBy("and"));
this.getSpellAbility().addTarget(new TargetOpponent());
- effect = new GainLifeEffect(3);
- effect.setText("and you gain 3 life");
- this.getSpellAbility().addEffect(effect);
// Madness {B}
this.addAbility(new MadnessAbility(this, new ManaCostsImpl("{B}")));
diff --git a/Mage.Sets/src/mage/cards/a/AlpineHoundmaster.java b/Mage.Sets/src/mage/cards/a/AlpineHoundmaster.java
new file mode 100644
index 00000000000..adbd5c2f3a5
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/AlpineHoundmaster.java
@@ -0,0 +1,140 @@
+package mage.cards.a;
+
+import mage.MageInt;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.StaticValue;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.cards.*;
+import mage.constants.*;
+import mage.filter.FilterCard;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterAttackingCreature;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.NamePredicate;
+import mage.filter.predicate.permanent.AnotherPredicate;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetCardInLibrary;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class AlpineHoundmaster extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterAttackingCreature();
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ }
+
+ private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
+
+ public AlpineHoundmaster(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WARRIOR);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // When Alpine Houndmaster enters the battlefield, you may search your library for a card named Alpine Watchdog and/or a card named Igneous Cur, reveal them, put them into your hand, then shuffle your library.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new AlpineHoundmasterEffect(), true));
+
+ // Whenever Alpine Houndmaster attacks, it gets +X/+0 until end of turn, where X is the number of other attacking creatures.
+ this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(
+ xValue, StaticValue.get(0), Duration.EndOfTurn
+ ), false, "it gets +X/+0 until end of turn, where X is the number of other attacking creatures"));
+ }
+
+ private AlpineHoundmaster(final AlpineHoundmaster card) {
+ super(card);
+ }
+
+ @Override
+ public AlpineHoundmaster copy() {
+ return new AlpineHoundmaster(this);
+ }
+}
+
+class AlpineHoundmasterEffect extends OneShotEffect {
+
+ AlpineHoundmasterEffect() {
+ super(Outcome.Benefit);
+ staticText = "search your library for a card named Alpine Watchdog and/or a card named Igneous Cur, " +
+ "reveal them, put them into your hand, then shuffle your library";
+ }
+
+ private AlpineHoundmasterEffect(final AlpineHoundmasterEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public AlpineHoundmasterEffect copy() {
+ return new AlpineHoundmasterEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null) {
+ return false;
+ }
+ TargetCardInLibrary target = new AlpineHoundmasterTarget();
+ player.searchLibrary(target, source, game);
+ Cards cards = new CardsImpl(target.getTargets());
+ player.revealCards(source, cards, game);
+ player.moveCards(cards, Zone.HAND, source, game);
+ player.shuffleLibrary(source, game);
+ return true;
+ }
+}
+
+class AlpineHoundmasterTarget extends TargetCardInLibrary {
+
+ private static final FilterCard filter
+ = new FilterCard("card named Alpine Watchdog and/or a card named Igneous Cur");
+
+ static {
+ filter.add(Predicates.or(
+ new NamePredicate("Alpine Watchdog"),
+ new NamePredicate("Igneous Cur")
+ ));
+ }
+
+ AlpineHoundmasterTarget() {
+ super(0, 2, filter);
+ }
+
+ private AlpineHoundmasterTarget(final AlpineHoundmasterTarget target) {
+ super(target);
+ }
+
+ @Override
+ public AlpineHoundmasterTarget copy() {
+ return new AlpineHoundmasterTarget(this);
+ }
+
+ @Override
+ public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
+ if (!super.canTarget(controllerId, id, source, game)) {
+ return false;
+ }
+ Card card = game.getCard(id);
+ if (card == null) {
+ return false;
+ }
+ return this.getTargets()
+ .stream()
+ .map(game::getCard)
+ .map(MageObject::getName)
+ .noneMatch(card.getName()::equals);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/a/AlpineWatchdog.java b/Mage.Sets/src/mage/cards/a/AlpineWatchdog.java
new file mode 100644
index 00000000000..65c6d9bdb42
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/AlpineWatchdog.java
@@ -0,0 +1,36 @@
+package mage.cards.a;
+
+import mage.MageInt;
+import mage.abilities.keyword.VigilanceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class AlpineWatchdog extends CardImpl {
+
+ public AlpineWatchdog(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
+
+ this.subtype.add(SubType.DOG);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Vigilance
+ this.addAbility(VigilanceAbility.getInstance());
+ }
+
+ private AlpineWatchdog(final AlpineWatchdog card) {
+ super(card);
+ }
+
+ @Override
+ public AlpineWatchdog copy() {
+ return new AlpineWatchdog(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/a/AltarOfDementia.java b/Mage.Sets/src/mage/cards/a/AltarOfDementia.java
index 0413e9b9605..339134c9b42 100644
--- a/Mage.Sets/src/mage/cards/a/AltarOfDementia.java
+++ b/Mage.Sets/src/mage/cards/a/AltarOfDementia.java
@@ -48,7 +48,7 @@ class AltarOfDementiaEffect extends OneShotEffect {
public AltarOfDementiaEffect() {
super(Outcome.Damage);
- staticText = "Target player puts a number of cards equal to the sacrificed creature's power from the top of their library into their graveyard";
+ staticText = "Target player mills cards equal to the sacrificed creature's power";
}
public AltarOfDementiaEffect(final AltarOfDementiaEffect effect) {
@@ -67,7 +67,7 @@ class AltarOfDementiaEffect extends OneShotEffect {
}
}
if (amount > 0) {
- player.moveCards(player.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ player.millCards(amount, source, game);
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/a/AlteredEgo.java b/Mage.Sets/src/mage/cards/a/AlteredEgo.java
index ae603d05669..3cb307ca5bc 100644
--- a/Mage.Sets/src/mage/cards/a/AlteredEgo.java
+++ b/Mage.Sets/src/mage/cards/a/AlteredEgo.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CopyPermanentEffect;
@@ -32,7 +32,7 @@ public final class AlteredEgo extends CardImpl {
this.toughness = new MageInt(0);
// Altered Ego can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// You may have Altered Ego enter the battlefield as a copy of any creature on the battlefield, except it enters with an additional X +1/+1 counters on it.
Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, null);
diff --git a/Mage.Sets/src/mage/cards/a/AmassTheComponents.java b/Mage.Sets/src/mage/cards/a/AmassTheComponents.java
index 5d7c24dbad8..c3cdc37eced 100644
--- a/Mage.Sets/src/mage/cards/a/AmassTheComponents.java
+++ b/Mage.Sets/src/mage/cards/a/AmassTheComponents.java
@@ -71,8 +71,7 @@ class AmassTheComponentsEffect extends OneShotEffect {
if (player.choose(Outcome.Detriment, player.getHand(), target, game)) {
Card card = player.getHand().get(target.getFirstTarget(), game);
if (card != null) {
- player.removeFromHand(card, game);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
+ return player.putCardsOnBottomOfLibrary(card, game, source, true);
}
}
}
diff --git a/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java b/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java
index 2c8e04683a3..65390caee24 100644
--- a/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java
+++ b/Mage.Sets/src/mage/cards/a/AmbuscadeShaman.java
@@ -1,25 +1,20 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.TriggeredAbilityImpl;
-import mage.abilities.effects.Effect;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.keyword.DashAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
+import mage.constants.SetTargetPointer;
import mage.constants.SubType;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.game.events.GameEvent;
-import mage.game.permanent.Permanent;
-import mage.target.targetpointer.FixedTarget;
+import mage.filter.StaticFilters;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class AmbuscadeShaman extends CardImpl {
@@ -32,16 +27,18 @@ public final class AmbuscadeShaman extends CardImpl {
this.toughness = new MageInt(2);
// Whenever Ambuscade Shaman or another creature enters the battlefield under your control, that creature gets +2/+2 until end of turn.
- Effect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn);
- effect.setText("that creature gets +2/+2 until end of turn");
- this.addAbility(new AmbuscadeShamanTriggeredAbility(effect));
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new BoostTargetEffect(2, 2, Duration.EndOfTurn)
+ .setText("that creature gets +2/+2 until end of turn"),
+ StaticFilters.FILTER_PERMANENT_CREATURE, false,
+ SetTargetPointer.PERMANENT, true
+ ));
// Dash {3}{B} (You may cast this spell for its dash cost. If you do, it gains haste, and it's returned from the battlefield to its owner's hand at the beginning of the next end step.));
this.addAbility(new DashAbility(this, "{3}{B}"));
-
}
- public AmbuscadeShaman(final AmbuscadeShaman card) {
+ private AmbuscadeShaman(final AmbuscadeShaman card) {
super(card);
}
@@ -50,41 +47,3 @@ public final class AmbuscadeShaman extends CardImpl {
return new AmbuscadeShaman(this);
}
}
-
-class AmbuscadeShamanTriggeredAbility extends TriggeredAbilityImpl {
-
- AmbuscadeShamanTriggeredAbility(Effect effect) {
- super(Zone.BATTLEFIELD, effect, false);
- }
-
- AmbuscadeShamanTriggeredAbility(final AmbuscadeShamanTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public AmbuscadeShamanTriggeredAbility copy() {
- return new AmbuscadeShamanTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- UUID targetId = event.getTargetId();
- Permanent permanent = game.getPermanent(targetId);
- if (permanent.isControlledBy(this.controllerId)
- && permanent.isCreature()) {
- this.getEffects().setTargetPointer(new FixedTarget(permanent, game));
- return true;
- }
- return false;
- }
-
- @Override
- public String getRule() {
- return "Whenever {this} or another creature enters the battlefield under your control, that creature gets +2/+2 until end of turn.";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/a/AminatousAugury.java b/Mage.Sets/src/mage/cards/a/AminatousAugury.java
index 9e230a447ca..78a047d2d3c 100644
--- a/Mage.Sets/src/mage/cards/a/AminatousAugury.java
+++ b/Mage.Sets/src/mage/cards/a/AminatousAugury.java
@@ -175,7 +175,8 @@ class AminatousAuguryCastFromExileEffect extends AsThoughEffectImpl {
usedCardTypes.add(CardType.fromString(choice.getChoice()));
}
usedCardTypes.addAll(unusedCardTypes);
- player.setCastSourceIdWithAlternateMana(sourceId, null, null);
+ player.setCastSourceIdWithAlternateMana(sourceId, null, card.getSpellAbility().getCosts());
+ // TODO- This does not correctly work when you cancel the cast (has to be done by watcher I guess)
game.getState().setValue(source.getSourceId().toString() + "cardTypes", usedCardTypes);
}
return true;
diff --git a/Mage.Sets/src/mage/cards/a/Amnesia.java b/Mage.Sets/src/mage/cards/a/Amnesia.java
index ae4eebaa75f..b452e933bc8 100644
--- a/Mage.Sets/src/mage/cards/a/Amnesia.java
+++ b/Mage.Sets/src/mage/cards/a/Amnesia.java
@@ -1,28 +1,25 @@
-
package mage.cards.a;
-import java.util.Set;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
-import mage.cards.CardImpl;
-import mage.cards.CardSetInfo;
-import mage.cards.Cards;
+import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class Amnesia extends CardImpl {
public Amnesia(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{U}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{U}{U}");
// Target player reveals their hand and discards all nonland cards.
this.getSpellAbility().addEffect(new AmnesiaEffect());
@@ -60,13 +57,10 @@ class AmnesiaEffect extends OneShotEffect {
Player player = game.getPlayer(source.getFirstTarget());
if (player != null) {
Cards hand = player.getHand();
- player.revealCards("Amnesia", hand, game);
+ player.revealCards(source, hand, game);
Set cards = hand.getCards(game);
- for (Card card : cards) {
- if (card != null && !card.isLand()) {
- player.discard(card, source, game);
- }
- }
+ cards.removeIf(MageObject::isLand);
+ player.discard(new CardsImpl(cards), source, game);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/a/AnaBattlemage.java b/Mage.Sets/src/mage/cards/a/AnaBattlemage.java
index 38d6c7af250..bed405a1977 100644
--- a/Mage.Sets/src/mage/cards/a/AnaBattlemage.java
+++ b/Mage.Sets/src/mage/cards/a/AnaBattlemage.java
@@ -20,8 +20,8 @@ import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
+import mage.target.TargetPlayer;
import mage.target.common.TargetCreaturePermanent;
-import mage.target.common.TargetOpponent;
import java.util.UUID;
@@ -49,7 +49,7 @@ public final class AnaBattlemage extends CardImpl {
this.addAbility(kickerAbility);
// When Ana Battlemage enters the battlefield, if it was kicked with its {2}{U} kicker, target player discards three cards.
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(3));
- ability.addTarget(new TargetOpponent());
+ ability.addTarget(new TargetPlayer());
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{2}{U}"),
"When {this} enters the battlefield, if it was kicked with its {2}{U} kicker, target player discards three cards."));
// When Ana Battlemage enters the battlefield, if it was kicked with its {1}{B} kicker, tap target untapped creature and that creature deals damage equal to its power to its controller.
diff --git a/Mage.Sets/src/mage/cards/a/AnaxHardenedInTheForge.java b/Mage.Sets/src/mage/cards/a/AnaxHardenedInTheForge.java
index 2412c0a40fb..b55489b2c7d 100644
--- a/Mage.Sets/src/mage/cards/a/AnaxHardenedInTheForge.java
+++ b/Mage.Sets/src/mage/cards/a/AnaxHardenedInTheForge.java
@@ -1,7 +1,6 @@
package mage.cards.a;
import mage.MageInt;
-import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.DevotionCount;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -12,17 +11,27 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
-import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.SatyrCantBlockToken;
-import java.util.Objects;
import java.util.UUID;
+import mage.abilities.common.DiesThisOrAnotherCreatureTriggeredAbility;
+import mage.abilities.effects.Effect;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.permanent.TokenPredicate;
/**
* @author TheElk801
*/
public final class AnaxHardenedInTheForge extends CardImpl {
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature you control");
+
+ static {
+ filter.add(TargetController.YOU.getControllerPredicate());
+ filter.add(Predicates.not(TokenPredicate.instance));
+ }
+
public AnaxHardenedInTheForge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{1}{R}{R}");
@@ -38,8 +47,9 @@ public final class AnaxHardenedInTheForge extends CardImpl {
.setText("{this}'s power is equal to your devotion to red")
).addHint(DevotionCount.R.getHint()));
- // Whenever Anax or another nontoken creature you control dies, create a 1/1 red Satyr creature token with "This creature can't block." If the creature had power 4 or greater, create two of those tokens instead.
- this.addAbility(new AnaxHardenedInTheForgeTriggeredAbility());
+ // Whenever Anax or another nontoken creature you control dies, create a 1/1 red Satyr creature token
+ // with "This creature can't block." If the creature had power 4 or greater, create two of those tokens instead.
+ this.addAbility(new AnaxHardenedInTheForgeTriggeredAbility(null, false, filter));
}
private AnaxHardenedInTheForge(final AnaxHardenedInTheForge card) {
@@ -52,10 +62,10 @@ public final class AnaxHardenedInTheForge extends CardImpl {
}
}
-class AnaxHardenedInTheForgeTriggeredAbility extends TriggeredAbilityImpl {
+class AnaxHardenedInTheForgeTriggeredAbility extends DiesThisOrAnotherCreatureTriggeredAbility {
- AnaxHardenedInTheForgeTriggeredAbility() {
- super(Zone.BATTLEFIELD, null, false);
+ AnaxHardenedInTheForgeTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter) {
+ super(effect, optional, filter);
}
private AnaxHardenedInTheForgeTriggeredAbility(final AnaxHardenedInTheForgeTriggeredAbility ability) {
@@ -67,33 +77,21 @@ class AnaxHardenedInTheForgeTriggeredAbility extends TriggeredAbilityImpl {
return new AnaxHardenedInTheForgeTriggeredAbility(this);
}
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.ZONE_CHANGE;
- }
-
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
- if (!zEvent.isDiesEvent()) {
- return false;
+ if (super.checkTrigger(event, game)) {
+ int tokenCount = ((ZoneChangeEvent) event).getTarget().getPower().getValue() > 3 ? 2 : 1;
+ this.getEffects().clear();
+ this.addEffect(new CreateTokenEffect(new SatyrCantBlockToken(), tokenCount));
+ return true;
}
- if (!zEvent.getTarget().getId().equals(getSourceId())
- && (zEvent.getTarget() instanceof PermanentToken
- || !zEvent.getTarget().isCreature()
- || !Objects.equals(zEvent.getTarget().getControllerId(), getControllerId()))) {
- return false;
- }
- int tokenCount = zEvent.getTarget().getPower().getValue() > 3 ? 2 : 1;
- this.getEffects().clear();
- this.addEffect(new CreateTokenEffect(new SatyrCantBlockToken(), tokenCount));
- return true;
+ return false;
}
@Override
public String getRule() {
- return "Whenever {this} or another nontoken creature you control dies, " +
- "create a 1/1 red Satyr creature token with \"This creature can't block.\" " +
- "If the creature had power 4 or greater, create two of those tokens instead.";
+ return "Whenever {this} or another nontoken creature you control dies, "
+ + "create a 1/1 red Satyr creature token with \"This creature can't block.\" "
+ + "If the creature had power 4 or greater, create two of those tokens instead.";
}
}
diff --git a/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java b/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java
index bc7ddf8dacc..095ca784ba2 100644
--- a/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java
+++ b/Mage.Sets/src/mage/cards/a/AncientStoneIdol.java
@@ -1,31 +1,25 @@
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.AttackingCreatureCount;
import mage.abilities.effects.common.CreateTokenEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
-import mage.constants.SubType;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.CostModificationType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.common.FilterCreaturePermanent;
-import mage.filter.predicate.permanent.AttackingPredicate;
-import mage.game.Game;
import mage.game.permanent.token.StoneTrapIdolToken;
-import mage.util.CardUtil;
+
+import java.util.UUID;
/**
- *
* @author TheElk801
*/
public final class AncientStoneIdol extends CardImpl {
@@ -41,13 +35,16 @@ public final class AncientStoneIdol extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// This spell costs {1} less to cast for each attacking creature.
- this.addAbility(new SimpleStaticAbility(Zone.ALL, new AncientStoneIdolCostReductionEffect()));
+ DynamicValue xValue = new AttackingCreatureCount();
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue))
+ .addHint(new ValueHint("Attacking creatures", xValue))
+ );
// Trample
this.addAbility(TrampleAbility.getInstance());
// When Ancient Stone Idol dies, create a 6/12 colorless Construct artifact creature token with trample.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new StoneTrapIdolToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new StoneTrapIdolToken())));
}
public AncientStoneIdol(final AncientStoneIdol card) {
@@ -59,41 +56,3 @@ public final class AncientStoneIdol extends CardImpl {
return new AncientStoneIdol(this);
}
}
-
-class AncientStoneIdolCostReductionEffect extends CostModificationEffectImpl {
-
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
-
- static {
- filter.add(AttackingPredicate.instance);
- }
-
- public AncientStoneIdolCostReductionEffect() {
- super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {1} less to cast for each attacking creature";
- }
-
- protected AncientStoneIdolCostReductionEffect(AncientStoneIdolCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- int reductionAmount = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
- CardUtil.reduceCost(abilityToModify, reductionAmount);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if ((abilityToModify instanceof SpellAbility) && abilityToModify.getSourceId().equals(source.getSourceId())) {
- return game.getCard(abilityToModify.getSourceId()) != null;
- }
- return false;
- }
-
- @Override
- public AncientStoneIdolCostReductionEffect copy() {
- return new AncientStoneIdolCostReductionEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/a/AndraditeLeech.java b/Mage.Sets/src/mage/cards/a/AndraditeLeech.java
index 0102b19379a..3d91d654f5e 100644
--- a/Mage.Sets/src/mage/cards/a/AndraditeLeech.java
+++ b/Mage.Sets/src/mage/cards/a/AndraditeLeech.java
@@ -1,25 +1,21 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementControllerEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.SubType;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author LoneFox
*/
public final class AndraditeLeech extends CardImpl {
@@ -31,17 +27,17 @@ public final class AndraditeLeech extends CardImpl {
}
public AndraditeLeech(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.LEECH);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Black spells you cast cost {B} more to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
- new SpellsCostIncreasementControllerEffect(filter, new ManaCostsImpl("{B}"))));
+ new SpellsCostIncreasingAllEffect(new ManaCostsImpl("{B}"), filter, TargetController.YOU)));
// {B}: Andradite Leech gets +1/+1 until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
- new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{B}")));
+ new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{B}")));
}
public AndraditeLeech(final AndraditeLeech card) {
diff --git a/Mage.Sets/src/mage/cards/a/AngelOfFury.java b/Mage.Sets/src/mage/cards/a/AngelOfFury.java
index 9bbdb35252d..e6f7115a0c7 100644
--- a/Mage.Sets/src/mage/cards/a/AngelOfFury.java
+++ b/Mage.Sets/src/mage/cards/a/AngelOfFury.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -26,7 +26,7 @@ public final class AngelOfFury extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Angel of Fury is put into your graveyard from the battlefield, you may shuffle it into your library.
- this.addAbility(new DiesTriggeredAbility(new ShuffleIntoLibrarySourceEffect(), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new ShuffleIntoLibrarySourceEffect(), true));
}
public AngelOfFury(final AngelOfFury card) {
diff --git a/Mage.Sets/src/mage/cards/a/AngelOfTheDireHour.java b/Mage.Sets/src/mage/cards/a/AngelOfTheDireHour.java
index 2b3826169ca..e02c3656b33 100644
--- a/Mage.Sets/src/mage/cards/a/AngelOfTheDireHour.java
+++ b/Mage.Sets/src/mage/cards/a/AngelOfTheDireHour.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.ExileAllEffect;
import mage.abilities.keyword.FlashAbility;
@@ -36,7 +36,7 @@ public final class AngelOfTheDireHour extends CardImpl {
// When Angel of the Dire Hour enters the battlefield, if you cast it from your hand, exile all attacking creatures.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new ExileAllEffect(new FilterAttackingCreature("attacking creatures")), false),
- CastFromHandSourceCondition.instance,
+ CastFromHandSourcePermanentCondition.instance,
"When {this} enters the battlefield, if you cast it from your hand, exile all attacking creatures."),
new CastFromHandWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/a/AngelicAscension.java b/Mage.Sets/src/mage/cards/a/AngelicAscension.java
new file mode 100644
index 00000000000..4d99578f646
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/AngelicAscension.java
@@ -0,0 +1,68 @@
+package mage.cards.a;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.ExileTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.game.permanent.token.AngelToken;
+import mage.game.permanent.token.Token;
+import mage.target.common.TargetCreatureOrPlaneswalker;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class AngelicAscension extends CardImpl {
+
+ public AngelicAscension(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
+
+ // Exile target creature or planeswalker. Its controller creates a 4/4 white Angel creature token with flying.
+ this.getSpellAbility().addEffect(new ExileTargetEffect());
+ this.getSpellAbility().addEffect(new AngelicAscensionEffect());
+ this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker());
+ }
+
+ private AngelicAscension(final AngelicAscension card) {
+ super(card);
+ }
+
+ @Override
+ public AngelicAscension copy() {
+ return new AngelicAscension(this);
+ }
+}
+
+class AngelicAscensionEffect extends OneShotEffect {
+
+ private static final Token token = new AngelToken();
+
+ AngelicAscensionEffect() {
+ super(Outcome.PutCreatureInPlay);
+ this.staticText = "Its controller creates a 4/4 white Angel creature token with flying";
+ }
+
+ private AngelicAscensionEffect(final AngelicAscensionEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public AngelicAscensionEffect copy() {
+ return new AngelicAscensionEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanentOrLKIBattlefield(source.getFirstTarget());
+ if (permanent == null) {
+ return false;
+ }
+ return token.putOntoBattlefield(1, game, source.getSourceId(), permanent.getControllerId());
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java b/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java
index 2c5a6aef46a..d9eff6ea194 100644
--- a/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java
+++ b/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java
@@ -98,7 +98,7 @@ class AngrathMinotaurPirateThirdAbilityEffect extends OneShotEffect {
permanent.destroy(source.getSourceId(), game, false);
powerSum += permanent.getPower().getValue();
}
- game.applyEffects();
+ game.getState().processAction(game);
targetOpponent.damage(powerSum, source.getSourceId(), game);
}
return true;
diff --git a/Mage.Sets/src/mage/cards/a/AnimalSanctuary.java b/Mage.Sets/src/mage/cards/a/AnimalSanctuary.java
new file mode 100644
index 00000000000..b87c98b14c6
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/AnimalSanctuary.java
@@ -0,0 +1,61 @@
+package mage.cards.a;
+
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.common.counter.AddCountersTargetEffect;
+import mage.abilities.mana.ColorlessManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+import mage.filter.FilterPermanent;
+import mage.filter.predicate.Predicates;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class AnimalSanctuary extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterPermanent("Bird, Cat, Dog, Goat, Ox, or Snake");
+
+ static {
+ filter.add(Predicates.or(
+ SubType.BIRD.getPredicate(),
+ SubType.CAT.getPredicate(),
+ SubType.DOG.getPredicate(),
+ SubType.GOAT.getPredicate(),
+ SubType.OX.getPredicate(),
+ SubType.SNAKE.getPredicate()
+ ));
+ }
+
+ public AnimalSanctuary(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
+
+ // {T}: Add {C}.
+ this.addAbility(new ColorlessManaAbility());
+
+ // {2}, {T}: Put a +1/+1 counter on target Bird, Cat, Dog, Goat, Ox, or Snake.
+ Ability ability = new SimpleActivatedAbility(
+ new AddCountersTargetEffect(CounterType.P1P1.createInstance()), new GenericManaCost(2)
+ );
+ ability.addCost(new TapSourceCost());
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(ability);
+ }
+
+ private AnimalSanctuary(final AnimalSanctuary card) {
+ super(card);
+ }
+
+ @Override
+ public AnimalSanctuary copy() {
+ return new AnimalSanctuary(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java b/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java
index 94e44b7c8e9..1ac2052194d 100644
--- a/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java
+++ b/Mage.Sets/src/mage/cards/a/AnimarSoulOfElements.java
@@ -1,7 +1,5 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
@@ -21,8 +19,9 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.util.CardUtil;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class AnimarSoulOfElements extends CardImpl {
@@ -73,10 +72,8 @@ class AnimarCostReductionEffect extends CostModificationEffectImpl {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null && spellAbility != null) {
int amount = sourcePermanent.getCounters(game).getCount(CounterType.P1P1);
- if (amount > 0) {
- CardUtil.reduceCost(spellAbility, amount);
- return true;
- }
+ CardUtil.reduceCost(spellAbility, amount);
+ return true;
}
return false;
}
@@ -85,9 +82,9 @@ class AnimarCostReductionEffect extends CostModificationEffectImpl {
public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify instanceof SpellAbility) {
if (abilityToModify.isControlledBy(source.getControllerId())) {
- Card spell = ((SpellAbility) abilityToModify).getCharacteristics(game);
- if (spell != null) {
- return spell.isCreature();
+ Card card = ((SpellAbility) abilityToModify).getCharacteristics(game);
+ if (card != null) {
+ return card.isCreature();
}
}
}
diff --git a/Mage.Sets/src/mage/cards/a/AnimateDead.java b/Mage.Sets/src/mage/cards/a/AnimateDead.java
index 0f833cc16e8..4a2f98ff4f7 100644
--- a/Mage.Sets/src/mage/cards/a/AnimateDead.java
+++ b/Mage.Sets/src/mage/cards/a/AnimateDead.java
@@ -225,9 +225,7 @@ class AnimateDeadChangeAbilityEffect extends ContinuousEffectImpl implements Sou
abilityToRemove = ability;
}
}
- if (abilityToRemove != null) {
- permanent.getAbilities().remove(abilityToRemove);
- }
+ permanent.removeAbility(abilityToRemove, source.getSourceId(), game);
permanent.addAbility(newAbility, source.getSourceId(), game);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/a/AnjeFalkenrath.java b/Mage.Sets/src/mage/cards/a/AnjeFalkenrath.java
index 9d0e2834dd0..70c8b6c5a06 100644
--- a/Mage.Sets/src/mage/cards/a/AnjeFalkenrath.java
+++ b/Mage.Sets/src/mage/cards/a/AnjeFalkenrath.java
@@ -83,7 +83,7 @@ class AnjeFalkenrathTriggeredAbility extends TriggeredAbilityImpl {
if (card == null) {
return false;
}
- return card.getAbilities(game).stream().anyMatch(ability -> ability instanceof MadnessAbility);
+ return card.getAbilities(game).containsClass(MadnessAbility.class);
}
@Override
diff --git a/Mage.Sets/src/mage/cards/a/AnodetLurker.java b/Mage.Sets/src/mage/cards/a/AnodetLurker.java
index ecd459aad4b..983985f0353 100644
--- a/Mage.Sets/src/mage/cards/a/AnodetLurker.java
+++ b/Mage.Sets/src/mage/cards/a/AnodetLurker.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class AnodetLurker extends CardImpl {
this.toughness = new MageInt(3);
// When Anodet Lurker dies, you gain 3 life.
- this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(3)));
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(3)));
}
public AnodetLurker(final AnodetLurker card) {
diff --git a/Mage.Sets/src/mage/cards/a/AnointedChorister.java b/Mage.Sets/src/mage/cards/a/AnointedChorister.java
new file mode 100644
index 00000000000..c4761f699a7
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/AnointedChorister.java
@@ -0,0 +1,46 @@
+package mage.cards.a;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class AnointedChorister extends CardImpl {
+
+ public AnointedChorister(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ // Lifelink
+ this.addAbility(LifelinkAbility.getInstance());
+
+ // {4}{W}: Anointed Chorister gets +3/+3 until end of turn.
+ this.addAbility(new SimpleActivatedAbility(
+ new BoostSourceEffect(3, 3, Duration.EndOfTurn), new ManaCostsImpl("{4}{W}")
+ ));
+ }
+
+ private AnointedChorister(final AnointedChorister card) {
+ super(card);
+ }
+
+ @Override
+ public AnointedChorister copy() {
+ return new AnointedChorister(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/a/AphettoVulture.java b/Mage.Sets/src/mage/cards/a/AphettoVulture.java
index f62b8b9f223..7096706082f 100644
--- a/Mage.Sets/src/mage/cards/a/AphettoVulture.java
+++ b/Mage.Sets/src/mage/cards/a/AphettoVulture.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.PutOnLibraryTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -38,7 +38,7 @@ public final class AphettoVulture extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Aphetto Vulture dies, you may put target Zombie card from your graveyard on top of your library.
- Ability ability = new DiesTriggeredAbility(new PutOnLibraryTargetEffect(true), true);
+ Ability ability = new DiesSourceTriggeredAbility(new PutOnLibraryTargetEffect(true), true);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/a/Apocalypse.java b/Mage.Sets/src/mage/cards/a/Apocalypse.java
index 09008dac712..073e15d3361 100644
--- a/Mage.Sets/src/mage/cards/a/Apocalypse.java
+++ b/Mage.Sets/src/mage/cards/a/Apocalypse.java
@@ -1,30 +1,25 @@
-
package mage.cards.a;
-import java.util.UUID;
-import mage.abilities.Ability;
-import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
+import mage.abilities.effects.common.ExileAllEffect;
+import mage.abilities.effects.common.discard.DiscardHandControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
+import mage.filter.StaticFilters;
+
+import java.util.UUID;
/**
- *
* @author markedagain
*/
public final class Apocalypse extends CardImpl {
public Apocalypse(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{R}{R}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}{R}{R}");
// Exile all permanents. You discard your hand.
- this.getSpellAbility().addEffect(new ApocalypseExileAllPermanentsEffect());
- this.getSpellAbility().addEffect(new ApocalypseDiscardEffect());
+ this.getSpellAbility().addEffect(new ExileAllEffect(StaticFilters.FILTER_PERMANENTS));
+ this.getSpellAbility().addEffect(new DiscardHandControllerEffect().setText("You discard your hand"));
}
public Apocalypse(final Apocalypse card) {
@@ -36,55 +31,3 @@ public final class Apocalypse extends CardImpl {
return new Apocalypse(this);
}
}
-class ApocalypseDiscardEffect extends OneShotEffect {
-
- public ApocalypseDiscardEffect() {
- super(Outcome.Discard);
- this.staticText = "Discard your hand";
- }
-
- public ApocalypseDiscardEffect(final ApocalypseDiscardEffect effect) {
- super(effect);
- }
-
- @Override
- public ApocalypseDiscardEffect copy() {
- return new ApocalypseDiscardEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- for (Card card : player.getHand().getCards(game)) {
- player.discard(card, source, game);
- }
- return true;
- }
- return false;
- }
-}
-class ApocalypseExileAllPermanentsEffect extends OneShotEffect {
-
- public ApocalypseExileAllPermanentsEffect() {
- super(Outcome.Exile);
- staticText = "Exile all permanents";
- }
-
- public ApocalypseExileAllPermanentsEffect(final ApocalypseExileAllPermanentsEffect effect) {
- super(effect);
- }
-
- @Override
- public ApocalypseExileAllPermanentsEffect copy() {
- return new ApocalypseExileAllPermanentsEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) {
- permanent.moveToExile(null, null, source.getSourceId(), game);
- }
- return true;
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java b/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java
index ea4a3c95484..f47ae0b0812 100644
--- a/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java
+++ b/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java
@@ -27,6 +27,8 @@ public final class ApproachOfTheSecondSun extends CardImpl {
public ApproachOfTheSecondSun(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{W}");
+ // If this spell was cast from your hand and you've cast another spell named Approach of the Second Sun this game,
+ // you win the game. Otherwise, put Approach of the Second Sun into its owner's library seventh from the top and you gain 7 life.
getSpellAbility().addEffect(new ApproachOfTheSecondSunEffect());
getSpellAbility().addWatcher(new ApproachOfTheSecondSunWatcher());
}
@@ -46,7 +48,7 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect {
public ApproachOfTheSecondSunEffect() {
super(Outcome.Win);
this.staticText
- = "If this spell was cast from your hand and you've cast another spell named Approach of the Second Sun this game, you win the game. "
+ = "If this spell was cast from your hand and you've cast another spell named {this} this game, you win the game. "
+ "Otherwise, put {this} into its owner's library seventh from the top and you gain 7 life.";
}
@@ -93,7 +95,7 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect {
class ApproachOfTheSecondSunWatcher extends Watcher {
- private Map approachesCast = new HashMap<>();
+ private final Map approachesCast = new HashMap<>();
public ApproachOfTheSecondSunWatcher() {
super(WatcherScope.GAME);
diff --git a/Mage.Sets/src/mage/cards/a/ArashinSovereign.java b/Mage.Sets/src/mage/cards/a/ArashinSovereign.java
index 88676ac5f6b..0aeac68a2d4 100644
--- a/Mage.Sets/src/mage/cards/a/ArashinSovereign.java
+++ b/Mage.Sets/src/mage/cards/a/ArashinSovereign.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
@@ -33,7 +33,7 @@ public final class ArashinSovereign extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Arashin Sovereign dies, you may put it on the top or bottom of its owner's library.
- this.addAbility(new DiesTriggeredAbility(new ArashinSovereignEffect(), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new ArashinSovereignEffect(), true));
}
public ArashinSovereign(final ArashinSovereign card) {
diff --git a/Mage.Sets/src/mage/cards/a/ArcaneArtisan.java b/Mage.Sets/src/mage/cards/a/ArcaneArtisan.java
index e4028535a35..d46ca7710fd 100644
--- a/Mage.Sets/src/mage/cards/a/ArcaneArtisan.java
+++ b/Mage.Sets/src/mage/cards/a/ArcaneArtisan.java
@@ -30,6 +30,7 @@ import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
+import mage.cards.CardsImpl;
/**
* @author TheElk801
@@ -167,12 +168,10 @@ class ArcaneArtisanExileEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Object object = game.getState().getValue(CardUtil.getCardZoneString("_tokensCreated", source.getSourceId(), game, true));
if (object != null) {
- Set tokensCreated = (Set) object;
- for (UUID tokenId : tokensCreated) {
- Permanent token = game.getPermanent(tokenId);
- if (token != null) {
- token.destroy(source.getSourceId(), game, true);
- }
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ controller.moveCards(new CardsImpl((Set) object), Zone.EXILED, source, game);
+ return true;
}
}
return true;
diff --git a/Mage.Sets/src/mage/cards/a/ArcaneMelee.java b/Mage.Sets/src/mage/cards/a/ArcaneMelee.java
index 9e45b06db79..2657238404a 100644
--- a/Mage.Sets/src/mage/cards/a/ArcaneMelee.java
+++ b/Mage.Sets/src/mage/cards/a/ArcaneMelee.java
@@ -1,17 +1,14 @@
-
package mage.cards.a;
-import java.util.UUID;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
-import mage.cards.Card;
+import mage.abilities.effects.common.cost.SpellsCostReductionAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.util.CardUtil;
+import mage.constants.CardType;
+import mage.constants.Zone;
+import mage.filter.common.FilterInstantOrSorceryCard;
+
+import java.util.UUID;
/**
* @author noxx
@@ -22,7 +19,9 @@ public final class ArcaneMelee extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}");
// Instant and sorcery spells cost {2} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ArcaneMeleeCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostReductionAllEffect(new FilterInstantOrSorceryCard("Instant and sorcery spells"), 2))
+ );
}
public ArcaneMelee(final ArcaneMelee card) {
@@ -34,39 +33,3 @@ public final class ArcaneMelee extends CardImpl {
return new ArcaneMelee(this);
}
}
-
-class ArcaneMeleeCostReductionEffect extends CostModificationEffectImpl {
-
- ArcaneMeleeCostReductionEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "Instant and sorcery spells cost {2} less to cast";
- }
-
- ArcaneMeleeCostReductionEffect(ArcaneMeleeCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, 2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- Card sourceCard = game.getCard((abilityToModify).getSourceId());
- if (sourceCard != null && (sourceCard.isInstant() || sourceCard.isSorcery())) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public ArcaneMeleeCostReductionEffect copy() {
- return new ArcaneMeleeCostReductionEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/a/Archaeomender.java b/Mage.Sets/src/mage/cards/a/Archaeomender.java
new file mode 100644
index 00000000000..7d796a45047
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/Archaeomender.java
@@ -0,0 +1,47 @@
+package mage.cards.a;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterCard;
+import mage.filter.common.FilterArtifactCard;
+import mage.target.common.TargetCardInYourGraveyard;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class Archaeomender extends CardImpl {
+
+ private static final FilterCard filter
+ = new FilterArtifactCard("artifact card from your graveyard");
+
+ public Archaeomender(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WIZARD);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // When Archaeomender enters the battlefield, return target artifact card from your graveyard to your hand.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
+ ability.addTarget(new TargetCardInYourGraveyard(filter));
+ this.addAbility(ability);
+ }
+
+ private Archaeomender(final Archaeomender card) {
+ super(card);
+ }
+
+ @Override
+ public Archaeomender copy() {
+ return new Archaeomender(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/a/ArchfiendsVessel.java b/Mage.Sets/src/mage/cards/a/ArchfiendsVessel.java
new file mode 100644
index 00000000000..95d0680393e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/ArchfiendsVessel.java
@@ -0,0 +1,131 @@
+package mage.cards.a;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.EntersTheBattlefieldEvent;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.game.permanent.token.DemonToken;
+import mage.game.permanent.token.Token;
+import mage.game.stack.Spell;
+import mage.players.Player;
+import mage.watchers.common.SpellsCastWatcher;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class ArchfiendsVessel extends CardImpl {
+
+ public ArchfiendsVessel(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ // Lifelink
+ this.addAbility(LifelinkAbility.getInstance());
+
+ // When Archfiend's Vessel enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, exile it. If you do, create a 5/5 black Demon creature token with flying.
+ this.addAbility(new ArchfiendsVesselAbility(), new SpellsCastWatcher());
+ }
+
+ private ArchfiendsVessel(final ArchfiendsVessel card) {
+ super(card);
+ }
+
+ @Override
+ public ArchfiendsVessel copy() {
+ return new ArchfiendsVessel(this);
+ }
+}
+
+class ArchfiendsVesselAbility extends EntersBattlefieldTriggeredAbility {
+
+ ArchfiendsVesselAbility() {
+ super(new ArchfiendsVesselEffect());
+ }
+
+ private ArchfiendsVesselAbility(ArchfiendsVesselAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (super.checkTrigger(event, game)) {
+ if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
+ EntersTheBattlefieldEvent entersTheBattlefieldEvent = (EntersTheBattlefieldEvent) event;
+ if (entersTheBattlefieldEvent.getTargetId().equals(getSourceId()) && entersTheBattlefieldEvent.getFromZone() == Zone.GRAVEYARD) {
+ return true;
+ } else {
+ SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
+ List spellsCastFromGraveyard = watcher.getSpellsCastFromGraveyardThisTurn(getControllerId());
+ if (spellsCastFromGraveyard != null) {
+ return spellsCastFromGraveyard.stream()
+ .anyMatch(spell -> spell.getMainCard().getId().equals((entersTheBattlefieldEvent.getTarget().getMainCard().getId())));
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public ArchfiendsVesselAbility copy() {
+ return new ArchfiendsVesselAbility(this);
+ }
+}
+
+class ArchfiendsVesselEffect extends OneShotEffect {
+
+ ArchfiendsVesselEffect() {
+ super(Outcome.Benefit);
+ staticText = "if it entered from your graveyard or you cast it from your graveyard, exile it. If you do, create a 5/5 black Demon creature token with flying";
+ }
+
+ private ArchfiendsVesselEffect(ArchfiendsVesselEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent archfiendsVessel = source.getSourcePermanentIfItStillExists(game);
+ if (archfiendsVessel != null) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ boolean moved = controller.moveCards(archfiendsVessel.getMainCard(), Zone.EXILED, source, game);
+ if (moved) {
+ Token token = new DemonToken();
+ token.putOntoBattlefield(1, game, source.getSourceId(), controller.getId());
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public ArchfiendsVesselEffect copy() {
+ return new ArchfiendsVesselEffect(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/a/ArchonOfFallingStars.java b/Mage.Sets/src/mage/cards/a/ArchonOfFallingStars.java
index 0ac34127ddf..0e32d828501 100644
--- a/Mage.Sets/src/mage/cards/a/ArchonOfFallingStars.java
+++ b/Mage.Sets/src/mage/cards/a/ArchonOfFallingStars.java
@@ -2,7 +2,7 @@ package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -33,7 +33,7 @@ public final class ArchonOfFallingStars extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Archon of Falling Stars dies, you may return target enchantment card from your graveyard to the battlefield.
- Ability ability = new DiesTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(false, false), true);
+ Ability ability = new DiesSourceTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(false, false), true);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/a/ArchonOfJustice.java b/Mage.Sets/src/mage/cards/a/ArchonOfJustice.java
index 755522cb19d..c08485495bd 100644
--- a/Mage.Sets/src/mage/cards/a/ArchonOfJustice.java
+++ b/Mage.Sets/src/mage/cards/a/ArchonOfJustice.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class ArchonOfJustice extends CardImpl {
this.toughness = new MageInt(4);
this.addAbility(FlyingAbility.getInstance());
- Ability ability = new DiesTriggeredAbility(new ExileTargetEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new ExileTargetEffect(), false);
ability.addTarget(new TargetPermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java b/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java
index c450ed30746..f3821390611 100644
--- a/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java
+++ b/Mage.Sets/src/mage/cards/a/ArchonOfRedemption.java
@@ -1,18 +1,22 @@
package mage.cards.a;
import mage.MageInt;
-import mage.abilities.TriggeredAbilityImpl;
-import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SetTargetPointer;
import mage.constants.SubType;
-import mage.constants.Zone;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
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 java.util.UUID;
@@ -21,6 +25,12 @@ import java.util.UUID;
*/
public final class ArchonOfRedemption extends CardImpl {
+ private static final FilterPermanent filter = new FilterCreaturePermanent("creature with flying");
+
+ static {
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ }
+
public ArchonOfRedemption(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
this.subtype.add(SubType.ARCHON);
@@ -29,11 +39,14 @@ public final class ArchonOfRedemption extends CardImpl {
this.toughness = new MageInt(4);
this.addAbility(FlyingAbility.getInstance());
+
// Whenever Archon of Redemption or another creature with flying enters the battlefield under your control, you may gain life equal to that creature's power.
- this.addAbility(new ArchonOfRedemptionTriggeredAbility());
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new ArchonOfRedemptionEffect(), filter, true, SetTargetPointer.PERMANENT, true
+ ));
}
- public ArchonOfRedemption(final ArchonOfRedemption card) {
+ private ArchonOfRedemption(final ArchonOfRedemption card) {
super(card);
}
@@ -43,43 +56,29 @@ public final class ArchonOfRedemption extends CardImpl {
}
}
-class ArchonOfRedemptionTriggeredAbility extends TriggeredAbilityImpl {
+class ArchonOfRedemptionEffect extends OneShotEffect {
- ArchonOfRedemptionTriggeredAbility() {
- super(Zone.BATTLEFIELD, null, true);
+ ArchonOfRedemptionEffect() {
+ super(Outcome.Benefit);
+ staticText = "gain life equal to that creature's power";
}
- ArchonOfRedemptionTriggeredAbility(final ArchonOfRedemptionTriggeredAbility ability) {
- super(ability);
+ private ArchonOfRedemptionEffect(final ArchonOfRedemptionEffect effect) {
+ super(effect);
}
@Override
- public ArchonOfRedemptionTriggeredAbility copy() {
- return new ArchonOfRedemptionTriggeredAbility(this);
+ public ArchonOfRedemptionEffect copy() {
+ return new ArchonOfRedemptionEffect(this);
}
@Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == EventType.ENTERS_THE_BATTLEFIELD;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- Permanent permanent = game.getPermanent(event.getTargetId());
- if (permanent != null
- && permanent.isControlledBy(getControllerId())
- && permanent.isCreature()
- && (permanent.getId().equals(getSourceId())
- || (permanent.getAbilities().contains(FlyingAbility.getInstance())))) {
- this.getEffects().clear();
- this.addEffect(new GainLifeEffect(permanent.getPower().getValue()));
- return true;
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
+ if (player == null || permanent == null) {
+ return false;
}
- return false;
- }
-
- @Override
- public String getRule() {
- return "Whenever {this} or another creature with flying enters the battlefield under your control, you may gain life equal to that creature's power.";
+ return player.gainLife(permanent.getPower().getValue(), game, source) > 0;
}
}
diff --git a/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java b/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java
index fd4d1baa2af..782302bb39c 100644
--- a/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java
+++ b/Mage.Sets/src/mage/cards/a/ArchonOfValorsReach.java
@@ -169,6 +169,11 @@ class ArchonOfValorsReachReplacementEffect extends ContinuousRuleModifyingEffect
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
+
+ if ((String) game.getState().getValue(source.getSourceId().toString() + "_cardtype") == null){
+ return false;
+ }
+
CardType cardType = ArchonOfValorsReachChoice.getType((String) game.getState().getValue(source.getSourceId().toString() + "_cardtype"));
// spell is not on the stack yet, so we have to check the card
Card card = game.getCard(event.getSourceId());
diff --git a/Mage.Sets/src/mage/cards/a/ArcticNishoba.java b/Mage.Sets/src/mage/cards/a/ArcticNishoba.java
index 5425eed0364..11fb4439dd1 100644
--- a/Mage.Sets/src/mage/cards/a/ArcticNishoba.java
+++ b/Mage.Sets/src/mage/cards/a/ArcticNishoba.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.OrCost;
import mage.constants.SubType;
import mage.abilities.keyword.TrampleAbility;
@@ -45,7 +45,7 @@ public final class ArcticNishoba extends CardImpl {
// When Arctic Nishoba dies, you gain 2 life for each age counter on it.
Effect effect = new GainLifeEffect(new MultipliedValue(new CountersSourceCount(CounterType.AGE), 2));
effect.setText("you gain 2 life for each age counter on it");
- this.addAbility(new DiesTriggeredAbility(effect));
+ this.addAbility(new DiesSourceTriggeredAbility(effect));
}
public ArcticNishoba(final ArcticNishoba card) {
diff --git a/Mage.Sets/src/mage/cards/a/ArenaRector.java b/Mage.Sets/src/mage/cards/a/ArenaRector.java
index b1fa212eb28..53510af308b 100644
--- a/Mage.Sets/src/mage/cards/a/ArenaRector.java
+++ b/Mage.Sets/src/mage/cards/a/ArenaRector.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
@@ -29,7 +29,7 @@ public final class ArenaRector extends CardImpl {
this.toughness = new MageInt(2);
// When Arena Rector dies, you may exile it. If you do, search your library for a planeswalker card, put it onto the battlefield, then shuffle your library.
- this.addAbility(new DiesTriggeredAbility(
+ this.addAbility(new DiesSourceTriggeredAbility(
new DoIfCostPaid(
new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(new FilterPlaneswalkerCard())),
new ExileSourceFromGraveCost(),
diff --git a/Mage.Sets/src/mage/cards/a/ArgivianRestoration.java b/Mage.Sets/src/mage/cards/a/ArgivianRestoration.java
index ba7aa7f660c..6332eb2124d 100644
--- a/Mage.Sets/src/mage/cards/a/ArgivianRestoration.java
+++ b/Mage.Sets/src/mage/cards/a/ArgivianRestoration.java
@@ -1,7 +1,5 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -9,18 +7,18 @@ import mage.constants.CardType;
import mage.filter.common.FilterArtifactCard;
import mage.target.common.TargetCardInYourGraveyard;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class ArgivianRestoration extends CardImpl {
public ArgivianRestoration(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{U}{U}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}{U}");
// Return target artifact card from your graveyard to the battlefield.
- this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect());
+ this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect(false, false));
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterArtifactCard("artifact card from your graveyard")));
}
diff --git a/Mage.Sets/src/mage/cards/a/ArmadaWurm.java b/Mage.Sets/src/mage/cards/a/ArmadaWurm.java
index c6fbc3025b7..64455089fcd 100644
--- a/Mage.Sets/src/mage/cards/a/ArmadaWurm.java
+++ b/Mage.Sets/src/mage/cards/a/ArmadaWurm.java
@@ -1,7 +1,5 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -10,10 +8,11 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.game.permanent.token.WurmToken2;
+import mage.game.permanent.token.WurmWithTrampleToken;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class ArmadaWurm extends CardImpl {
@@ -29,7 +28,7 @@ public final class ArmadaWurm extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// When Armada Wurm enters the battlefield, create a 5/5 green Wurm creature token with trample.
- this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WurmToken2()), false));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WurmWithTrampleToken()), false));
}
diff --git a/Mage.Sets/src/mage/cards/a/ArmoredAscension.java b/Mage.Sets/src/mage/cards/a/ArmoredAscension.java
index ad9a117331d..25b7a1516bb 100644
--- a/Mage.Sets/src/mage/cards/a/ArmoredAscension.java
+++ b/Mage.Sets/src/mage/cards/a/ArmoredAscension.java
@@ -34,11 +34,13 @@ public final class ArmoredAscension extends CardImpl {
this.subtype.add(SubType.AURA);
+ // Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
+ // Enchanted creature gets +1/+1 for each Plains you control and has flying.
PermanentsOnBattlefieldCount amount = new PermanentsOnBattlefieldCount(filter, 1);
SimpleStaticAbility ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(amount, amount, Duration.WhileOnBattlefield));
ability.addEffect(new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA));
diff --git a/Mage.Sets/src/mage/cards/a/ArtifactMutation.java b/Mage.Sets/src/mage/cards/a/ArtifactMutation.java
index 416308846b2..abc4b8b08c1 100644
--- a/Mage.Sets/src/mage/cards/a/ArtifactMutation.java
+++ b/Mage.Sets/src/mage/cards/a/ArtifactMutation.java
@@ -1,7 +1,5 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.abilities.dynamicvalue.common.TargetConvertedManaCost;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
@@ -11,19 +9,20 @@ import mage.constants.CardType;
import mage.game.permanent.token.SaprolingToken;
import mage.target.common.TargetArtifactPermanent;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class ArtifactMutation extends CardImpl {
public ArtifactMutation(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}{G}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{G}");
// Destroy target artifact. It can't be regenerated.
this.getSpellAbility().addEffect(new DestroyTargetEffect(true));
this.getSpellAbility().addTarget(new TargetArtifactPermanent());
+
// create X 1/1 green Saproling creature tokens, where X is that artifact's converted mana cost.
this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), TargetConvertedManaCost.instance).setText("create X 1/1 green Saproling creature tokens, where X is that artifact's converted mana cost"));
}
diff --git a/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java b/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java
index 1d8a35af4a3..a6848d62d51 100644
--- a/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java
+++ b/Mage.Sets/src/mage/cards/a/ArtisanOfForms.java
@@ -63,7 +63,7 @@ class ArtisanOfFormsApplyToPermanent extends ApplyToPermanent {
@Override
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
- permanent.addAbility(ArtisanOfForms.createAbility(), game);
+ permanent.addAbility(ArtisanOfForms.createAbility(), source.getSourceId(), game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/a/AsajjVentress.java b/Mage.Sets/src/mage/cards/a/AsajjVentress.java
index 3e2aa60f81b..4cf2118aab6 100644
--- a/Mage.Sets/src/mage/cards/a/AsajjVentress.java
+++ b/Mage.Sets/src/mage/cards/a/AsajjVentress.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.condition.common.HateCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.common.BlockedCreatureCount;
@@ -42,7 +42,7 @@ public final class AsajjVentress extends CardImpl {
BlockedCreatureCount value = new BlockedCreatureCount();
Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn, true);
effect.setText("she gets +1/+1 for each creature blocking her until end of turn");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
// Hate — Whenever Asajj Ventress attacks, if an opponent lost life from a source other than combat damage this turn, target creature blocks this turn if able.
Ability ability = new ConditionalInterveningIfTriggeredAbility(
diff --git a/Mage.Sets/src/mage/cards/a/AshcloudPhoenix.java b/Mage.Sets/src/mage/cards/a/AshcloudPhoenix.java
index c63e5d77abb..d4b74755af4 100644
--- a/Mage.Sets/src/mage/cards/a/AshcloudPhoenix.java
+++ b/Mage.Sets/src/mage/cards/a/AshcloudPhoenix.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
@@ -36,7 +36,7 @@ public final class AshcloudPhoenix extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Ashcloud Phoenix dies, return it to the battlefield face down under your control.
- this.addAbility(new DiesTriggeredAbility(new AshcloudPhoenixEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new AshcloudPhoenixEffect()));
// Morph {4}{R}{R}
this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{4}{R}{R}")));
diff --git a/Mage.Sets/src/mage/cards/a/AshenSkinZubera.java b/Mage.Sets/src/mage/cards/a/AshenSkinZubera.java
index 050b2493a30..79fb5cfd077 100644
--- a/Mage.Sets/src/mage/cards/a/AshenSkinZubera.java
+++ b/Mage.Sets/src/mage/cards/a/AshenSkinZubera.java
@@ -5,7 +5,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.ZuberasDiedDynamicValue;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class AshenSkinZubera extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(2);
- Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(ZuberasDiedDynamicValue.instance));
+ Ability ability = new DiesSourceTriggeredAbility(new DiscardTargetEffect(ZuberasDiedDynamicValue.instance));
ability.addTarget(new TargetOpponent());
this.addAbility(ability, new ZuberasDiedWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/a/AshlingThePilgrim.java b/Mage.Sets/src/mage/cards/a/AshlingThePilgrim.java
index edf24e4da50..9188c0d57e9 100644
--- a/Mage.Sets/src/mage/cards/a/AshlingThePilgrim.java
+++ b/Mage.Sets/src/mage/cards/a/AshlingThePilgrim.java
@@ -6,7 +6,9 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageEverythingEffect;
+import mage.abilities.effects.common.IfAbilityHasResolvedXTimesEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
+import mage.abilities.hint.common.AbilityResolutionCountHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -17,7 +19,6 @@ import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import mage.players.Player;
import mage.watchers.common.AbilityResolvedWatcher;
import java.util.UUID;
@@ -40,7 +41,8 @@ public final class AshlingThePilgrim extends CardImpl {
Ability ability = new SimpleActivatedAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl("{1}{R}")
);
- ability.addEffect(new AshlingThePilgrimEffect());
+ ability.addEffect(new IfAbilityHasResolvedXTimesEffect(Outcome.Damage, 3, new AshlingThePilgrimEffect()));
+ ability.addHint(AbilityResolutionCountHint.instance);
this.addAbility(ability, new AbilityResolvedWatcher());
}
@@ -58,8 +60,7 @@ class AshlingThePilgrimEffect extends OneShotEffect {
AshlingThePilgrimEffect() {
super(Outcome.Damage);
- this.staticText = "If this is the third time this ability has resolved this turn, " +
- "remove all +1/+1 counters from {this}, and it deals that much damage to each creature and each player";
+ this.staticText = "remove all +1/+1 counters from {this}, and it deals that much damage to each creature and each player";
}
private AshlingThePilgrimEffect(final AshlingThePilgrimEffect effect) {
@@ -73,20 +74,15 @@ class AshlingThePilgrimEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
- AbilityResolvedWatcher watcher = game.getState().getWatcher(AbilityResolvedWatcher.class);
- if (controller == null
- || sourcePermanent == null
- || watcher == null
- || !watcher.checkActivations(source, game)) {
- return false;
+ if (sourcePermanent != null) {
+ int counters = sourcePermanent.getCounters(game).getCount(CounterType.P1P1);
+ if (counters < 1) {
+ return false;
+ }
+ sourcePermanent.removeCounters(CounterType.P1P1.createInstance(counters), game);
+ return new DamageEverythingEffect(counters, StaticFilters.FILTER_PERMANENT_CREATURE).apply(game, source);
}
- int counters = sourcePermanent.getCounters(game).getCount(CounterType.P1P1);
- if (counters < 1) {
- return false;
- }
- sourcePermanent.removeCounters(CounterType.P1P1.createInstance(counters), game);
- return new DamageEverythingEffect(counters, StaticFilters.FILTER_PERMANENT_CREATURE).apply(game, source);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/a/AshmouthHound.java b/Mage.Sets/src/mage/cards/a/AshmouthHound.java
index 15e10029c72..e3e5ed4fb4f 100644
--- a/Mage.Sets/src/mage/cards/a/AshmouthHound.java
+++ b/Mage.Sets/src/mage/cards/a/AshmouthHound.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -19,13 +19,13 @@ public final class AshmouthHound extends CardImpl {
public AshmouthHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.ELEMENTAL);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// Whenever Ashmouth Hound blocks or becomes blocked by a creature, Ashmouth Hound deals 1 damage to that creature.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new DamageTargetEffect(1, true, "that creature"), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new DamageTargetEffect(1, true, "that creature"), false));
}
public AshmouthHound(final AshmouthHound card) {
diff --git a/Mage.Sets/src/mage/cards/a/AssembledAlphas.java b/Mage.Sets/src/mage/cards/a/AssembledAlphas.java
index 95a23a8ece7..03807132bbc 100644
--- a/Mage.Sets/src/mage/cards/a/AssembledAlphas.java
+++ b/Mage.Sets/src/mage/cards/a/AssembledAlphas.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetControllerEffect;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -27,7 +27,7 @@ public final class AssembledAlphas extends CardImpl {
this.toughness = new MageInt(5);
// Whenever Assembled Alphas blocks or becomes blocked by a creature, Assembled Alphas deals 3 damage to that creature and 3 damage to that creature's controller.
- Ability ability = new BlocksOrBecomesBlockedTriggeredAbility(
+ Ability ability = new BlocksOrBecomesBlockedSourceTriggeredAbility(
new DamageTargetEffect(3, true, "that creature"), StaticFilters.FILTER_PERMANENT_CREATURE, false, null, true);
Effect effect = new DamageTargetControllerEffect(3);
diff --git a/Mage.Sets/src/mage/cards/a/AttendantOfVraska.java b/Mage.Sets/src/mage/cards/a/AttendantOfVraska.java
index ca986d1948c..0222b630499 100644
--- a/Mage.Sets/src/mage/cards/a/AttendantOfVraska.java
+++ b/Mage.Sets/src/mage/cards/a/AttendantOfVraska.java
@@ -2,7 +2,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount;
@@ -38,7 +38,7 @@ public final class AttendantOfVraska extends CardImpl {
// When Attendant of Vraska dies, if you control a Vraska planeswalker, you gain life equal to Attendant of Vraska's power.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
- new DiesTriggeredAbility(new GainLifeEffect(
+ new DiesSourceTriggeredAbility(new GainLifeEffect(
new SourcePermanentPowerCount()
), false), new PermanentsOnTheBattlefieldCondition(filter),
"When {this} dies, if you control a Vraska planeswalker, "
diff --git a/Mage.Sets/src/mage/cards/a/AuraOfSilence.java b/Mage.Sets/src/mage/cards/a/AuraOfSilence.java
index 78336fd491c..23ae3bcc876 100644
--- a/Mage.Sets/src/mage/cards/a/AuraOfSilence.java
+++ b/Mage.Sets/src/mage/cards/a/AuraOfSilence.java
@@ -1,35 +1,42 @@
-
package mage.cards.a;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.effects.common.DestroyTargetEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
-import mage.cards.Card;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
import mage.filter.StaticFilters;
-import mage.game.Game;
+import mage.filter.predicate.Predicates;
import mage.target.TargetPermanent;
-import mage.util.CardUtil;
import java.util.UUID;
/**
- *
* @author emerald000
*/
public final class AuraOfSilence extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard("Artifact and enchantment spells");
+
+ static {
+ filter.add(Predicates.or(
+ CardType.ARTIFACT.getPredicate(),
+ CardType.ENCHANTMENT.getPredicate()));
+ }
+
public AuraOfSilence(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}");
// Artifact and enchantment spells your opponents cast cost {2} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AuraOfSilenceCostModificationEffect()));
-
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(2, filter, TargetController.OPPONENT)));
+
// Sacrifice Aura of Silence: Destroy target artifact or enchantment.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new SacrificeSourceCost());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
@@ -44,41 +51,4 @@ public final class AuraOfSilence extends CardImpl {
public AuraOfSilence copy() {
return new AuraOfSilence(this);
}
-}
-
-class AuraOfSilenceCostModificationEffect extends CostModificationEffectImpl {
-
- AuraOfSilenceCostModificationEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Artifact and enchantment spells your opponents cast cost {2} more to cast";
- }
-
- AuraOfSilenceCostModificationEffect(AuraOfSilenceCostModificationEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- Card card = game.getCard(abilityToModify.getSourceId());
- if (card != null && (card.isArtifact() || card.isEnchantment())) {
- return true;
- }
- }
- }
- return false;
- }
-
- @Override
- public AuraOfSilenceCostModificationEffect copy() {
- return new AuraOfSilenceCostModificationEffect(this);
- }
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/a/AuraThief.java b/Mage.Sets/src/mage/cards/a/AuraThief.java
index 9a148b7e92f..d44d77becb3 100644
--- a/Mage.Sets/src/mage/cards/a/AuraThief.java
+++ b/Mage.Sets/src/mage/cards/a/AuraThief.java
@@ -7,7 +7,7 @@ package mage.cards.a;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
@@ -43,7 +43,7 @@ public final class AuraThief extends CardImpl {
// When Aura Thief dies, you gain control of all enchantments. You don't get
// to move Auras.
- this.addAbility(new DiesTriggeredAbility(new AuraThiefDiesTriggeredEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new AuraThiefDiesTriggeredEffect()));
}
public AuraThief(final AuraThief card) {
diff --git a/Mage.Sets/src/mage/cards/a/AuspiciousAncestor.java b/Mage.Sets/src/mage/cards/a/AuspiciousAncestor.java
index 505daa753c9..09612cb5c47 100644
--- a/Mage.Sets/src/mage/cards/a/AuspiciousAncestor.java
+++ b/Mage.Sets/src/mage/cards/a/AuspiciousAncestor.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DoIfCostPaid;
@@ -36,7 +36,7 @@ public final class AuspiciousAncestor extends CardImpl {
this.toughness = new MageInt(3);
// When Auspicious Ancestor dies, you gain 3 life.
- this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(3), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(3), false));
// Whenever a player casts a white spell, you may pay {1}. If you do, you gain 1 life.
this.addAbility(new SpellCastAllTriggeredAbility(new DoIfCostPaid(new GainLifeEffect(1), new ManaCostsImpl("{1}")), filter, true));
}
diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfFury.java b/Mage.Sets/src/mage/cards/a/AvatarOfFury.java
index 9153c0a4f99..6489605608b 100644
--- a/Mage.Sets/src/mage/cards/a/AvatarOfFury.java
+++ b/Mage.Sets/src/mage/cards/a/AvatarOfFury.java
@@ -1,33 +1,41 @@
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.CostModificationType;
import mage.constants.Duration;
-import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
+import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
+import mage.filter.predicate.Predicates;
import mage.game.Game;
-import mage.util.CardUtil;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class AvatarOfFury extends CardImpl {
+ private static final FilterPermanent filter = new FilterPermanent("artifact, creature, or enchantment");
+
+ static {
+ filter.add(Predicates.or(CardType.ARTIFACT.getPredicate(),
+ CardType.CREATURE.getPredicate(),
+ CardType.ENCHANTMENT.getPredicate()));
+ }
+
public AvatarOfFury(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{R}{R}");
this.subtype.add(SubType.AVATAR);
@@ -36,9 +44,14 @@ public final class AvatarOfFury extends CardImpl {
this.toughness = new MageInt(6);
// If an opponent controls seven or more lands, Avatar of Fury costs {6} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.ALL, new AvatarOfFuryAdjustingCostsEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(6, AvatarOfFuryCondition.instance)
+ .setText("if an opponent controls seven or more lands, Avatar of Fury costs {6} less to cast"))
+ .addHint(new ConditionHint(AvatarOfFuryCondition.instance, "Opponent controls seven or more lands"))
+ );
+
// Flying
this.addAbility(FlyingAbility.getInstance());
+
// {R}: Avatar of Fury gets +1/+0 until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}")));
}
@@ -53,39 +66,22 @@ public final class AvatarOfFury extends CardImpl {
}
}
-class AvatarOfFuryAdjustingCostsEffect extends CostModificationEffectImpl {
+enum AvatarOfFuryCondition implements Condition {
- AvatarOfFuryAdjustingCostsEffect() {
- super(Duration.EndOfGame, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "If an opponent controls seven or more lands, {this} costs {6} less to cast";
- }
-
- AvatarOfFuryAdjustingCostsEffect(AvatarOfFuryAdjustingCostsEffect effect) {
- super(effect);
- }
+ instance;
@Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- CardUtil.reduceCost(abilityToModify, 6);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify.getSourceId().equals(source.getSourceId())
- && (abilityToModify instanceof SpellAbility)) {
- for (UUID playerId : game.getOpponents(abilityToModify.getControllerId())) {
- if (game.getBattlefield().countAll(StaticFilters.FILTER_LAND, playerId, game) > 6) {
- return true;
- }
+ public boolean apply(Game game, Ability source) {
+ for (UUID playerId : game.getOpponents(source.getControllerId())) {
+ if (game.getBattlefield().countAll(StaticFilters.FILTER_LAND, playerId, game) > 6) {
+ return true;
}
}
return false;
}
@Override
- public AvatarOfFuryAdjustingCostsEffect copy() {
- return new AvatarOfFuryAdjustingCostsEffect(this);
+ public String toString() {
+ return "an opponent controls seven or more lands";
}
-
}
diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfGrowth.java b/Mage.Sets/src/mage/cards/a/AvatarOfGrowth.java
index cd41b415dd6..0bee9d45c82 100644
--- a/Mage.Sets/src/mage/cards/a/AvatarOfGrowth.java
+++ b/Mage.Sets/src/mage/cards/a/AvatarOfGrowth.java
@@ -4,8 +4,9 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.common.OpponentsCount;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.cost.SpellCostReductionSourceForOpponentsEffect;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -35,7 +36,8 @@ public final class AvatarOfGrowth extends CardImpl {
this.toughness = new MageInt(4);
// This spell costs {1} less to cast for each opponent you have.
- this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceForOpponentsEffect("This spell costs {1} less to cast for each opponent you have")));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, OpponentsCount.instance)
+ .setText("This spell costs {1} less to cast for each opponent you have")));
// Trample
this.addAbility(TrampleAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfHope.java b/Mage.Sets/src/mage/cards/a/AvatarOfHope.java
index d1e82950fe5..08957746eec 100644
--- a/Mage.Sets/src/mage/cards/a/AvatarOfHope.java
+++ b/Mage.Sets/src/mage/cards/a/AvatarOfHope.java
@@ -1,22 +1,24 @@
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
import mage.abilities.effects.common.combat.CanBlockAdditionalCreatureEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
-import mage.util.CardUtil;
+
+import java.util.UUID;
/**
- *
* @author Plopman
*/
public final class AvatarOfHope extends CardImpl {
@@ -29,9 +31,14 @@ public final class AvatarOfHope extends CardImpl {
this.toughness = new MageInt(9);
// If you have 3 or less life, Avatar of Hope costs {6} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.ALL, new AvatarOfHopeAdjustingCostsEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(6, AvatarOfHopeCondition.instance)
+ .setText("if you have 3 or less life, Avatar of Hope costs {6} less to cast"))
+ .addHint(new ConditionHint(AvatarOfHopeCondition.instance))
+ );
+
// Flying
this.addAbility(FlyingAbility.getInstance());
+
// Avatar of Hope can block any number of creatures.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CanBlockAdditionalCreatureEffect(0)));
}
@@ -46,39 +53,21 @@ public final class AvatarOfHope extends CardImpl {
}
}
-class AvatarOfHopeAdjustingCostsEffect extends CostModificationEffectImpl {
+enum AvatarOfHopeCondition implements Condition {
- AvatarOfHopeAdjustingCostsEffect() {
- super(Duration.EndOfGame, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "If you have 3 or less life, {this} costs {6} less to cast";
- }
-
- AvatarOfHopeAdjustingCostsEffect(AvatarOfHopeAdjustingCostsEffect effect) {
- super(effect);
- }
+ instance;
@Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- CardUtil.reduceCost(abilityToModify, 6);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify.getSourceId().equals(source.getSourceId())
- && (abilityToModify instanceof SpellAbility)) {
- Player player = game.getPlayer(abilityToModify.getControllerId());
- if (player != null && player.getLife() < 4) {
- return true;
- }
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player != null && player.getLife() <= 3) {
+ return true;
}
-
return false;
}
@Override
- public AvatarOfHopeAdjustingCostsEffect copy() {
- return new AvatarOfHopeAdjustingCostsEffect(this);
+ public String toString() {
+ return "you have 3 or less life";
}
-
}
diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfMight.java b/Mage.Sets/src/mage/cards/a/AvatarOfMight.java
index 8c127b2a309..d051a3174d4 100644
--- a/Mage.Sets/src/mage/cards/a/AvatarOfMight.java
+++ b/Mage.Sets/src/mage/cards/a/AvatarOfMight.java
@@ -1,27 +1,30 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
-import mage.Mana;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.condition.Condition;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class AvatarOfMight extends CardImpl {
+ private static final Condition condition = new AvatarOfMightCondition();
+
public AvatarOfMight(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{G}{G}");
this.subtype.add(SubType.AVATAR);
@@ -29,7 +32,10 @@ public final class AvatarOfMight extends CardImpl {
this.toughness = new MageInt(8);
// If an opponent controls at least four more creatures than you, Avatar of Might costs {6} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new AvatarOfMightCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(6, condition)
+ .setText("If an opponent controls at least four more creatures than you, {this} costs {6} less to cast"))
+ .addHint(new ConditionHint(condition, "Opponent controls at least four more creatures than you"))
+ );
// Trample
this.addAbility(TrampleAbility.getInstance());
@@ -45,49 +51,17 @@ public final class AvatarOfMight extends CardImpl {
}
}
-class AvatarOfMightCostReductionEffect extends CostModificationEffectImpl {
-
- AvatarOfMightCostReductionEffect() {
- super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "If an opponent controls at least four more creatures than you, {this} costs {6} less to cast";
- }
-
- AvatarOfMightCostReductionEffect(final AvatarOfMightCostReductionEffect effect) {
- super(effect);
- }
+class AvatarOfMightCondition implements Condition {
@Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- Mana mana = spellAbility.getManaCostsToPay().getMana();
- if (mana.getGeneric() > 0) {
- int newCount = mana.getGeneric() - 6;
- if (newCount < 0) {
- newCount = 0;
- }
- mana.setGeneric(newCount);
- spellAbility.getManaCostsToPay().load(mana.toString());
- return true;
- }
- return false;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify.getSourceId().equals(source.getSourceId()) && (abilityToModify instanceof SpellAbility)) {
- int creatures = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game);
- for (UUID playerId : game.getOpponents(source.getControllerId())) {
- Player opponent = game.getPlayer(playerId);
- if (opponent != null && game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, opponent.getId(), game) >= creatures + 4) {
- return true;
- }
+ public boolean apply(Game game, Ability source) {
+ int creatures = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game);
+ for (UUID playerId : game.getOpponents(source.getControllerId())) {
+ Player opponent = game.getPlayer(playerId);
+ if (opponent != null && game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, opponent.getId(), game) >= creatures + 4) {
+ return true;
}
}
return false;
}
-
- @Override
- public AvatarOfMightCostReductionEffect copy() {
- return new AvatarOfMightCostReductionEffect(this);
- }
}
diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfWill.java b/Mage.Sets/src/mage/cards/a/AvatarOfWill.java
index 89651d2328a..d67fb660599 100644
--- a/Mage.Sets/src/mage/cards/a/AvatarOfWill.java
+++ b/Mage.Sets/src/mage/cards/a/AvatarOfWill.java
@@ -1,22 +1,20 @@
-
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
-import mage.Mana;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.condition.common.OpponentHasNoCardsInHandCondition;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.players.Player;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class AvatarOfWill extends CardImpl {
@@ -28,7 +26,10 @@ public final class AvatarOfWill extends CardImpl {
this.toughness = new MageInt(6);
// If an opponent has no cards in hand, Avatar of Will costs {6} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new AvatarOfWillCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(6, OpponentHasNoCardsInHandCondition.instance)
+ .setText("If an opponent has no cards in hand, Avatar of Will costs {6} less to cast")
+ ).addHint(new ConditionHint(OpponentHasNoCardsInHandCondition.instance, "Opponent has no cards in hand"))
+ );
// Flying
this.addAbility(FlyingAbility.getInstance());
@@ -43,49 +44,3 @@ public final class AvatarOfWill extends CardImpl {
return new AvatarOfWill(this);
}
}
-
-class AvatarOfWillCostReductionEffect extends CostModificationEffectImpl {
-
- AvatarOfWillCostReductionEffect() {
- super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "If an opponent has no cards in hand, {this} costs {6} less to cast";
- }
-
- AvatarOfWillCostReductionEffect(final AvatarOfWillCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- Mana mana = spellAbility.getManaCostsToPay().getMana();
- if (mana.getGeneric() > 0) {
- int newCount = mana.getGeneric() - 6;
- if (newCount < 0) {
- newCount = 0;
- }
- mana.setGeneric(newCount);
- spellAbility.getManaCostsToPay().load(mana.toString());
- return true;
- }
- return false;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify.getSourceId().equals(source.getSourceId())) {
- for (UUID playerId : game.getOpponents(source.getControllerId())) {
- Player opponent = game.getPlayer(playerId);
- if (opponent != null && opponent.getHand().isEmpty()) {
- return true;
- }
- }
- }
- return false;
- }
-
- @Override
- public AvatarOfWillCostReductionEffect copy() {
- return new AvatarOfWillCostReductionEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfWoe.java b/Mage.Sets/src/mage/cards/a/AvatarOfWoe.java
index a8f9ca18931..70911593e40 100644
--- a/Mage.Sets/src/mage/cards/a/AvatarOfWoe.java
+++ b/Mage.Sets/src/mage/cards/a/AvatarOfWoe.java
@@ -1,30 +1,36 @@
package mage.cards.a;
-import java.util.UUID;
import mage.MageInt;
-import mage.Mana;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount;
import mage.abilities.effects.common.DestroyTargetEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.FearAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class AvatarOfWoe extends CardImpl {
+ protected static final DynamicValue graveyardCount = new CardsInAllGraveyardsCount(StaticFilters.FILTER_CARD_CREATURE);
+ private static final Condition condition = new AvatarOfWoeCondition();
+
public AvatarOfWoe(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{B}{B}");
this.subtype.add(SubType.AVATAR);
@@ -32,12 +38,15 @@ public final class AvatarOfWoe extends CardImpl {
this.toughness = new MageInt(5);
// If there are ten or more creature cards total in all graveyards, Avatar of Woe costs {6} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new AvatarOfWoeCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(6, condition)
+ .setText("If there are ten or more creature cards total in all graveyards, {this} costs {6} less to cast"))
+ .addHint(new ValueHint("Creature cards in all graveyards", graveyardCount))
+ );
// Fear
this.addAbility(FearAbility.getInstance());
- // {tap}: Destroy target creature. It can't be regenerated.
+ // {T}: Destroy target creature. It can't be regenerated.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(true), new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
@@ -53,42 +62,13 @@ public final class AvatarOfWoe extends CardImpl {
}
}
-class AvatarOfWoeCostReductionEffect extends CostModificationEffectImpl {
-
- AvatarOfWoeCostReductionEffect() {
- super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "If there are ten or more creature cards total in all graveyards, {this} costs {6} less to cast";
- }
-
- AvatarOfWoeCostReductionEffect(final AvatarOfWoeCostReductionEffect effect) {
- super(effect);
- }
+class AvatarOfWoeCondition implements Condition {
@Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- Mana mana = spellAbility.getManaCostsToPay().getMana();
- if (mana.getGeneric() > 0) {
- int newCount = mana.getGeneric() - 6;
- if (newCount < 0) {
- newCount = 0;
- }
- mana.setGeneric(newCount);
- spellAbility.getManaCostsToPay().load(mana.toString());
+ public boolean apply(Game game, Ability source) {
+ if (AvatarOfWoe.graveyardCount.calculate(game, source, null) >= 10) {
return true;
}
return false;
}
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- return abilityToModify.getSourceId().equals(source.getSourceId())
- && (abilityToModify instanceof SpellAbility)
- && new CardsInAllGraveyardsCount(StaticFilters.FILTER_CARD_CREATURE).calculate(game, source, this) >= 10;
- }
-
- @Override
- public AvatarOfWoeCostReductionEffect copy() {
- return new AvatarOfWoeCostReductionEffect(this);
- }
}
diff --git a/Mage.Sets/src/mage/cards/a/AvenFisher.java b/Mage.Sets/src/mage/cards/a/AvenFisher.java
index 8ce46a7e9fd..7842c555fed 100644
--- a/Mage.Sets/src/mage/cards/a/AvenFisher.java
+++ b/Mage.Sets/src/mage/cards/a/AvenFisher.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -25,7 +25,7 @@ public final class AvenFisher extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.addAbility(FlyingAbility.getInstance());
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
}
public AvenFisher(final AvenFisher card) {
diff --git a/Mage.Sets/src/mage/cards/a/AvenGagglemaster.java b/Mage.Sets/src/mage/cards/a/AvenGagglemaster.java
new file mode 100644
index 00000000000..0ce91fdf8e9
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/a/AvenGagglemaster.java
@@ -0,0 +1,56 @@
+package mage.cards.a;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class AvenGagglemaster extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
+
+ static {
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ }
+
+ private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter, 2);
+
+ public AvenGagglemaster(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
+
+ this.subtype.add(SubType.BIRD);
+ this.subtype.add(SubType.WARRIOR);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(3);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // When Aven Gagglemaster enters the battlefield, you gain 2 life for each creature you control with flying.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(xValue)
+ .setText("you gain 2 life for each creature you control with flying")));
+ }
+
+ private AvenGagglemaster(final AvenGagglemaster card) {
+ super(card);
+ }
+
+ @Override
+ public AvenGagglemaster copy() {
+ return new AvenGagglemaster(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/a/AvengingAngel.java b/Mage.Sets/src/mage/cards/a/AvengingAngel.java
index 2397ba31092..5769a74414a 100644
--- a/Mage.Sets/src/mage/cards/a/AvengingAngel.java
+++ b/Mage.Sets/src/mage/cards/a/AvengingAngel.java
@@ -4,7 +4,7 @@ package mage.cards.a;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
@@ -33,7 +33,7 @@ public final class AvengingAngel extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Avenging Angel dies, you may put it on top of its owner's library.
- this.addAbility(new DiesTriggeredAbility(new AvengingAngelEffect(), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new AvengingAngelEffect(), true));
}
public AvengingAngel(final AvengingAngel card) {
diff --git a/Mage.Sets/src/mage/cards/a/AwakenerDruid.java b/Mage.Sets/src/mage/cards/a/AwakenerDruid.java
index e2fa750bf94..a14bb44b092 100644
--- a/Mage.Sets/src/mage/cards/a/AwakenerDruid.java
+++ b/Mage.Sets/src/mage/cards/a/AwakenerDruid.java
@@ -96,6 +96,7 @@ class AwakenerDruidToken extends TokenImpl {
super(token);
}
+ @Override
public AwakenerDruidToken copy() {
return new AwakenerDruidToken(this);
}
diff --git a/Mage.Sets/src/mage/cards/a/AyaraFirstOfLocthwain.java b/Mage.Sets/src/mage/cards/a/AyaraFirstOfLocthwain.java
index b7f6b297ca0..0e45252d447 100644
--- a/Mage.Sets/src/mage/cards/a/AyaraFirstOfLocthwain.java
+++ b/Mage.Sets/src/mage/cards/a/AyaraFirstOfLocthwain.java
@@ -3,7 +3,7 @@ package mage.cards.a;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
@@ -20,10 +20,10 @@ import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
+import mage.filter.predicate.permanent.AnotherPredicate;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
-import mage.filter.predicate.permanent.AnotherPredicate;
/**
* @author TheElk801
@@ -31,7 +31,7 @@ import mage.filter.predicate.permanent.AnotherPredicate;
public final class AyaraFirstOfLocthwain extends CardImpl {
private static final FilterPermanent filter
- = new FilterCreaturePermanent("{this} or another black creature");
+ = new FilterCreaturePermanent("black creature");
private static final FilterControlledPermanent filter2
= new FilterControlledCreaturePermanent("another black creature");
@@ -51,7 +51,9 @@ public final class AyaraFirstOfLocthwain extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Ayara, First of Locthwain or another black creature enters the battlefield under your control, each opponent loses 1 life and you gain 1 life.
- Ability ability = new EntersBattlefieldControlledTriggeredAbility(new LoseLifeOpponentsEffect(1), filter);
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new LoseLifeOpponentsEffect(1), filter, false, true
+ );
ability.addEffect(new GainLifeEffect(1).concatBy("and"));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/b/BINGO.java b/Mage.Sets/src/mage/cards/b/BINGO.java
index 185acbd19d8..d6d4b004a2e 100644
--- a/Mage.Sets/src/mage/cards/b/BINGO.java
+++ b/Mage.Sets/src/mage/cards/b/BINGO.java
@@ -39,7 +39,7 @@ public final class BINGO extends CardImpl {
public BINGO(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/b/BackForMore.java b/Mage.Sets/src/mage/cards/b/BackForMore.java
index 3ef46f510ed..26ed102c20f 100644
--- a/Mage.Sets/src/mage/cards/b/BackForMore.java
+++ b/Mage.Sets/src/mage/cards/b/BackForMore.java
@@ -2,18 +2,19 @@ package mage.cards.b;
import mage.MageObjectReference;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.TargetController;
+import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
@@ -48,6 +49,12 @@ public final class BackForMore extends CardImpl {
class BackForMoreEffect extends OneShotEffect {
+ private static final FilterPermanent filter = new FilterCreaturePermanent("creature you don't control");
+
+ static {
+ filter.add(TargetController.NOT_YOU.getControllerPredicate());
+ }
+
BackForMoreEffect() {
super(Outcome.Benefit);
staticText = "Return target creature card from your graveyard to the battlefield. " +
@@ -75,49 +82,13 @@ class BackForMoreEffect extends OneShotEffect {
if (permanent == null) {
return false;
}
- game.addDelayedTriggeredAbility(new BackForMoreReflexiveTriggeredAbility(
- new MageObjectReference(permanent, game)
- ), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class BackForMoreReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- private static final FilterPermanent filter = new FilterCreaturePermanent("creature you don't control");
-
- static {
- filter.add(TargetController.NOT_YOU.getControllerPredicate());
- }
-
- BackForMoreReflexiveTriggeredAbility(MageObjectReference mor) {
- super(new BackForMoreDamageEffect(mor), Duration.OneUse, false);
- this.addTarget(new TargetPermanent(0, 1, filter, false));
- }
-
- private BackForMoreReflexiveTriggeredAbility(final BackForMoreReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public BackForMoreReflexiveTriggeredAbility copy() {
- return new BackForMoreReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When you do, it fights up to one target creature you don't control.";
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new BackForMoreDamageEffect(new MageObjectReference(permanent, game)),
+ false, "it fights up to one target creature you don't control"
+ );
+ ability.addTarget(new TargetPermanent(0, 1, filter, false));
+ game.fireReflexiveTriggeredAbility(ability, source);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BadDeal.java b/Mage.Sets/src/mage/cards/b/BadDeal.java
new file mode 100644
index 00000000000..22116bb83c1
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BadDeal.java
@@ -0,0 +1,38 @@
+package mage.cards.b;
+
+import mage.abilities.dynamicvalue.common.StaticValue;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.LoseLifeAllPlayersEffect;
+import mage.abilities.effects.common.discard.DiscardEachPlayerEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.TargetController;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BadDeal extends CardImpl {
+
+ public BadDeal(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{B}");
+
+ // You draw two cards and each opponent discards two cards. Each player loses 2 life.
+ this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2).setText("You draw two cards"));
+ this.getSpellAbility().addEffect(new DiscardEachPlayerEffect(
+ StaticValue.get(2), false, TargetController.OPPONENT
+ ).concatBy("and"));
+ this.getSpellAbility().addEffect(new LoseLifeAllPlayersEffect(2).setText("Each player loses 2 life"));
+ }
+
+ private BadDeal(final BadDeal card) {
+ super(card);
+ }
+
+ @Override
+ public BadDeal copy() {
+ return new BadDeal(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/Balance.java b/Mage.Sets/src/mage/cards/b/Balance.java
index 153b24ecc5c..2c7ea4d675e 100644
--- a/Mage.Sets/src/mage/cards/b/Balance.java
+++ b/Mage.Sets/src/mage/cards/b/Balance.java
@@ -1,21 +1,10 @@
package mage.cards.b;
-import mage.abilities.Ability;
-import mage.abilities.effects.OneShotEffect;
-import mage.cards.*;
+import mage.abilities.effects.common.BalanceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
-import mage.filter.FilterCard;
-import mage.filter.common.FilterControlledCreaturePermanent;
-import mage.filter.common.FilterControlledLandPermanent;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
-import mage.target.common.TargetCardInHand;
-import mage.target.common.TargetControlledPermanent;
-import java.util.HashMap;
-import java.util.Map;
import java.util.UUID;
/**
@@ -39,139 +28,3 @@ public final class Balance extends CardImpl {
return new Balance(this);
}
}
-
-class BalanceEffect extends OneShotEffect {
-
- BalanceEffect() {
- super(Outcome.Sacrifice);
- staticText = "each player chooses a number of lands they control "
- + "equal to the number of lands controlled by the player "
- + "who controls the fewest, then sacrifices the rest. "
- + "Players discard cards and sacrifice creatures the same way";
- }
-
- BalanceEffect(final BalanceEffect effect) {
- super(effect);
- }
-
- @Override
- public BalanceEffect copy() {
- return new BalanceEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- //Lands
- int minLand = Integer.MAX_VALUE;
- Cards landsToSacrifice = new CardsImpl();
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int count = game.getBattlefield().countAll(new FilterControlledLandPermanent(), player.getId(), game);
- if (count < minLand) {
- minLand = count;
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- TargetControlledPermanent target = new TargetControlledPermanent(minLand, minLand, new FilterControlledLandPermanent("lands to keep"), true);
- if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) {
- for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledLandPermanent(), player.getId(), source.getSourceId(), game)) {
- if (permanent != null && !target.getTargets().contains(permanent.getId())) {
- landsToSacrifice.add(permanent);
- }
- }
- }
- }
- }
-
- for (UUID cardId : landsToSacrifice) {
- Permanent permanent = game.getPermanent(cardId);
- if (permanent != null) {
- permanent.sacrifice(source.getSourceId(), game);
- }
- }
-
- //Creatures
- int minCreature = Integer.MAX_VALUE;
- Cards creaturesToSacrifice = new CardsImpl();
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int count = game.getBattlefield().countAll(new FilterControlledCreaturePermanent(), player.getId(), game);
- if (count < minCreature) {
- minCreature = count;
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- TargetControlledPermanent target = new TargetControlledPermanent(minCreature, minCreature, new FilterControlledCreaturePermanent("creatures to keep"), true);
- if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) {
- for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), player.getId(), source.getSourceId(), game)) {
- if (permanent != null && !target.getTargets().contains(permanent.getId())) {
- creaturesToSacrifice.add(permanent);
- }
- }
- }
- }
- }
-
- for (UUID cardId : creaturesToSacrifice) {
- Permanent permanent = game.getPermanent(cardId);
- if (permanent != null) {
- permanent.sacrifice(source.getSourceId(), game);
- }
- }
-
- //Cards in hand
- int minCard = Integer.MAX_VALUE;
- Map cardsToDiscard = new HashMap<>(2);
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int count = player.getHand().size();
- if (count < minCard) {
- minCard = count;
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Cards cards = new CardsImpl();
- TargetCardInHand target = new TargetCardInHand(minCard, new FilterCard("cards to keep"));
- if (target.choose(Outcome.Discard, player.getId(), source.getSourceId(), game)) {
- for (Card card : player.getHand().getCards(game)) {
- if (card != null && !target.getTargets().contains(card.getId())) {
- cards.add(card);
- }
- }
- cardsToDiscard.put(playerId, cards);
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null && cardsToDiscard.get(playerId) != null) {
- for (UUID cardId : cardsToDiscard.get(playerId)) {
- Card card = game.getCard(cardId);
- player.discard(card, source, game);
-
- }
- }
- }
- return true;
- }
- return false;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/b/BalancingAct.java b/Mage.Sets/src/mage/cards/b/BalancingAct.java
index 2052ec14e87..d8cd45b70cd 100644
--- a/Mage.Sets/src/mage/cards/b/BalancingAct.java
+++ b/Mage.Sets/src/mage/cards/b/BalancingAct.java
@@ -1,10 +1,7 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
@@ -18,21 +15,21 @@ import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetControlledPermanent;
+import java.util.UUID;
+
/**
- *
* @author Plopman (Restore Balance), cbt33
*/
public final class BalancingAct extends CardImpl {
public BalancingAct(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{W}{W}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}{W}");
// Each player chooses a number of permanents they control equal to the number of permanents controlled by the player who controls the fewest, then sacrifices the rest. Each player discards cards the same way.
this.getSpellAbility().addEffect(new BalancingActEffect());
}
- public BalancingAct(final BalancingAct card) {
+ private BalancingAct(final BalancingAct card) {
super(card);
}
@@ -44,13 +41,12 @@ public final class BalancingAct extends CardImpl {
class BalancingActEffect extends OneShotEffect {
-
- public BalancingActEffect() {
+ BalancingActEffect() {
super(Outcome.Sacrifice);
staticText = "Each player chooses a number of permanents they control equal to the number of permanents controlled by the player who controls the fewest, then sacrifices the rest. Each player discards cards the same way";
}
- public BalancingActEffect(final BalancingActEffect effect) {
+ private BalancingActEffect(final BalancingActEffect effect) {
super(effect);
}
@@ -65,23 +61,23 @@ class BalancingActEffect extends OneShotEffect {
if (controller != null) {
int minPermanent = Integer.MAX_VALUE, minCard = Integer.MAX_VALUE;
// count minimal permanents
- for(UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)){
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
- if(player != null){
+ if (player != null) {
int count = game.getBattlefield().getActivePermanents(new FilterControlledPermanent(), player.getId(), source.getSourceId(), game).size();
- if(count < minPermanent){
+ if (count < minPermanent) {
minPermanent = count;
}
}
}
// sacrifice permanents over the minimum
- for(UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)){
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
- if(player != null){
+ if (player != null) {
TargetControlledPermanent target = new TargetControlledPermanent(minPermanent, minPermanent, new FilterControlledPermanent(), true);
- if(target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), game)){
- for(Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledPermanent(), player.getId(), source.getSourceId(), game)){
- if(permanent != null && !target.getTargets().contains(permanent.getId())){
+ if (target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), game)) {
+ for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledPermanent(), player.getId(), source.getSourceId(), game)) {
+ if (permanent != null && !target.getTargets().contains(permanent.getId())) {
permanent.sacrifice(source.getSourceId(), game);
}
}
@@ -90,29 +86,25 @@ class BalancingActEffect extends OneShotEffect {
}
// count minimal cards in hand
- for(UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)){
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
- if(player != null){
+ if (player != null) {
int count = player.getHand().size();
- if(count < minCard){
+ if (count < minCard) {
minCard = count;
}
}
}
-
+
// discard cards over the minimum
- for(UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)){
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
- if(player != null){
+ if (player != null) {
TargetCardInHand target = new TargetCardInHand(minCard, new FilterCard());
- if(target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), game)){
- Cards cards = player.getHand().copy();
- for(UUID cardUUID : cards){
- Card card = player.getHand().get(cardUUID, game);
- if(!target.getTargets().contains(cardUUID)){
- player.discard(card, source, game);
- }
- }
+ if (target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), game)) {
+ Cards cards = player.getHand().copy();
+ cards.removeIf(target.getTargets()::contains);
+ player.discard(cards, source, game);
}
}
}
diff --git a/Mage.Sets/src/mage/cards/b/Banehound.java b/Mage.Sets/src/mage/cards/b/Banehound.java
index 493e33caa61..20f196c29a9 100644
--- a/Mage.Sets/src/mage/cards/b/Banehound.java
+++ b/Mage.Sets/src/mage/cards/b/Banehound.java
@@ -19,7 +19,7 @@ public final class Banehound extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
this.subtype.add(SubType.NIGHTMARE);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/b/BantSojourners.java b/Mage.Sets/src/mage/cards/b/BantSojourners.java
index 85063e89a3f..1aa6ebb6dbb 100644
--- a/Mage.Sets/src/mage/cards/b/BantSojourners.java
+++ b/Mage.Sets/src/mage/cards/b/BantSojourners.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.CycleTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.CyclingAbility;
@@ -30,7 +30,7 @@ public final class BantSojourners extends CardImpl {
// When you cycle Bant Sojourners or it dies, you may create a 1/1 white Soldier creature token.
Ability ability1 = new CycleTriggeredAbility(new CreateTokenEffect(new SoldierToken()), true);
- Ability ability2 = new DiesTriggeredAbility(new CreateTokenEffect(new SoldierToken()), true);
+ Ability ability2 = new DiesSourceTriggeredAbility(new CreateTokenEffect(new SoldierToken()), true);
this.addAbility(ability1);
this.addAbility(ability2);
diff --git a/Mage.Sets/src/mage/cards/b/BarbedShocker.java b/Mage.Sets/src/mage/cards/b/BarbedShocker.java
index 0ae806c0d07..48177c00ffe 100644
--- a/Mage.Sets/src/mage/cards/b/BarbedShocker.java
+++ b/Mage.Sets/src/mage/cards/b/BarbedShocker.java
@@ -1,14 +1,11 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.TrampleAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -17,14 +14,15 @@ import mage.constants.SubType;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author markedagain
*/
public final class BarbedShocker extends CardImpl {
public BarbedShocker(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.INSECT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
@@ -37,7 +35,7 @@ public final class BarbedShocker extends CardImpl {
this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new BarbedShockerEffect(), false, true));
}
- public BarbedShocker(final BarbedShocker card) {
+ private BarbedShocker(final BarbedShocker card) {
super(card);
}
@@ -46,14 +44,15 @@ public final class BarbedShocker extends CardImpl {
return new BarbedShocker(this);
}
}
+
class BarbedShockerEffect extends OneShotEffect {
- public BarbedShockerEffect() {
+ BarbedShockerEffect() {
super(Outcome.Discard);
this.staticText = " that player discards all the cards in their hand, then draws that many cards";
}
- public BarbedShockerEffect(final BarbedShockerEffect effect) {
+ private BarbedShockerEffect(final BarbedShockerEffect effect) {
super(effect);
}
@@ -65,14 +64,11 @@ class BarbedShockerEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
- if (targetPlayer != null) {
- int count = targetPlayer.getHand().size();
- for (Card card : targetPlayer.getHand().getCards(game)) {
- targetPlayer.discard(card, source, game);
- }
- targetPlayer.drawCards(count, source.getSourceId(), game);
- return false;
- }
+ if (targetPlayer == null) {
+ return false;
+ }
+ int count = targetPlayer.discard(targetPlayer.getHand(), source, game).size();
+ targetPlayer.drawCards(count, source.getSourceId(), game);
return true;
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/b/Barishi.java b/Mage.Sets/src/mage/cards/b/Barishi.java
index 41c85f15c73..fa9196a7e4d 100644
--- a/Mage.Sets/src/mage/cards/b/Barishi.java
+++ b/Mage.Sets/src/mage/cards/b/Barishi.java
@@ -3,7 +3,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.constants.SubType;
@@ -31,7 +31,7 @@ public final class Barishi extends CardImpl {
this.toughness = new MageInt(3);
// When Barishi dies, exile Barishi, then shuffle all creature cards from your graveyard into your library.
- this.addAbility(new DiesTriggeredAbility(new BarishiEffect(), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new BarishiEffect(), false));
}
public Barishi(final Barishi card) {
diff --git a/Mage.Sets/src/mage/cards/b/BarrinTolarianArchmage.java b/Mage.Sets/src/mage/cards/b/BarrinTolarianArchmage.java
new file mode 100644
index 00000000000..77dc1727ab4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BarrinTolarianArchmage.java
@@ -0,0 +1,111 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.ReturnToHandTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
+import mage.filter.predicate.permanent.AnotherPredicate;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.ZoneChangeEvent;
+import mage.target.TargetPermanent;
+import mage.watchers.Watcher;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BarrinTolarianArchmage extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterCreatureOrPlaneswalkerPermanent("other target creature or planeswalker");
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ }
+
+ public BarrinTolarianArchmage(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WIZARD);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // When Barrin, Tolarian Archmage enters the battlefield, return up to one other target creature or planeswalker to its owner's hand.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect());
+ ability.addTarget(new TargetPermanent(0, 1, filter, false));
+ this.addAbility(ability);
+
+ // At the beginning of your end step, if a permanent was put into your hand from the battlefield this turn, draw a card.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfEndStepTriggeredAbility(
+ new DrawCardSourceControllerEffect(1), TargetController.YOU, false
+ ), BarrinTolarianArchmageCondition.instance, "At the beginning of your end step, " +
+ "if a permanent was put into your hand from the battlefield this turn, draw a card."
+ ), new BarrinTolarianArchmageWatcher());
+ }
+
+ private BarrinTolarianArchmage(final BarrinTolarianArchmage card) {
+ super(card);
+ }
+
+ @Override
+ public BarrinTolarianArchmage copy() {
+ return new BarrinTolarianArchmage(this);
+ }
+}
+
+enum BarrinTolarianArchmageCondition implements Condition {
+ instance;
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ BarrinTolarianArchmageWatcher watcher = game.getState().getWatcher(BarrinTolarianArchmageWatcher.class);
+ return watcher != null && watcher.checkPlayer(source.getControllerId());
+ }
+}
+
+class BarrinTolarianArchmageWatcher extends Watcher {
+
+ private final Set playerSet = new HashSet<>();
+
+ BarrinTolarianArchmageWatcher() {
+ super(WatcherScope.GAME);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() != GameEvent.EventType.ZONE_CHANGE) {
+ return;
+ }
+ ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
+ if (zEvent.getFromZone() == Zone.BATTLEFIELD
+ && zEvent.getToZone() == Zone.HAND) {
+ playerSet.add(zEvent.getTarget().getOwnerId());
+ }
+ }
+
+ @Override
+ public void reset() {
+ playerSet.clear();
+ super.reset();
+ }
+
+ boolean checkPlayer(UUID playerId) {
+ return playerSet.contains(playerId);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BarteredCow.java b/Mage.Sets/src/mage/cards/b/BarteredCow.java
index 07fb03f4e69..9675188862e 100644
--- a/Mage.Sets/src/mage/cards/b/BarteredCow.java
+++ b/Mage.Sets/src/mage/cards/b/BarteredCow.java
@@ -2,7 +2,7 @@ package mage.cards.b;
import mage.MageInt;
import mage.MageObject;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DiscardCardControllerTriggeredAbility;
@@ -41,7 +41,7 @@ public final class BarteredCow extends CardImpl {
// When Bartered Cow dies or when you discard it, create a Food token.
this.addAbility(new OrTriggeredAbility(
Zone.ALL, new CreateTokenEffect(new FoodToken()), false,
- "When {this} dies or when you discard it, ", new DiesTriggeredAbility((Effect) null),
+ "When {this} dies or when you discard it, ", new DiesSourceTriggeredAbility((Effect) null),
new DiscardCardControllerTriggeredAbility(null, false, filter)
));
}
diff --git a/Mage.Sets/src/mage/cards/b/BasriDevotedPaladin.java b/Mage.Sets/src/mage/cards/b/BasriDevotedPaladin.java
new file mode 100644
index 00000000000..c484ec5995a
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BasriDevotedPaladin.java
@@ -0,0 +1,113 @@
+package mage.cards.b;
+
+import mage.abilities.Ability;
+import mage.abilities.DelayedTriggeredAbility;
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
+import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.effects.common.counter.AddCountersTargetEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.abilities.keyword.VigilanceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.counters.CounterType;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.target.common.TargetCreaturePermanent;
+import mage.target.targetpointer.FixedTarget;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class BasriDevotedPaladin extends CardImpl {
+
+ public BasriDevotedPaladin(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{W}{W}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.BASRI);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
+
+ // +1: Put a +1/+1 counter on up to one target creature. It gains vigilance until end of turn.
+ Ability ability = new LoyaltyAbility(new AddCountersTargetEffect(
+ CounterType.P1P1.createInstance()
+ ).setText("Put a +1/+1 counter on up to one target creature"), 1);
+ ability.addEffect(new GainAbilityTargetEffect(
+ VigilanceAbility.getInstance(), Duration.EndOfTurn
+ ).setText("It gains vigilance until end of turn"));
+ ability.addTarget(new TargetCreaturePermanent(0, 1));
+ this.addAbility(ability);
+
+ // −1: Whenever a creature attacks this turn, put a +1/+1 counter on it.
+ this.addAbility(new LoyaltyAbility(new CreateDelayedTriggeredAbilityEffect(new BasriDevotedPaladinTriggeredAbility()), -1));
+
+ // −6: Creatures you control get +2/+2 and gain flying until end of turn.
+ Effect effect = new BoostControlledEffect(2, 2, Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE);
+ effect.setText("Creatures you control get +2/+2");
+ LoyaltyAbility ultimateAbility = new LoyaltyAbility(effect, -6);
+ effect = new GainAbilityControlledEffect(FlyingAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURE);
+ effect.setText("and gain flying until end of turn");
+ ultimateAbility.addEffect(effect);
+ this.addAbility(ultimateAbility);
+ }
+
+ private BasriDevotedPaladin(final BasriDevotedPaladin card) {
+ super(card);
+ }
+
+ @Override
+ public BasriDevotedPaladin copy() {
+ return new BasriDevotedPaladin(this);
+ }
+}
+
+class BasriDevotedPaladinTriggeredAbility extends DelayedTriggeredAbility {
+
+ public BasriDevotedPaladinTriggeredAbility() {
+ super(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), Duration.EndOfTurn, false);
+ }
+
+ public BasriDevotedPaladinTriggeredAbility(BasriDevotedPaladinTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public BasriDevotedPaladinTriggeredAbility copy() {
+ return new BasriDevotedPaladinTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ Permanent permanent = game.getPermanent(event.getSourceId());
+ if (permanent != null) {
+ for (Effect effect : getEffects()) {
+ effect.setTargetPointer(new FixedTarget(permanent, game));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever a creature attacks this turn, put a +1/+1 counter on it.";
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/b/BasriKet.java b/Mage.Sets/src/mage/cards/b/BasriKet.java
new file mode 100644
index 00000000000..ea8957545d8
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BasriKet.java
@@ -0,0 +1,119 @@
+package mage.cards.b;
+
+import mage.abilities.Ability;
+import mage.abilities.DelayedTriggeredAbility;
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.GetEmblemEffect;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.effects.common.counter.AddCountersTargetEffect;
+import mage.abilities.keyword.IndestructibleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.counters.CounterType;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.permanent.TokenPredicate;
+import mage.game.Game;
+import mage.game.command.emblems.BasriKetEmblem;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.game.permanent.token.SoldierToken;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class BasriKet extends CardImpl {
+
+ public BasriKet(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{W}{W}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.BASRI);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
+
+ // +1: Put a +1/+1 counter on up to one target creature. It gains indestructible until end of turn.
+ Ability ability = new LoyaltyAbility(new AddCountersTargetEffect(
+ CounterType.P1P1.createInstance()
+ ).setText("Put a +1/+1 counter on up to one target creature"), 1);
+ ability.addEffect(new GainAbilityTargetEffect(
+ IndestructibleAbility.getInstance(), Duration.EndOfTurn
+ ).setText("It gains indestructible until end of turn"));
+ ability.addTarget(new TargetCreaturePermanent(0, 1));
+ this.addAbility(ability);
+
+ // −2: Whenever one or more nontoken creatures attack this turn, create that many 1/1 white Soldier creature tokens that are tapped and attacking.
+ this.addAbility(new LoyaltyAbility(new CreateDelayedTriggeredAbilityEffect(new BasriKetTriggeredAbility()), -2));
+
+ // −6: You get an emblem with "At the beginning of combat on your turn, create a 1/1 white Soldier creature token, then put a +1/+1 counter on each creature you control."
+ this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new BasriKetEmblem()), -6));
+ }
+
+ private BasriKet(final BasriKet card) {
+ super(card);
+ }
+
+ @Override
+ public BasriKet copy() {
+ return new BasriKet(this);
+ }
+}
+
+class BasriKetTriggeredAbility extends DelayedTriggeredAbility {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature");
+
+ static {
+ filter.add(Predicates.not(TokenPredicate.instance));
+ }
+
+ public BasriKetTriggeredAbility() {
+ super(null, Duration.EndOfTurn, false);
+ }
+
+ public BasriKetTriggeredAbility(BasriKetTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public BasriKetTriggeredAbility copy() {
+ return new BasriKetTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ int attackingNonTokens = 0;
+ for (UUID attacker : game.getCombat().getAttackers()) {
+ Permanent permanent = game.getPermanent(attacker);
+ if (filter.match(permanent, game)) {
+ attackingNonTokens++;
+ }
+ }
+ if (attackingNonTokens > 0) {
+ this.getEffects().clear();
+ addEffect(new CreateTokenEffect(new SoldierToken(), attackingNonTokens, true, true));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever one or more nontoken creatures attack this turn, create that many 1/1 white Soldier creature tokens that are tapped and attacking.";
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/b/BasrisAcolyte.java b/Mage.Sets/src/mage/cards/b/BasrisAcolyte.java
new file mode 100644
index 00000000000..a1e1a2e5203
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BasrisAcolyte.java
@@ -0,0 +1,59 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.counter.AddCountersTargetEffect;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.permanent.AnotherPredicate;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BasrisAcolyte extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledCreaturePermanent("other creatures you control");
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ }
+
+ public BasrisAcolyte(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
+
+ this.subtype.add(SubType.CAT);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Lifelink
+ this.addAbility(LifelinkAbility.getInstance());
+
+ // When Basri's Acolyte enters the battlefield, put a +1/+1 counter on each of up to two other target creatures you control.
+ Ability ability = new EntersBattlefieldTriggeredAbility(
+ new AddCountersTargetEffect(CounterType.P1P1.createInstance())
+ .setText("put a +1/+1 counter on each of up to two other target creatures you control")
+ );
+ ability.addTarget(new TargetPermanent(0, 2, filter, false));
+ this.addAbility(ability);
+ }
+
+ private BasrisAcolyte(final BasrisAcolyte card) {
+ super(card);
+ }
+
+ @Override
+ public BasrisAcolyte copy() {
+ return new BasrisAcolyte(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BasrisAegis.java b/Mage.Sets/src/mage/cards/b/BasrisAegis.java
new file mode 100644
index 00000000000..e0dbee48d23
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BasrisAegis.java
@@ -0,0 +1,46 @@
+package mage.cards.b;
+
+import mage.abilities.effects.common.counter.AddCountersTargetEffect;
+import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.counters.CounterType;
+import mage.filter.FilterCard;
+import mage.filter.predicate.mageobject.NamePredicate;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class BasrisAegis extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard("Basri, Devoted Paladin");
+
+ static {
+ filter.add(new NamePredicate("Basri, Devoted Paladin"));
+ }
+
+ public BasrisAegis(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}{W}");
+
+ // Put a +1/+1 counter on each of up to two target creatures. You may search your library and/or graveyard for a card named Basri, Devoted Paladin, reveal it, and put it into your hand. If you search your library this way, shuffle it.
+ this.getSpellAbility().addEffect(new AddCountersTargetEffect(
+ CounterType.P1P1.createInstance()
+ ).setText("Put a +1/+1 counter on each of up to two target creatures"));
+ this.getSpellAbility().addEffect(new SearchLibraryGraveyardPutInHandEffect(filter, false, true));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2));
+ }
+
+ private BasrisAegis(final BasrisAegis card) {
+ super(card);
+ }
+
+ @Override
+ public BasrisAegis copy() {
+ return new BasrisAegis(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BasrisLieutenant.java b/Mage.Sets/src/mage/cards/b/BasrisLieutenant.java
new file mode 100644
index 00000000000..330eec1325b
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BasrisLieutenant.java
@@ -0,0 +1,77 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.common.DiesThisOrAnotherCreatureTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.counter.AddCountersTargetEffect;
+import mage.abilities.keyword.ProtectionAbility;
+import mage.abilities.keyword.VigilanceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.counters.CounterType;
+import mage.filter.FilterObject;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.MulticoloredPredicate;
+import mage.filter.predicate.permanent.CounterPredicate;
+import mage.game.permanent.token.KnightToken;
+import mage.target.common.TargetControlledCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class BasrisLieutenant extends CardImpl {
+
+ private static final FilterObject multicoloredFilter = new FilterObject<>("multicolored");
+ private static final FilterCreaturePermanent controlledCreatureWithP1P1CounterFilter = new FilterCreaturePermanent("creature you control");
+
+ static {
+ multicoloredFilter.add(MulticoloredPredicate.instance);
+ controlledCreatureWithP1P1CounterFilter.add(TargetController.YOU.getControllerPredicate());
+ controlledCreatureWithP1P1CounterFilter.add(new CounterPredicate(CounterType.P1P1));
+ }
+
+ public BasrisLieutenant(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.KNIGHT);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(4);
+
+ // Vigilance, protection from multicolored
+ this.addAbility(VigilanceAbility.getInstance());
+
+ // protection from multicolored
+ this.addAbility(new ProtectionAbility(multicoloredFilter));
+
+ // When Basri's Lieutenant enters the battlefield, put a +1/+1 counter on target creature you control.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
+ ability.addTarget(new TargetControlledCreaturePermanent());
+ this.addAbility(ability);
+
+ // Whenever Basri's Lieutenant or another creature you control dies, if it had a +1/+1 counter on it, create a 2/2 white Knight creature token with vigilance.
+ this.addAbility(new DiesThisOrAnotherCreatureTriggeredAbility(
+ new CreateTokenEffect(new KnightToken()).setText("if it had a +1/+1 counter on it, create a 2/2 white Knight creature token with vigilance"),
+ false,
+ controlledCreatureWithP1P1CounterFilter
+ ));
+ }
+
+ private BasrisLieutenant(final BasrisLieutenant card) {
+ super(card);
+ }
+
+ @Override
+ public BasrisLieutenant copy() {
+ return new BasrisLieutenant(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BasrisSolidarity.java b/Mage.Sets/src/mage/cards/b/BasrisSolidarity.java
new file mode 100644
index 00000000000..3af3b9c8148
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BasrisSolidarity.java
@@ -0,0 +1,34 @@
+package mage.cards.b;
+
+import mage.abilities.effects.common.counter.AddCountersAllEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.counters.CounterType;
+import mage.filter.StaticFilters;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BasrisSolidarity extends CardImpl {
+
+ public BasrisSolidarity(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{W}");
+
+ // Put a +1/+1 counter on each creature you control.
+ this.getSpellAbility().addEffect(new AddCountersAllEffect(
+ CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE
+ ));
+ }
+
+ private BasrisSolidarity(final BasrisSolidarity card) {
+ super(card);
+ }
+
+ @Override
+ public BasrisSolidarity copy() {
+ return new BasrisSolidarity(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BazaarTrademage.java b/Mage.Sets/src/mage/cards/b/BazaarTrademage.java
index e2cdeab2071..847ce58f667 100644
--- a/Mage.Sets/src/mage/cards/b/BazaarTrademage.java
+++ b/Mage.Sets/src/mage/cards/b/BazaarTrademage.java
@@ -1,7 +1,7 @@
package mage.cards.b;
import mage.MageInt;
-import mage.abilities.common.EntersBattlefieldAbility;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class BazaarTrademage extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Bazaar Trademage enters the battlefield, draw two cards, then discard three cards.
- this.addAbility(new EntersBattlefieldAbility(new DrawDiscardControllerEffect(2, 3)));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawDiscardControllerEffect(2, 3)));
}
private BazaarTrademage(final BazaarTrademage card) {
diff --git a/Mage.Sets/src/mage/cards/b/BearerOfTheHeavens.java b/Mage.Sets/src/mage/cards/b/BearerOfTheHeavens.java
index d935f234c4a..0cdf4f2efbe 100644
--- a/Mage.Sets/src/mage/cards/b/BearerOfTheHeavens.java
+++ b/Mage.Sets/src/mage/cards/b/BearerOfTheHeavens.java
@@ -3,7 +3,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.DelayedTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -31,7 +31,7 @@ public final class BearerOfTheHeavens extends CardImpl {
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT));
Effect effect = new CreateDelayedTriggeredAbilityEffect(delayedAbility);
effect.setText("destroy all permanents at the beginning of the next end step");
- this.addAbility(new DiesTriggeredAbility(effect, false));
+ this.addAbility(new DiesSourceTriggeredAbility(effect, false));
}
public BearerOfTheHeavens(final BearerOfTheHeavens card) {
diff --git a/Mage.Sets/src/mage/cards/b/BedlamReveler.java b/Mage.Sets/src/mage/cards/b/BedlamReveler.java
index 6f6175f7ccf..5e4a2b29cc6 100644
--- a/Mage.Sets/src/mage/cards/b/BedlamReveler.java
+++ b/Mage.Sets/src/mage/cards/b/BedlamReveler.java
@@ -1,4 +1,3 @@
-
package mage.cards.b;
import mage.MageInt;
@@ -8,7 +7,7 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
-import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
import mage.abilities.effects.common.discard.DiscardHandControllerEffect;
import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.ProwessAbility;
@@ -26,27 +25,25 @@ import java.util.UUID;
*/
public final class BedlamReveler extends CardImpl {
- private static final DynamicValue cardsCount = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
-
public BedlamReveler(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{R}{R}");
this.subtype.add(SubType.DEVIL, SubType.HORROR);
this.power = new MageInt(3);
this.toughness = new MageInt(4);
- // Bedlam Reveler costs {1} less to cast for each instant or sorcery card in your graveyard.
- this.addAbility(new SimpleStaticAbility(
- Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY)
- ).addHint(new ValueHint("Instant and sorcery cards in your graveyard", cardsCount)));
+ // This spell costs {1} less to cast for each instant and sorcery card in your graveyard.
+ DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
+ ability.setRuleAtTheTop(true);
+ ability.addHint(new ValueHint("Instant or sourcery card in your graveyard", xValue));
+ this.addAbility(ability);
// Prowess
this.addAbility(new ProwessAbility());
// When Bedlam Reveler enters the battlefield, discard your hand, then draw three cards.
- Ability ability = new EntersBattlefieldTriggeredAbility(
- new DiscardHandControllerEffect().setText("discard your hand,")
- );
- ability.addEffect(new DrawCardSourceControllerEffect(3).setText("then draw three cards"));
+ ability = new EntersBattlefieldTriggeredAbility(new DiscardHandControllerEffect());
+ ability.addEffect(new DrawCardSourceControllerEffect(3).concatBy(", then"));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java b/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java
index 4ef63a42815..ed65fe16d84 100644
--- a/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java
+++ b/Mage.Sets/src/mage/cards/b/BelltowerSphinx.java
@@ -85,6 +85,6 @@ class BelltowerSphinxEffect extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever a source deals damage to {this}, that source's controller puts that many cards from the top of their library into their graveyard.";
+ return "Whenever a source deals damage to {this}, that source's controller mills that many cards.";
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BenevolentOffering.java b/Mage.Sets/src/mage/cards/b/BenevolentOffering.java
index 1a708b23439..1e4ea4310b1 100644
--- a/Mage.Sets/src/mage/cards/b/BenevolentOffering.java
+++ b/Mage.Sets/src/mage/cards/b/BenevolentOffering.java
@@ -1,7 +1,5 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@@ -19,8 +17,9 @@ import mage.target.Target;
import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class BenevolentOffering extends CardImpl {
@@ -69,10 +68,10 @@ class BenevolentOfferingEffect1 extends OneShotEffect {
target.choose(Outcome.Sacrifice, source.getControllerId(), source.getSourceId(), game);
Player opponent = game.getPlayer(target.getFirstTarget());
if (opponent != null) {
- Effect effect = new CreateTokenTargetEffect(new SpiritWhiteToken("C14"), 3);
+ Effect effect = new CreateTokenTargetEffect(new SpiritWhiteToken(), 3);
effect.setTargetPointer(new FixedTarget(opponent.getId()));
effect.apply(game, source);
- new CreateTokenEffect(new SpiritWhiteToken("C14"), 3).apply(game, source);
+ new CreateTokenEffect(new SpiritWhiteToken(), 3).apply(game, source);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BenthicExplorers.java b/Mage.Sets/src/mage/cards/b/BenthicExplorers.java
index 8e9d18a9899..9e9ad151288 100644
--- a/Mage.Sets/src/mage/cards/b/BenthicExplorers.java
+++ b/Mage.Sets/src/mage/cards/b/BenthicExplorers.java
@@ -4,7 +4,6 @@ import mage.MageInt;
import mage.Mana;
import mage.abilities.Abilities;
import mage.abilities.Ability;
-import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.common.TapSourceCost;
@@ -22,7 +21,6 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetLandPermanent;
import mage.util.CardUtil;
-
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -48,8 +46,10 @@ public final class BenthicExplorers extends CardImpl {
this.toughness = new MageInt(4);
// {tap}, Untap a tapped land an opponent controls: Add one mana of any type that land could produce.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BenthicExplorersManaEffect(), new TapSourceCost());
- ability.addCost(new BenthicExplorersCost(new TargetLandPermanent(filter)));
+ Ability ability = new BenthicExplorersManaAbility();
+ TargetLandPermanent targetOpponentLand = new TargetLandPermanent(filter);
+ targetOpponentLand.setNotTarget(true); // not a target, it is chosen
+ ability.addCost(new BenthicExplorersCost(targetOpponentLand));
this.addAbility(ability);
}
@@ -107,6 +107,22 @@ class BenthicExplorersCost extends CostImpl {
}
+class BenthicExplorersManaAbility extends ActivatedManaAbilityImpl {
+
+ BenthicExplorersManaAbility() {
+ super(Zone.BATTLEFIELD, new BenthicExplorersManaEffect(), new TapSourceCost());
+ }
+
+ private BenthicExplorersManaAbility(BenthicExplorersManaAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public BenthicExplorersManaAbility copy() {
+ return new BenthicExplorersManaAbility(this);
+ }
+}
+
class BenthicExplorersManaEffect extends ManaEffect {
public BenthicExplorersManaEffect() {
@@ -226,7 +242,6 @@ class BenthicExplorersManaEffect extends ManaEffect {
}
Permanent land = (Permanent) game.getState().getValue("UntapTargetCost" + source.getSourceId().toString());
if (land != null) {
- System.out.println("The land is " + land.getName());
Abilities mana = land.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD);
for (ActivatedManaAbilityImpl ability : mana) {
if (ability.definesMana(game)) {
@@ -236,7 +251,6 @@ class BenthicExplorersManaEffect extends ManaEffect {
}
}
}
- System.out.println("The types : " + types.toString());
return types;
}
diff --git a/Mage.Sets/src/mage/cards/b/BibFortuna.java b/Mage.Sets/src/mage/cards/b/BibFortuna.java
index c2a33363c8b..8ac710afa35 100644
--- a/Mage.Sets/src/mage/cards/b/BibFortuna.java
+++ b/Mage.Sets/src/mage/cards/b/BibFortuna.java
@@ -4,7 +4,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.abilities.effects.common.ShuffleLibrarySourceEffect;
@@ -35,7 +35,7 @@ public final class BibFortuna extends CardImpl {
this.addAbility(ability);
// When Bib Fortuna dies shuffle your library.
- this.addAbility(new DiesTriggeredAbility(new ShuffleLibrarySourceEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new ShuffleLibrarySourceEffect()));
}
public BibFortuna(final BibFortuna card) {
diff --git a/Mage.Sets/src/mage/cards/b/BileBlight.java b/Mage.Sets/src/mage/cards/b/BileBlight.java
index 0b237561908..77b3e4f0fbc 100644
--- a/Mage.Sets/src/mage/cards/b/BileBlight.java
+++ b/Mage.Sets/src/mage/cards/b/BileBlight.java
@@ -61,7 +61,7 @@ class BileBlightEffect extends BoostAllEffect {
} else {
String name = target.getName();
for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
- if (CardUtil.haveSameNames(perm.getName(), name)) {
+ if (CardUtil.haveSameNames(perm, name, game)) {
affectedObjectList.add(new MageObjectReference(perm, game));
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BiomancersFamiliar.java b/Mage.Sets/src/mage/cards/b/BiomancersFamiliar.java
index b6e4df29f6d..eb1b89e658f 100644
--- a/Mage.Sets/src/mage/cards/b/BiomancersFamiliar.java
+++ b/Mage.Sets/src/mage/cards/b/BiomancersFamiliar.java
@@ -86,19 +86,7 @@ class BiomancersFamiliarCostReductionEffect extends CostModificationEffectImpl {
if (reduceMax <= 0) {
return true;
}
- ChoiceImpl choice = new ChoiceImpl(true);
- Set set = new LinkedHashSet<>();
-
- for (int i = 0; i <= reduceMax; i++) {
- set.add(String.valueOf(i));
- }
- choice.setChoices(set);
- choice.setMessage("Reduce ability cost");
- if (!controller.choose(Outcome.Benefit, choice, game)) {
- return false;
- }
- int reduce = Integer.parseInt(choice.getChoice());
- CardUtil.reduceCost(abilityToModify, reduce);
+ CardUtil.reduceCost(abilityToModify, reduceMax);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/b/BishopOfTheBloodstained.java b/Mage.Sets/src/mage/cards/b/BishopOfTheBloodstained.java
index 7454450cfde..d36f35dd5a3 100644
--- a/Mage.Sets/src/mage/cards/b/BishopOfTheBloodstained.java
+++ b/Mage.Sets/src/mage/cards/b/BishopOfTheBloodstained.java
@@ -1,7 +1,5 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -15,8 +13,9 @@ import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class BishopOfTheBloodstained extends CardImpl {
@@ -36,7 +35,7 @@ public final class BishopOfTheBloodstained extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(3);
- // When Bishop of the Bloodstained enters the battlefield, target opponent loses 1 life for each vampire you control.
+ // When Bishop of the Bloodstained enters the battlefield, target opponent loses 1 life for each Vampire you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(new PermanentsOnBattlefieldCount(filter)));
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/b/BitterheartWitch.java b/Mage.Sets/src/mage/cards/b/BitterheartWitch.java
index 4527fc3c3a4..2b4b0623a4a 100644
--- a/Mage.Sets/src/mage/cards/b/BitterheartWitch.java
+++ b/Mage.Sets/src/mage/cards/b/BitterheartWitch.java
@@ -4,7 +4,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.cards.Card;
@@ -36,7 +36,7 @@ public final class BitterheartWitch extends CardImpl {
this.addAbility(DeathtouchAbility.getInstance());
// When Bitterheart Witch dies, you may search your library for a Curse card, put it onto the battlefield attached to target player, then shuffle your library.
- Ability ability = new DiesTriggeredAbility(new BitterheartWitchEffect(), true);
+ Ability ability = new DiesSourceTriggeredAbility(new BitterheartWitchEffect(), true);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/b/BlackCat.java b/Mage.Sets/src/mage/cards/b/BlackCat.java
index d6f263c9072..f12607a99c8 100644
--- a/Mage.Sets/src/mage/cards/b/BlackCat.java
+++ b/Mage.Sets/src/mage/cards/b/BlackCat.java
@@ -32,7 +32,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -54,7 +54,7 @@ public final class BlackCat extends CardImpl {
this.toughness = new MageInt(1);
// When Black Cat dies, target opponent discards a card at random.
- Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(1, true),false);
+ Ability ability = new DiesSourceTriggeredAbility(new DiscardTargetEffect(1, true),false);
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/b/BlastZone.java b/Mage.Sets/src/mage/cards/b/BlastZone.java
index 982b139f1c3..5f33f3a11d8 100644
--- a/Mage.Sets/src/mage/cards/b/BlastZone.java
+++ b/Mage.Sets/src/mage/cards/b/BlastZone.java
@@ -38,7 +38,8 @@ public final class BlastZone extends CardImpl {
// Blast Zone enters the battlefield with a charge counter on it.
this.addAbility(new EntersBattlefieldAbility(
new AddCountersSourceEffect(CounterType.CHARGE.createInstance(1))
- ));
+ ,"with a charge counter")
+ );
// {T}: Add {C}.
this.addAbility(new ColorlessManaAbility());
diff --git a/Mage.Sets/src/mage/cards/b/BlazingEffigy.java b/Mage.Sets/src/mage/cards/b/BlazingEffigy.java
index ddf098cd72d..d429166ebe4 100644
--- a/Mage.Sets/src/mage/cards/b/BlazingEffigy.java
+++ b/Mage.Sets/src/mage/cards/b/BlazingEffigy.java
@@ -7,7 +7,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -35,7 +35,7 @@ public final class BlazingEffigy extends CardImpl {
this.toughness = new MageInt(3);
// When Blazing Effigy dies, it deals X damage to target creature, where X is 3 plus the amount of damage dealt to Blazing Effigy this turn by other sources named Blazing Effigy.
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(BlazingEffigyCount.instance), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(BlazingEffigyCount.instance), false);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability, new BlazingEffigyWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/b/BlazingHellhound.java b/Mage.Sets/src/mage/cards/b/BlazingHellhound.java
index 65ed6aee7c0..61d0e0f67e6 100644
--- a/Mage.Sets/src/mage/cards/b/BlazingHellhound.java
+++ b/Mage.Sets/src/mage/cards/b/BlazingHellhound.java
@@ -25,7 +25,7 @@ public final class BlazingHellhound extends CardImpl {
public BlazingHellhound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{R}");
- this.subtype.add(SubType.ELEMENTAL, SubType.HOUND);
+ this.subtype.add(SubType.ELEMENTAL, SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/b/BlessedReincarnation.java b/Mage.Sets/src/mage/cards/b/BlessedReincarnation.java
index ac0276b9c5d..5f4770a1043 100644
--- a/Mage.Sets/src/mage/cards/b/BlessedReincarnation.java
+++ b/Mage.Sets/src/mage/cards/b/BlessedReincarnation.java
@@ -74,7 +74,7 @@ class BlessedReincarnationEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null && controller != null) {
controller.moveCards(permanent, Zone.EXILED, source, game);
- game.applyEffects();
+ game.getState().processAction(game);
Player permanentController = game.getPlayer(permanent.getControllerId());
if (permanentController != null) {
diff --git a/Mage.Sets/src/mage/cards/b/BlessedSanctuary.java b/Mage.Sets/src/mage/cards/b/BlessedSanctuary.java
new file mode 100644
index 00000000000..4cf9a6409d5
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BlessedSanctuary.java
@@ -0,0 +1,49 @@
+package mage.cards.b;
+
+import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.PreventAllNonCombatDamageToAllEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Zone;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.permanent.TokenPredicate;
+import mage.game.permanent.token.UnicornToken;
+
+import java.util.UUID;
+
+public class BlessedSanctuary extends CardImpl {
+
+ private static final FilterPermanent filterYourCreatures = new FilterControlledCreaturePermanent("creatures you control");
+ private static final FilterControlledCreaturePermanent filterNontoken = new FilterControlledCreaturePermanent("a nontoken creature");
+
+ static {
+ filterNontoken.add(Predicates.not(TokenPredicate.instance));
+ }
+
+ public BlessedSanctuary(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}");
+
+ //Prevent all noncombat damage that would be dealt to you and creatures you control.
+ this.addAbility(new SimpleStaticAbility(new PreventAllNonCombatDamageToAllEffect(
+ Duration.WhileOnBattlefield, filterYourCreatures, true)));
+
+ //Whenever a nontoken creature enters the battlefield under your control, create a 2/2 white Unicorn creature token.
+ this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD,
+ new CreateTokenEffect(new UnicornToken()), filterNontoken, false));
+ }
+
+ public BlessedSanctuary(final BlessedSanctuary card) {
+ super(card);
+ }
+
+ @Override
+ public BlessedSanctuary copy() {
+ return new BlessedSanctuary(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BlightKeeper.java b/Mage.Sets/src/mage/cards/b/BlightKeeper.java
index 985e69d9ec2..e72e5b1a9d4 100644
--- a/Mage.Sets/src/mage/cards/b/BlightKeeper.java
+++ b/Mage.Sets/src/mage/cards/b/BlightKeeper.java
@@ -1,7 +1,5 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -18,8 +16,9 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class BlightKeeper extends CardImpl {
@@ -37,7 +36,7 @@ public final class BlightKeeper extends CardImpl {
// {7}{B}, {T}, Sacrifice Blight Keeper: Target opponent loses 4 life and you gain 4 life.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseLifeTargetEffect(4), new ManaCostsImpl("{7}{B}"));
- ability.addEffect(new GainLifeEffect(4).setText("and you gain 4 life"));
+ ability.addEffect(new GainLifeEffect(4).concatBy("and"));
ability.addTarget(new TargetOpponent());
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost());
diff --git a/Mage.Sets/src/mage/cards/b/Blistergrub.java b/Mage.Sets/src/mage/cards/b/Blistergrub.java
index 7519cb0dd58..198b9e0537a 100644
--- a/Mage.Sets/src/mage/cards/b/Blistergrub.java
+++ b/Mage.Sets/src/mage/cards/b/Blistergrub.java
@@ -4,7 +4,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
import mage.abilities.keyword.SwampwalkAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class Blistergrub extends CardImpl {
// Swampwalk (This creature can't be blocked as long as defending player controls a Swamp.)
this.addAbility(new SwampwalkAbility());
// When Blistergrub dies, each opponent loses 2 life.
- this.addAbility(new DiesTriggeredAbility(new LoseLifeOpponentsEffect(2), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new LoseLifeOpponentsEffect(2), false));
}
public Blistergrub (final Blistergrub card) {
diff --git a/Mage.Sets/src/mage/cards/b/Blisterpod.java b/Mage.Sets/src/mage/cards/b/Blisterpod.java
index b3644a8392b..217161f196e 100644
--- a/Mage.Sets/src/mage/cards/b/Blisterpod.java
+++ b/Mage.Sets/src/mage/cards/b/Blisterpod.java
@@ -3,7 +3,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.DevoidAbility;
@@ -30,7 +30,7 @@ public final class Blisterpod extends CardImpl {
// When Blisterpod dies, create a 1/1 colorless Eldrazi Scion creature token. It has "Sacrifice this creature: Add {C}."
Effect effect = new CreateTokenEffect(new EldraziScionToken());
effect.setText("Create a 1/1 colorless Eldrazi Scion creature token. It has \"Sacrifice this creature: Add {C}.\"");
- this.addAbility(new DiesTriggeredAbility(effect, false));
+ this.addAbility(new DiesSourceTriggeredAbility(effect, false));
}
public Blisterpod(final Blisterpod card) {
diff --git a/Mage.Sets/src/mage/cards/b/BloodGlutton.java b/Mage.Sets/src/mage/cards/b/BloodGlutton.java
new file mode 100644
index 00000000000..0936f5a04e4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BloodGlutton.java
@@ -0,0 +1,36 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BloodGlutton extends CardImpl {
+
+ public BloodGlutton(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
+
+ this.subtype.add(SubType.VAMPIRE);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(3);
+
+ // Lifelink
+ this.addAbility(LifelinkAbility.getInstance());
+ }
+
+ private BloodGlutton(final BloodGlutton card) {
+ super(card);
+ }
+
+ @Override
+ public BloodGlutton copy() {
+ return new BloodGlutton(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BloodHound.java b/Mage.Sets/src/mage/cards/b/BloodHound.java
index f182a4b5e3a..98e7ef6b120 100644
--- a/Mage.Sets/src/mage/cards/b/BloodHound.java
+++ b/Mage.Sets/src/mage/cards/b/BloodHound.java
@@ -26,7 +26,7 @@ public final class BloodHound extends CardImpl {
public BloodHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/b/BloodSun.java b/Mage.Sets/src/mage/cards/b/BloodSun.java
index 227b656eaf9..0a9e2dd853a 100644
--- a/Mage.Sets/src/mage/cards/b/BloodSun.java
+++ b/Mage.Sets/src/mage/cards/b/BloodSun.java
@@ -1,6 +1,8 @@
package mage.cards.b;
+import java.util.ArrayList;
+import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -70,7 +72,13 @@ class BloodSunEffect extends ContinuousEffectImpl {
for (Permanent permanent : game.getState().getBattlefield().getActivePermanents(StaticFilters.FILTER_LANDS, player.getId(), source.getSourceId(), game)) {
switch (layer) {
case AbilityAddingRemovingEffects_6:
- permanent.getAbilities().removeIf(ability -> ability.getAbilityType() != AbilityType.MANA);
+ List toRemove = new ArrayList<>();
+ permanent.getAbilities().forEach(a -> {
+ if (a.getAbilityType() != AbilityType.MANA) {
+ toRemove.add(a);
+ }
+ });
+ permanent.removeAbilities(toRemove, source.getSourceId(), game);
break;
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BloodTribute.java b/Mage.Sets/src/mage/cards/b/BloodTribute.java
index 694c16ac064..5bc65b7e7ec 100644
--- a/Mage.Sets/src/mage/cards/b/BloodTribute.java
+++ b/Mage.Sets/src/mage/cards/b/BloodTribute.java
@@ -1,7 +1,5 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.common.KickedCondition;
import mage.abilities.costs.common.TapTargetCost;
@@ -24,8 +22,9 @@ import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class BloodTribute extends CardImpl {
@@ -41,8 +40,8 @@ public final class BloodTribute extends CardImpl {
this.addAbility(new KickerAbility(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))));
// Target opponent loses half their life, rounded up.
- this.getSpellAbility().addTarget(new TargetOpponent());
this.getSpellAbility().addEffect(new BloodTributeLoseLifeEffect());
+ this.getSpellAbility().addTarget(new TargetOpponent());
// If Blood Tribute was kicked, you gain life equal to the life lost this way.
Effect effect = new ConditionalOneShotEffect(
diff --git a/Mage.Sets/src/mage/cards/b/BloodbornScoundrels.java b/Mage.Sets/src/mage/cards/b/BloodbornScoundrels.java
index 87837760ce4..b55b53e9ba6 100644
--- a/Mage.Sets/src/mage/cards/b/BloodbornScoundrels.java
+++ b/Mage.Sets/src/mage/cards/b/BloodbornScoundrels.java
@@ -1,21 +1,20 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
-import mage.constants.SubType;
import mage.abilities.keyword.AssistAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.SubType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class BloodbornScoundrels extends CardImpl {
@@ -33,7 +32,7 @@ public final class BloodbornScoundrels extends CardImpl {
// When Bloodborn Scoundrels enters the battlefield, target opponent loses 2 life and you gain 2 life.
Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(2));
- ability.addEffect(new GainLifeEffect(2).setText("and you gain 2 life"));
+ ability.addEffect(new GainLifeEffect(2).concatBy("and"));
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java b/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java
index 5979a3dca01..71166b33c88 100644
--- a/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java
+++ b/Mage.Sets/src/mage/cards/b/BludgeonBrawl.java
@@ -122,8 +122,8 @@ class BludgeonBrawlGainAbilityEffect extends ContinuousEffectImpl {
Permanent permanent = game.getPermanent(permanentId);
if (permanent != null) {
int convertedManaCost = permanent.getConvertedManaCost();
- permanent.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(convertedManaCost)), game);
- permanent.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(convertedManaCost, 0)), game);
+ permanent.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(convertedManaCost)), source.getSourceId(), game);
+ permanent.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(convertedManaCost, 0)), source.getSourceId(), game);
}
}
return true;
diff --git a/Mage.Sets/src/mage/cards/b/BlurredMongoose.java b/Mage.Sets/src/mage/cards/b/BlurredMongoose.java
index 2ea3ba023c6..675a16d753d 100644
--- a/Mage.Sets/src/mage/cards/b/BlurredMongoose.java
+++ b/Mage.Sets/src/mage/cards/b/BlurredMongoose.java
@@ -3,7 +3,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.keyword.ShroudAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class BlurredMongoose extends CardImpl {
this.toughness = new MageInt(1);
// Blurred Mongoose can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
this.addAbility(ShroudAbility.getInstance());
}
diff --git a/Mage.Sets/src/mage/cards/b/BodySnatcher.java b/Mage.Sets/src/mage/cards/b/BodySnatcher.java
index 2f6e6aeb261..0bdc8fa8556 100644
--- a/Mage.Sets/src/mage/cards/b/BodySnatcher.java
+++ b/Mage.Sets/src/mage/cards/b/BodySnatcher.java
@@ -4,7 +4,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.effects.Effect;
@@ -38,7 +38,7 @@ public final class BodySnatcher extends CardImpl {
// When Body Snatcher dies, exile Body Snatcher and return target creature card from your graveyard to the battlefield.
Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect();
effect.setText("and return target creature card from your graveyard to the battlefield");
- Ability ability = new DiesTriggeredAbility(new ExileSourceEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new ExileSourceEffect(), false);
ability.addEffect(effect);
ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/b/BogDown.java b/Mage.Sets/src/mage/cards/b/BogDown.java
index b136f2e6062..64fa2d79135 100644
--- a/Mage.Sets/src/mage/cards/b/BogDown.java
+++ b/Mage.Sets/src/mage/cards/b/BogDown.java
@@ -8,7 +8,7 @@ import mage.abilities.keyword.KickerAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.filter.common.FilterControlledLandPermanent;
+import mage.filter.StaticFilters;
import mage.target.TargetPlayer;
import mage.target.common.TargetControlledPermanent;
@@ -24,12 +24,12 @@ public final class BogDown extends CardImpl {
// Kicker-Sacrifice two lands.
this.addAbility(new KickerAbility(new SacrificeTargetCost(new TargetControlledPermanent(2, 2,
- new FilterControlledLandPermanent("two lands"), true))));
+ StaticFilters.FILTER_CONTROLLED_LAND_SHORT_TEXT, true))));
// Target player discards two cards. If Bog Down was kicked, that player discards three cards instead.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new DiscardTargetEffect(3),
new DiscardTargetEffect(2), KickedCondition.instance,
- "Target player discards two cards. if this spell was kicked, that player discards three cards instead."));
+ "Target player discards two cards. If this spell was kicked, that player discards three cards instead."));
this.getSpellAbility().addTarget(new TargetPlayer());
}
diff --git a/Mage.Sets/src/mage/cards/b/BogardanFirefiend.java b/Mage.Sets/src/mage/cards/b/BogardanFirefiend.java
index dce2d9e9159..9bcf88f9a71 100644
--- a/Mage.Sets/src/mage/cards/b/BogardanFirefiend.java
+++ b/Mage.Sets/src/mage/cards/b/BogardanFirefiend.java
@@ -4,7 +4,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class BogardanFirefiend extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(1);
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(2), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(2), false);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/b/BogardanPhoenix.java b/Mage.Sets/src/mage/cards/b/BogardanPhoenix.java
index e56829c19b6..b724e003723 100644
--- a/Mage.Sets/src/mage/cards/b/BogardanPhoenix.java
+++ b/Mage.Sets/src/mage/cards/b/BogardanPhoenix.java
@@ -3,7 +3,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.constants.SubType;
import mage.abilities.keyword.FlyingAbility;
@@ -36,7 +36,7 @@ public final class BogardanPhoenix extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Bogardan Phoenix dies, exile it if it had a death counter on it. Otherwise, return it to the battlefield under your control and put a death counter on it.
- this.addAbility(new DiesTriggeredAbility(new BogardanPhoenixEffect(), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new BogardanPhoenixEffect(), false));
}
public BogardanPhoenix(final BogardanPhoenix card) {
diff --git a/Mage.Sets/src/mage/cards/b/BolassCitadel.java b/Mage.Sets/src/mage/cards/b/BolassCitadel.java
index 2827e6a9358..00c6d096532 100644
--- a/Mage.Sets/src/mage/cards/b/BolassCitadel.java
+++ b/Mage.Sets/src/mage/cards/b/BolassCitadel.java
@@ -20,9 +20,12 @@ import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
-import mage.util.CardUtil;
import java.util.UUID;
+import mage.cards.SplitCard;
+import mage.cards.SplitCardHalf;
+import mage.util.CardUtil;
+
/**
* @author jeffwadsworth
@@ -94,23 +97,43 @@ class BolassCitadelPlayTheTopCardEffect extends AsThoughEffectImpl {
@Override
public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
- Card cardToCheck = game.getCard(objectId);
- objectId = CardUtil.getMainCardId(game, objectId); // for split cards
+ Player player = game.getPlayer(playerId);
+ if (player != null) {
+ Card topCard = player.getLibrary().getFromTop(game);
+ UUID objectIdToCast = CardUtil.getMainCardId(game, objectId); // for adventure cards
+ if (topCard == null || !topCard.getId().equals(objectIdToCast)) {
+ return false;
+ }
+ if (!topCard.isLand()) {
+ if (topCard instanceof SplitCard) {
+ SplitCardHalf leftCard = ((SplitCard) topCard).getLeftHalfCard();
+ PayLifeCost lifeCost = new PayLifeCost(leftCard.getSpellAbility().getManaCosts().convertedManaCost());
+ Costs leftCosts = new CostsImpl();
+ leftCosts.add(lifeCost);
+ leftCosts.addAll(leftCard.getSpellAbility().getCosts());
+ player.setCastSourceIdWithAlternateMana(leftCard.getId(), null, leftCosts);
- if (!isAbilityAppliedForAlternateCast(cardToCheck, affectedAbility, playerId, source)) {
- return false;
- }
-
- Player controller = game.getPlayer(cardToCheck.getOwnerId());
- Card topCard = controller == null ? null : controller.getLibrary().getFromTop(game);
- if (topCard != null && objectId.equals(topCard.getId())) {
- // add the life cost first
- PayLifeCost cost = new PayLifeCost(affectedAbility.getManaCosts().convertedManaCost());
- Costs costs = new CostsImpl();
- costs.add(cost);
- costs.addAll(affectedAbility.getCosts());
- controller.setCastSourceIdWithAlternateMana(affectedAbility.getSourceId(), null, costs);
+ SplitCardHalf rightCard = ((SplitCard) topCard).getRightHalfCard();
+ lifeCost = new PayLifeCost(rightCard.getSpellAbility().getManaCosts().convertedManaCost());
+ Costs rightCosts = new CostsImpl();
+ rightCosts.add(lifeCost);
+ rightCosts.addAll(rightCard.getSpellAbility().getCosts());
+ player.setCastSourceIdWithAlternateMana(rightCard.getId(), null, rightCosts);
+ } else {
+ if (affectedAbility == null) {
+ affectedAbility = topCard.getSpellAbility();
+ } else {
+ objectIdToCast = affectedAbility.getSourceId();
+ }
+ PayLifeCost cost = new PayLifeCost(affectedAbility.getManaCosts().convertedManaCost());
+ Costs costs = new CostsImpl();
+ costs.add(cost);
+ costs.addAll(affectedAbility.getCosts());
+ player.setCastSourceIdWithAlternateMana(objectIdToCast, null, costs);
+ }
+ }
return true;
+
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/b/BoltBend.java b/Mage.Sets/src/mage/cards/b/BoltBend.java
index c48d40bee9d..1f27c67d0a0 100644
--- a/Mage.Sets/src/mage/cards/b/BoltBend.java
+++ b/Mage.Sets/src/mage/cards/b/BoltBend.java
@@ -1,5 +1,6 @@
package mage.cards.b;
+import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.FerociousCondition;
import mage.abilities.effects.common.ChooseNewTargetsTargetEffect;
@@ -13,8 +14,6 @@ import mage.filter.FilterStackObject;
import mage.filter.predicate.mageobject.NumberOfTargetsPredicate;
import mage.target.TargetStackObject;
-import java.util.UUID;
-
/**
* @author TheElk801
*/
@@ -31,7 +30,7 @@ public final class BoltBend extends CardImpl {
// This spell costs {3} less to cast if you control a creature with power 4 or greater.
this.addAbility(new SimpleStaticAbility(
- Zone.STACK, new SpellCostReductionSourceEffect(3, FerociousCondition.instance)
+ Zone.ALL, new SpellCostReductionSourceEffect(3, FerociousCondition.instance)
).setRuleAtTheTop(true).addHint(FerociousHint.instance));
// Change the target of target spell or ability with a single target.
diff --git a/Mage.Sets/src/mage/cards/b/BoltHound.java b/Mage.Sets/src/mage/cards/b/BoltHound.java
new file mode 100644
index 00000000000..abda3056990
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BoltHound.java
@@ -0,0 +1,45 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.abilities.keyword.HasteAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BoltHound extends CardImpl {
+
+ public BoltHound(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
+
+ this.subtype.add(SubType.ELEMENTAL);
+ this.subtype.add(SubType.DOG);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Haste
+ this.addAbility(HasteAbility.getInstance());
+
+ // Whenever Bolt Hound attacks, other creatures you control get +1/+0 until end of turn.
+ this.addAbility(new AttacksTriggeredAbility(new BoostControlledEffect(
+ 1, 0, Duration.EndOfTurn, true
+ ), false));
+ }
+
+ private BoltHound(final BoltHound card) {
+ super(card);
+ }
+
+ @Override
+ public BoltHound copy() {
+ return new BoltHound(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BondOfInsight.java b/Mage.Sets/src/mage/cards/b/BondOfInsight.java
index b6545b6f2f8..9580a0a5368 100644
--- a/Mage.Sets/src/mage/cards/b/BondOfInsight.java
+++ b/Mage.Sets/src/mage/cards/b/BondOfInsight.java
@@ -45,8 +45,8 @@ class BondOfInsightEffect extends OneShotEffect {
BondOfInsightEffect() {
super(Outcome.Benefit);
- staticText = "Each player puts the top four cards of their library into their graveyard. " +
- "Return up to two instant and/or sorcery cards from your graveyard to your hand";
+ staticText = "Each player mills four cards. " +
+ "Return up to two instant and/or sorcery cards from your graveyard to your hand.";
}
private BondOfInsightEffect(final BondOfInsightEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/b/BonePitBrute.java b/Mage.Sets/src/mage/cards/b/BonePitBrute.java
new file mode 100644
index 00000000000..33c81ee740e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BonePitBrute.java
@@ -0,0 +1,48 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.abilities.keyword.MenaceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BonePitBrute extends CardImpl {
+
+ public BonePitBrute(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}");
+
+ this.subtype.add(SubType.CYCLOPS);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(5);
+
+ // Menace
+ this.addAbility(new MenaceAbility());
+
+ // When Bone Pit Brute enters the battlefield, target creature gets +4/+0 until end of turn.
+ Ability ability = new EntersBattlefieldTriggeredAbility(
+ new BoostTargetEffect(4, 0, Duration.EndOfTurn)
+ );
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ }
+
+ private BonePitBrute(final BonePitBrute card) {
+ super(card);
+ }
+
+ @Override
+ public BonePitBrute copy() {
+ return new BonePitBrute(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BontuTheGlorified.java b/Mage.Sets/src/mage/cards/b/BontuTheGlorified.java
index 79e561b86e0..eac46899b4e 100644
--- a/Mage.Sets/src/mage/cards/b/BontuTheGlorified.java
+++ b/Mage.Sets/src/mage/cards/b/BontuTheGlorified.java
@@ -37,16 +37,16 @@ public final class BontuTheGlorified extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(6);
- //Menace
- this.addAbility(new MenaceAbility());
+ // Menace
+ this.addAbility(new MenaceAbility(false));
- //Indestructible
+ // Indestructible
this.addAbility(IndestructibleAbility.getInstance());
- //Bontu the Glorified can't attack or block unless a creature died under your control this turn.
+ // Bontu the Glorified can't attack or block unless a creature died under your control this turn.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BontuTheGlorifiedRestrictionEffect()), new CreaturesDiedWatcher());
- //{1}{B}, Sacrifice another creature: Scry 1. Each opponent loses 1 life and you gain 1 life.
+ // {1}{B}, Sacrifice another creature: Scry 1. Each opponent loses 1 life and you gain 1 life.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScryEffect(1), new ManaCostsImpl("{1}{B}"));
ability.addEffect(new LoseLifeOpponentsEffect(1));
Effect effect = new GainLifeEffect(1);
diff --git a/Mage.Sets/src/mage/cards/b/BookBurning.java b/Mage.Sets/src/mage/cards/b/BookBurning.java
index 6778bc4ee6e..6678b6520f0 100644
--- a/Mage.Sets/src/mage/cards/b/BookBurning.java
+++ b/Mage.Sets/src/mage/cards/b/BookBurning.java
@@ -41,7 +41,7 @@ class BookBurningMillEffect extends OneShotEffect {
public BookBurningMillEffect() {
super(Outcome.Detriment);
- staticText = "Any player may have {source} deal 6 damage to them. If no one does, target player puts the top six cards of their library into their graveyard";
+ staticText = "Any player may have {source} deal 6 damage to them. If no one does, target player mills six cards";
}
public BookBurningMillEffect(final BookBurningMillEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/b/BorealElemental.java b/Mage.Sets/src/mage/cards/b/BorealElemental.java
index bd0f8fcadaf..df54bda0db4 100644
--- a/Mage.Sets/src/mage/cards/b/BorealElemental.java
+++ b/Mage.Sets/src/mage/cards/b/BorealElemental.java
@@ -1,20 +1,17 @@
package mage.cards.b;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.target.Target;
-import mage.util.CardUtil;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
-import java.util.Collection;
import java.util.UUID;
/**
@@ -33,7 +30,9 @@ public final class BorealElemental extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Spells your opponents cast that target Boreal Elemental cost {2} more to cast.
- this.addAbility(new SimpleStaticAbility(new BorealElementalCostIncreaseEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(2, new FilterCard("Spells"), TargetController.OPPONENT))
+ );
}
private BorealElemental(final BorealElemental card) {
@@ -45,46 +44,3 @@ public final class BorealElemental extends CardImpl {
return new BorealElemental(this);
}
}
-
-class BorealElementalCostIncreaseEffect extends CostModificationEffectImpl {
-
- BorealElementalCostIncreaseEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Spells your opponents cast that target {this} cost {2} more to cast";
- }
-
- private BorealElementalCostIncreaseEffect(BorealElementalCostIncreaseEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (!(abilityToModify instanceof SpellAbility)
- || !game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- return false;
- }
- return abilityToModify
- .getModes()
- .getSelectedModes()
- .stream()
- .map(uuid -> abilityToModify.getModes().get(uuid))
- .map(Mode::getTargets)
- .flatMap(Collection::stream)
- .map(Target::getTargets)
- .flatMap(Collection::stream)
- .anyMatch(uuid -> uuid.equals(source.getSourceId()));
- }
-
- @Override
- public BorealElementalCostIncreaseEffect copy() {
- return new BorealElementalCostIncreaseEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/b/BorosMastiff.java b/Mage.Sets/src/mage/cards/b/BorosMastiff.java
index 9d2e118ed86..35811ff7790 100644
--- a/Mage.Sets/src/mage/cards/b/BorosMastiff.java
+++ b/Mage.Sets/src/mage/cards/b/BorosMastiff.java
@@ -23,7 +23,7 @@ public final class BorosMastiff extends CardImpl {
public BorosMastiff (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java b/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java
index 86f68cfe0b8..95e22f74883 100644
--- a/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java
+++ b/Mage.Sets/src/mage/cards/b/BoseijuWhoSheltersAll.java
@@ -1,10 +1,10 @@
package mage.cards.b;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
+import java.util.*;
+
import mage.MageObject;
+import mage.MageObjectReference;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTappedAbility;
@@ -58,7 +58,7 @@ public final class BoseijuWhoSheltersAll extends CardImpl {
class BoseijuWhoSheltersAllWatcher extends Watcher {
- private List spells = new ArrayList<>();
+ private final Set spells = new HashSet<>();
private final UUID originalId;
public BoseijuWhoSheltersAllWatcher(UUID originalId) {
@@ -69,17 +69,17 @@ class BoseijuWhoSheltersAllWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.MANA_PAID) {
- if (event.getData() != null && event.getData().equals(originalId.toString())) {
+ if (event.getData() != null && event.getData().equals(originalId.toString()) && event.getTargetId() != null) {
Card spell = game.getSpell(event.getTargetId());
if (spell != null && (spell.isInstant() || spell.isSorcery())) {
- spells.add(event.getTargetId());
+ spells.add(new MageObjectReference(game.getObject(event.getTargetId()), game));
}
}
}
}
- public boolean spellCantBeCountered(UUID spellId) {
- return spells.contains(spellId);
+ public boolean spellCantBeCountered(MageObjectReference mor) {
+ return spells.contains(mor);
}
@Override
@@ -128,6 +128,6 @@ class BoseijuWhoSheltersAllCantCounterEffect extends ContinuousRuleModifyingEffe
public boolean applies(GameEvent event, Ability source, Game game) {
BoseijuWhoSheltersAllWatcher watcher = game.getState().getWatcher(BoseijuWhoSheltersAllWatcher.class, source.getSourceId());
Spell spell = game.getStack().getSpell(event.getTargetId());
- return spell != null && watcher != null && watcher.spellCantBeCountered(spell.getId());
+ return spell != null && watcher != null && watcher.spellCantBeCountered(new MageObjectReference(spell, game));
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/b/BoundDetermined.java b/Mage.Sets/src/mage/cards/b/BoundDetermined.java
index cfb16ba5176..86d2018d827 100644
--- a/Mage.Sets/src/mage/cards/b/BoundDetermined.java
+++ b/Mage.Sets/src/mage/cards/b/BoundDetermined.java
@@ -86,7 +86,7 @@ class BoundEffect extends OneShotEffect {
Permanent toSacrifice = game.getPermanent(target.getFirstTarget());
if (toSacrifice != null) {
toSacrifice.sacrifice(source.getSourceId(), game);
- game.applyEffects();
+ game.getState().processAction(game);
int colors = toSacrifice.getColor(game).getColorCount();
if (colors > 0) {
TargetCardInYourGraveyard targetCard = new TargetCardInYourGraveyard(0, colors,
diff --git a/Mage.Sets/src/mage/cards/b/BrainPry.java b/Mage.Sets/src/mage/cards/b/BrainPry.java
index 555d1368c16..8704271ed89 100644
--- a/Mage.Sets/src/mage/cards/b/BrainPry.java
+++ b/Mage.Sets/src/mage/cards/b/BrainPry.java
@@ -60,7 +60,7 @@ class BrainPryEffect extends OneShotEffect {
if (targetPlayer != null && controller != null && sourceObject != null && cardName != null) {
boolean hasDiscarded = false;
for (Card card : targetPlayer.getHand().getCards(game)) {
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
targetPlayer.discard(card, source, game);
hasDiscarded = true;
break;
diff --git a/Mage.Sets/src/mage/cards/b/BranchingEvolution.java b/Mage.Sets/src/mage/cards/b/BranchingEvolution.java
new file mode 100644
index 00000000000..0e67487032f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BranchingEvolution.java
@@ -0,0 +1,86 @@
+package mage.cards.b;
+
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.counters.CounterType;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.util.CardUtil;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BranchingEvolution extends CardImpl {
+
+ public BranchingEvolution(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
+
+ // If one or more +1/+1 counters would be put a on a creature you control, twice that many +1/+1 counters are put on that creature instead.
+ this.addAbility(new SimpleStaticAbility(new BranchingEvolutionEffect()));
+ }
+
+ private BranchingEvolution(final BranchingEvolution card) {
+ super(card);
+ }
+
+ @Override
+ public BranchingEvolution copy() {
+ return new BranchingEvolution(this);
+ }
+}
+
+class BranchingEvolutionEffect extends ReplacementEffectImpl {
+
+ BranchingEvolutionEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.BoostCreature, false);
+ staticText = "If one or more +1/+1 counters would be put on a creature you control, " +
+ "twice that many +1/+1 counters are put on it instead";
+ }
+
+ private BranchingEvolutionEffect(final BranchingEvolutionEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ event.setAmountForCounters(CardUtil.addWithOverflowCheck(event.getAmount(), event.getAmount()), true);
+ return false;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ADD_COUNTERS;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (event.getData().equals(CounterType.P1P1.getName()) && event.getAmount() > 0) {
+ Permanent permanent = game.getPermanent(event.getTargetId());
+ if (permanent == null) {
+ permanent = game.getPermanentEntering(event.getTargetId());
+ }
+ return permanent != null && permanent.isControlledBy(source.getControllerId())
+ && permanent.isCreature();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public BranchingEvolutionEffect copy() {
+ return new BranchingEvolutionEffect(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BrashTaunter.java b/Mage.Sets/src/mage/cards/b/BrashTaunter.java
new file mode 100644
index 00000000000..d3c35dfb428
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BrashTaunter.java
@@ -0,0 +1,100 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DealtDamageToSourceTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.FightTargetSourceEffect;
+import mage.abilities.keyword.IndestructibleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.permanent.AnotherPredicate;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetOpponent;
+
+import java.util.UUID;
+
+/**
+ * @author jmharmon
+ */
+
+public final class BrashTaunter extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterCreaturePermanent();
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ }
+
+ public BrashTaunter(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}");
+
+ this.subtype.add(SubType.GOBLIN);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ // Indestructible
+ this.addAbility(IndestructibleAbility.getInstance());
+
+ // Whenever Brash Taunter is dealt damage, it deals that much damage to target opponent.
+ Ability ability = new DealtDamageToSourceTriggeredAbility(new BrashTaunterEffect(), false, false, true);
+ ability.addTarget(new TargetOpponent());
+ this.addAbility(ability);
+
+ // {2}{R}, {T}: Brash Taunter fights another target creature.
+ Ability ability1 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new FightTargetSourceEffect(), new ManaCostsImpl("{2}{R}"));
+ ability1.addCost(new TapSourceCost());
+ ability1.addTarget(new TargetPermanent(filter));
+ this.addAbility(ability1);
+ }
+
+ private BrashTaunter(final BrashTaunter card) {
+ super(card);
+ }
+
+ @Override
+ public BrashTaunter copy() {
+ return new BrashTaunter(this);
+ }
+}
+
+class BrashTaunterEffect extends OneShotEffect {
+
+ public BrashTaunterEffect() {
+ super(Outcome.Damage);
+ this.staticText = "it deals that much damage to target opponent";
+ }
+
+ public BrashTaunterEffect(final BrashTaunterEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public BrashTaunterEffect copy() {
+ return new BrashTaunterEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ int amount = (Integer) getValue("damage");
+ if (amount > 0) {
+ Player player = game.getPlayer(targetPointer.getFirst(game, source));
+ if (player != null) {
+ player.damage(amount, source.getSourceId(), game);
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BreachingLeviathan.java b/Mage.Sets/src/mage/cards/b/BreachingLeviathan.java
index 3171564a794..2c5230f3971 100644
--- a/Mage.Sets/src/mage/cards/b/BreachingLeviathan.java
+++ b/Mage.Sets/src/mage/cards/b/BreachingLeviathan.java
@@ -8,7 +8,7 @@ import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
@@ -42,7 +42,7 @@ public final class BreachingLeviathan extends CardImpl {
// When Breaching Leviathan enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new BreachingLeviathanEffect(), false),
- CastFromHandSourceCondition.instance,
+ CastFromHandSourcePermanentCondition.instance,
"When {this} enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps."),
new CastFromHandWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/b/BreakOpen.java b/Mage.Sets/src/mage/cards/b/BreakOpen.java
index 60df5e30ab4..5a5209b3304 100644
--- a/Mage.Sets/src/mage/cards/b/BreakOpen.java
+++ b/Mage.Sets/src/mage/cards/b/BreakOpen.java
@@ -17,7 +17,7 @@ import mage.target.common.TargetCreaturePermanent;
*/
public final class BreakOpen extends CardImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Face-down creature an opponent controls");
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face-down creature an opponent controls");
static {
filter.add(FaceDownPredicate.instance);
diff --git a/Mage.Sets/src/mage/cards/b/Breakthrough.java b/Mage.Sets/src/mage/cards/b/Breakthrough.java
index 15f6a890e9d..b2392375b4c 100644
--- a/Mage.Sets/src/mage/cards/b/Breakthrough.java
+++ b/Mage.Sets/src/mage/cards/b/Breakthrough.java
@@ -1,13 +1,11 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
@@ -15,25 +13,24 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class Breakthrough extends CardImpl {
public Breakthrough(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{U}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{U}");
// Draw four cards,
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4));
-
+
//then choose X cards in your hand and discard the rest.
this.getSpellAbility().addEffect(new BreakthroughEffect());
-
}
- public Breakthrough(final Breakthrough card) {
+ private Breakthrough(final Breakthrough card) {
super(card);
}
@@ -44,41 +41,38 @@ public final class Breakthrough extends CardImpl {
}
class BreakthroughEffect extends OneShotEffect {
-
+
BreakthroughEffect() {
super(Outcome.Discard);
this.staticText = ", then choose X cards in your hand and discard the rest.";
}
-
- BreakthroughEffect(final BreakthroughEffect effect) {
+
+ private BreakthroughEffect(final BreakthroughEffect effect) {
super(effect);
}
-
+
@Override
public BreakthroughEffect copy() {
return new BreakthroughEffect(this);
}
-
+
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- int amountToKeep = source.getManaCostsToPay().getX();
- if (amountToKeep == 0) {
- player.discard(player.getHand().size(), false, source, game);
- }
- else if (amountToKeep < player.getHand().size()) {
- TargetCardInHand target = new TargetCardInHand(amountToKeep, new FilterCard());
- target.setTargetName("cards to keep");
- target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), game);
- for (Card card : player.getHand().getCards(game)) {
- if (!target.getTargets().contains(card.getId())) {
- player.discard(card, source, game);
- }
- }
- }
- return true;
+ if (player == null) {
+ return false;
}
- return false;
+ int amountToKeep = source.getManaCostsToPay().getX();
+ if (amountToKeep == 0) {
+ player.discard(player.getHand(), source, game);
+ } else if (amountToKeep < player.getHand().size()) {
+ TargetCardInHand target = new TargetCardInHand(amountToKeep, new FilterCard());
+ target.setTargetName("cards to keep");
+ target.choose(Outcome.Benefit, player.getId(), source.getSourceId(), game);
+ Cards cards = player.getHand().copy();
+ cards.removeIf(target.getTargets()::contains);
+ player.discard(cards, source, game);
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/b/BreyaEtheriumShaper.java b/Mage.Sets/src/mage/cards/b/BreyaEtheriumShaper.java
index ba36808b695..b5339588b4e 100644
--- a/Mage.Sets/src/mage/cards/b/BreyaEtheriumShaper.java
+++ b/Mage.Sets/src/mage/cards/b/BreyaEtheriumShaper.java
@@ -1,7 +1,6 @@
package mage.cards.b;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
@@ -22,6 +21,8 @@ import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
+import java.util.UUID;
+
/**
*
* @author fireshoes
@@ -39,12 +40,12 @@ public final class BreyaEtheriumShaper extends CardImpl {
// When Breya, Etherium Shaper enters the battlefield, create two 1/1 blue Thopter artifact creature tokens with flying.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ThopterToken(), 2)));
- // {2}, Sacrifice two artifacts: Choose one — Breya deals 3 damage to target player.
+ // {2}, Sacrifice two artifacts: Choose one — Breya deals 3 damage to target player or planeswalker.
Ability ability = new SimpleActivatedAbility(
Zone.BATTLEFIELD,
new DamageTargetEffect(3),
new GenericManaCost(2));
- ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledArtifactPermanent("two artifacts"), true)));
+ ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledArtifactPermanent("artifacts"), true)));
ability.addTarget(new TargetPlayerOrPlaneswalker());
// Target creature gets -4/-4 until end of turn.
diff --git a/Mage.Sets/src/mage/cards/b/BrighthearthBanneret.java b/Mage.Sets/src/mage/cards/b/BrighthearthBanneret.java
index 1d6c96aa687..24a06469828 100644
--- a/Mage.Sets/src/mage/cards/b/BrighthearthBanneret.java
+++ b/Mage.Sets/src/mage/cards/b/BrighthearthBanneret.java
@@ -1,7 +1,5 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -15,8 +13,9 @@ import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class BrighthearthBanneret extends CardImpl {
@@ -30,7 +29,7 @@ public final class BrighthearthBanneret extends CardImpl {
}
public BrighthearthBanneret(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.ELEMENTAL, SubType.WARRIOR);
this.power = new MageInt(1);
@@ -38,6 +37,7 @@ public final class BrighthearthBanneret extends CardImpl {
// Elemental spells and Warrior spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
+
// Reinforce 1-{1}{R}
this.addAbility(new ReinforceAbility(1, new ManaCostsImpl("{1}{R}")));
}
diff --git a/Mage.Sets/src/mage/cards/b/Brightmare.java b/Mage.Sets/src/mage/cards/b/Brightmare.java
new file mode 100644
index 00000000000..5dfc133b5d1
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/Brightmare.java
@@ -0,0 +1,76 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class Brightmare extends CardImpl {
+
+ public Brightmare(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
+
+ this.subtype.add(SubType.UNICORN);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // When Brightmare enters the battlefield, tap up to one target creature. You gain life equal to that creature's power.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new BrightmareEffect());
+ ability.addTarget(new TargetCreaturePermanent(0, 1));
+ this.addAbility(ability);
+ }
+
+ private Brightmare(final Brightmare card) {
+ super(card);
+ }
+
+ @Override
+ public Brightmare copy() {
+ return new Brightmare(this);
+ }
+}
+
+class BrightmareEffect extends OneShotEffect {
+
+ BrightmareEffect() {
+ super(Outcome.Benefit);
+ staticText = "tap up to one target creature. You gain life equal to that creature's power";
+ }
+
+ private BrightmareEffect(final BrightmareEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public BrightmareEffect copy() {
+ return new BrightmareEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanent(source.getFirstTarget());
+ if (permanent == null) {
+ return false;
+ }
+ permanent.tap(game);
+ Player player = game.getPlayer(source.getControllerId());
+ if (player != null) {
+ player.gainLife(permanent.getPower().getValue(), game, source);
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/b/BrindleShoat.java b/Mage.Sets/src/mage/cards/b/BrindleShoat.java
index 95f1ad2db28..5b98c191d6c 100644
--- a/Mage.Sets/src/mage/cards/b/BrindleShoat.java
+++ b/Mage.Sets/src/mage/cards/b/BrindleShoat.java
@@ -3,7 +3,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class BrindleShoat extends CardImpl {
this.toughness = new MageInt(1);
// When Brindle Shoat dies, create a 3/3 green Boar creature token.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new BoarToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new BoarToken())));
}
public BrindleShoat(final BrindleShoat card) {
diff --git a/Mage.Sets/src/mage/cards/b/BrineGiant.java b/Mage.Sets/src/mage/cards/b/BrineGiant.java
index 09942e2ab33..98d9ca61f46 100644
--- a/Mage.Sets/src/mage/cards/b/BrineGiant.java
+++ b/Mage.Sets/src/mage/cards/b/BrineGiant.java
@@ -1,18 +1,17 @@
package mage.cards.b;
import mage.MageInt;
-import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
-import mage.game.Game;
-import mage.util.CardUtil;
import java.util.UUID;
@@ -21,8 +20,13 @@ import java.util.UUID;
*/
public final class BrineGiant extends CardImpl {
- private static final DynamicValue xValue
- = new PermanentsOnBattlefieldCount(BrineGiantCostReductionEffect.filter);
+ static final FilterControlledPermanent filter = new FilterControlledPermanent("enchantment you control");
+
+ static {
+ filter.add(CardType.ENCHANTMENT.getPredicate());
+ }
+
+ private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
public BrineGiant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{U}");
@@ -33,7 +37,7 @@ public final class BrineGiant extends CardImpl {
// This spell costs {1} less to cast for each enchantment you control.
this.addAbility(new SimpleStaticAbility(
- Zone.ALL, new BrineGiantCostReductionEffect()
+ Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue)
).addHint(new ValueHint("Enchantments you control", xValue)));
}
@@ -45,41 +49,4 @@ public final class BrineGiant extends CardImpl {
public BrineGiant copy() {
return new BrineGiant(this);
}
-}
-
-class BrineGiantCostReductionEffect extends CostModificationEffectImpl {
-
- static final FilterControlledPermanent filter = new FilterControlledPermanent();
-
- static {
- filter.add(CardType.ENCHANTMENT.getPredicate());
- }
-
- BrineGiantCostReductionEffect() {
- super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {1} less to cast for each enchantment you control";
- }
-
- private BrineGiantCostReductionEffect(final BrineGiantCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- int count = game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game).size();
- if (count > 0) {
- CardUtil.reduceCost(abilityToModify, count);
- }
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- return abilityToModify.getSourceId().equals(source.getSourceId());
- }
-
- @Override
- public BrineGiantCostReductionEffect copy() {
- return new BrineGiantCostReductionEffect(this);
- }
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/b/BrineHag.java b/Mage.Sets/src/mage/cards/b/BrineHag.java
index 5050409b69e..608e176fc28 100644
--- a/Mage.Sets/src/mage/cards/b/BrineHag.java
+++ b/Mage.Sets/src/mage/cards/b/BrineHag.java
@@ -7,7 +7,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessAllEffect;
import mage.cards.CardImpl;
@@ -36,7 +36,7 @@ public final class BrineHag extends CardImpl {
this.toughness = new MageInt(2);
// When Brine Hag dies, change the base power and toughness of all creatures that dealt damage to it this turn to 0/2.
- this.addAbility(new DiesTriggeredAbility(new BrineHagEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new BrineHagEffect()));
}
public BrineHag(final BrineHag card) {
diff --git a/Mage.Sets/src/mage/cards/b/BrinkOfMadness.java b/Mage.Sets/src/mage/cards/b/BrinkOfMadness.java
index fe17742f0b6..58a37d6967a 100644
--- a/Mage.Sets/src/mage/cards/b/BrinkOfMadness.java
+++ b/Mage.Sets/src/mage/cards/b/BrinkOfMadness.java
@@ -1,8 +1,5 @@
-
package mage.cards.b;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@@ -10,38 +7,33 @@ import mage.abilities.condition.common.CardsInHandCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeSourceEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.ComparisonType;
-import mage.constants.Outcome;
-import mage.constants.TargetController;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author Plopman
*/
public final class BrinkOfMadness extends CardImpl {
public BrinkOfMadness(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}{B}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}");
// At the beginning of your upkeep, if you have no cards in hand, sacrifice Brink of Madness and target opponent discards their hand.
- TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SacrificeSourceEffect(), TargetController.YOU, false);
+ TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new SacrificeSourceEffect(), TargetController.YOU, false);
ability.addEffect(new BrinkOfMadnessEffect());
ability.addTarget(new TargetOpponent());
CardsInHandCondition contition = new CardsInHandCondition(ComparisonType.EQUAL_TO, 0);
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, contition, "At the beginning of your upkeep, if you have no cards in hand, sacrifice {this} and target opponent discards their hand."));
-
+
}
- public BrinkOfMadness(final BrinkOfMadness card) {
+ private BrinkOfMadness(final BrinkOfMadness card) {
super(card);
}
@@ -49,34 +41,27 @@ public final class BrinkOfMadness extends CardImpl {
public BrinkOfMadness copy() {
return new BrinkOfMadness(this);
}
-
+
static class BrinkOfMadnessEffect extends OneShotEffect {
- public BrinkOfMadnessEffect() {
- super(Outcome.Benefit);
- this.staticText = "Target player discards their hand";
- }
-
- public BrinkOfMadnessEffect(final BrinkOfMadnessEffect effect) {
- super(effect);
- }
-
- @Override
- public BrinkOfMadnessEffect copy() {
- return new BrinkOfMadnessEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getFirstTarget());
- if (player != null) {
- Set cards = player.getHand().getCards(game);
- for (Card card : cards) {
- player.discard(card, source, game);
- }
- return true;
+ private BrinkOfMadnessEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "Target player discards their hand";
+ }
+
+ private BrinkOfMadnessEffect(final BrinkOfMadnessEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public BrinkOfMadnessEffect copy() {
+ return new BrinkOfMadnessEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getFirstTarget());
+ return player != null && !player.discard(player.getHand(), source, game).isEmpty();
}
- return false;
}
}
-}
diff --git a/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java b/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java
index 59228d09e5f..297b9d1c58b 100644
--- a/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java
+++ b/Mage.Sets/src/mage/cards/b/BrokenAmbitions.java
@@ -11,7 +11,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
@@ -45,18 +44,21 @@ public final class BrokenAmbitions extends CardImpl {
class BrokenAmbitionsEffect extends OneShotEffect {
+ private static final String effectText = "Counter target spell unless its controller pays {X}. Clash with an opponent. If you win, that spell's controller mills four cards";
+
protected Cost cost;
protected DynamicValue genericMana;
public BrokenAmbitionsEffect(Cost cost) {
super(Outcome.Benefit);
this.cost = cost;
- this.staticText = "Counter target spell unless its controller pays {X}. Clash with an opponent. If you win, that spell's controller puts the top four cards of their library into their graveyard";
+ this.staticText = effectText;
}
public BrokenAmbitionsEffect(DynamicValue genericMana) {
super(Outcome.Detriment);
this.genericMana = genericMana;
+ this.staticText = effectText;
}
public BrokenAmbitionsEffect(final BrokenAmbitionsEffect effect) {
@@ -67,6 +69,7 @@ class BrokenAmbitionsEffect extends OneShotEffect {
if (effect.genericMana != null) {
this.genericMana = effect.genericMana.copy();
}
+ this.staticText = effectText;
}
@Override
@@ -103,7 +106,7 @@ class BrokenAmbitionsEffect extends OneShotEffect {
game.informPlayers(player.getLogName() + " chooses to pay " + costValueMessage + " to prevent the counter effect");
if (ClashEffect.getInstance().apply(game, source)) {
- player.moveCards(player.getLibrary().getTopCards(game, 4), Zone.GRAVEYARD, source, game);
+ player.millCards(4, source, game);
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/b/BronzehideLion.java b/Mage.Sets/src/mage/cards/b/BronzehideLion.java
index a1f7fa245bd..98dd760b607 100644
--- a/Mage.Sets/src/mage/cards/b/BronzehideLion.java
+++ b/Mage.Sets/src/mage/cards/b/BronzehideLion.java
@@ -4,9 +4,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
-import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffectImpl;
@@ -46,7 +45,7 @@ public final class BronzehideLion extends CardImpl {
// When Bronzehide Lion dies, return it to the battlefield.
// It's an Aura enchantment with enchant creature you control and
// "{G}{W}: Enchanted creature gains indestructible until end of turn," and it loses all other abilities.
- this.addAbility(new DiesTriggeredAbility(new BronzehideLionReturnEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new BronzehideLionReturnEffect()));
}
private BronzehideLion(final BronzehideLion card) {
@@ -109,7 +108,7 @@ class BronzehideLionContinuousEffect extends ContinuousEffectImpl {
private final int zoneChangeCounter;
private final Ability activatedAbility = new SimpleActivatedAbility(new GainAbilityAttachedEffect(
- IndestructibleAbility.getInstance(), AttachmentType.AURA, Duration.WhileOnBattlefield
+ IndestructibleAbility.getInstance(), AttachmentType.AURA, Duration.EndOfTurn
), new ManaCostsImpl("{G}{W}"));
BronzehideLionContinuousEffect(int zoneChangeCounter) {
@@ -133,17 +132,14 @@ class BronzehideLionContinuousEffect extends ContinuousEffectImpl {
if (game.getState().getZoneChangeCounter(source.getSourceId()) > zoneChangeCounter) {
discard();
}
- MageObject sourceObject = game.getPermanent(source.getSourceId());
+ Permanent sourceObject = game.getPermanent(source.getSourceId());
if (sourceObject == null) {
sourceObject = game.getPermanentEntering(source.getSourceId());
}
if (sourceObject == null) {
return false;
}
- if (!(sourceObject instanceof Permanent)) {
- return true;
- }
- Permanent lion = (Permanent) sourceObject;
+ Permanent lion = sourceObject;
switch (layer) {
case TypeChangingEffects_4:
lion.getCardType().clear();
@@ -158,7 +154,7 @@ class BronzehideLionContinuousEffect extends ContinuousEffectImpl {
toRemove.add(ability);
}
}
- lion.getAbilities(game).removeAll(toRemove);
+ lion.removeAbilities(toRemove, source.getSourceId(), game);
lion.getSpellAbility().getTargets().clear();
lion.getSpellAbility().getEffects().clear();
diff --git a/Mage.Sets/src/mage/cards/b/BrushWithDeath.java b/Mage.Sets/src/mage/cards/b/BrushWithDeath.java
index f3a9b2da3ec..78df808785b 100644
--- a/Mage.Sets/src/mage/cards/b/BrushWithDeath.java
+++ b/Mage.Sets/src/mage/cards/b/BrushWithDeath.java
@@ -1,7 +1,5 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.keyword.BuybackAbility;
@@ -10,17 +8,19 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author LoneFox
*/
public final class BrushWithDeath extends CardImpl {
public BrushWithDeath(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
// Buyback {2}{B}{B}
this.addAbility(new BuybackAbility("{2}{B}{B}"));
+
// Target opponent loses 2 life. You gain 2 life.
this.getSpellAbility().addEffect(new LoseLifeTargetEffect(2));
this.getSpellAbility().addEffect(new GainLifeEffect(2));
diff --git a/Mage.Sets/src/mage/cards/b/Brushwagg.java b/Mage.Sets/src/mage/cards/b/Brushwagg.java
index 147d23b284a..d6c6e568b64 100644
--- a/Mage.Sets/src/mage/cards/b/Brushwagg.java
+++ b/Mage.Sets/src/mage/cards/b/Brushwagg.java
@@ -3,7 +3,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class Brushwagg extends CardImpl {
this.toughness = new MageInt(2);
// Whenever Brushwagg blocks or becomes blocked, it gets -2/+2 until end of turn.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(-2, 2, Duration.EndOfTurn), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(-2, 2, Duration.EndOfTurn), false));
}
public Brushwagg(final Brushwagg card) {
diff --git a/Mage.Sets/src/mage/cards/b/BrutalizerExarch.java b/Mage.Sets/src/mage/cards/b/BrutalizerExarch.java
index de15f1581de..308ddc69c14 100644
--- a/Mage.Sets/src/mage/cards/b/BrutalizerExarch.java
+++ b/Mage.Sets/src/mage/cards/b/BrutalizerExarch.java
@@ -83,13 +83,9 @@ class BrutalizerExarchEffect2 extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
- if (permanent != null) {
- Player player = game.getPlayer(permanent.getOwnerId());
- if (player == null) {
- return false;
- }
-
- return permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
+ Player controller = game.getPlayer(source.getControllerId());
+ if (permanent != null && controller != null) {
+ return controller.putCardsOnBottomOfLibrary(permanent, game, source, true);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/b/BruvacTheGrandiloquent.java b/Mage.Sets/src/mage/cards/b/BruvacTheGrandiloquent.java
new file mode 100644
index 00000000000..be1371b8650
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BruvacTheGrandiloquent.java
@@ -0,0 +1,80 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.util.CardUtil;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BruvacTheGrandiloquent extends CardImpl {
+
+ public BruvacTheGrandiloquent(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.ADVISOR);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(4);
+
+ // If an opponent would mill one or more cards, they mill twice that many cards instead.
+ this.addAbility(new SimpleStaticAbility(new BruvacTheGrandiloquentReplacementEffect()));
+ }
+
+ private BruvacTheGrandiloquent(final BruvacTheGrandiloquent card) {
+ super(card);
+ }
+
+ @Override
+ public BruvacTheGrandiloquent copy() {
+ return new BruvacTheGrandiloquent(this);
+ }
+}
+
+class BruvacTheGrandiloquentReplacementEffect extends ReplacementEffectImpl {
+
+ BruvacTheGrandiloquentReplacementEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.Neutral);
+ staticText = "If an opponent would mill one or more cards, they mill twice that many cards instead";
+ }
+
+ private BruvacTheGrandiloquentReplacementEffect(final BruvacTheGrandiloquentReplacementEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public BruvacTheGrandiloquentReplacementEffect copy() {
+ return new BruvacTheGrandiloquentReplacementEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.MILL_CARDS;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ return game.getOpponents(source.getControllerId()).contains(event.getPlayerId());
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ event.setAmount(CardUtil.addWithOverflowCheck(event.getAmount(), event.getAmount()));
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BuildersBane.java b/Mage.Sets/src/mage/cards/b/BuildersBane.java
index 98b8621a8d6..d29d7db6058 100644
--- a/Mage.Sets/src/mage/cards/b/BuildersBane.java
+++ b/Mage.Sets/src/mage/cards/b/BuildersBane.java
@@ -77,7 +77,7 @@ class BuildersBaneEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(targetID);
if (permanent != null) {
if (permanent.destroy(source.getSourceId(), game, false)) {
- game.applyEffects();
+ game.getState().processAction(game);
if (permanent.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(permanent.getId())
&& game.getState().getZone(permanent.getId()) != Zone.GRAVEYARD) {
// A replacement effect has moved the card to another zone as grvayard
diff --git a/Mage.Sets/src/mage/cards/b/BumpInTheNight.java b/Mage.Sets/src/mage/cards/b/BumpInTheNight.java
index 9dc048b4cfc..024b2619e44 100644
--- a/Mage.Sets/src/mage/cards/b/BumpInTheNight.java
+++ b/Mage.Sets/src/mage/cards/b/BumpInTheNight.java
@@ -1,7 +1,5 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.keyword.FlashbackAbility;
@@ -11,14 +9,15 @@ import mage.constants.CardType;
import mage.constants.TimingRule;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
* @author nantuko
*/
public final class BumpInTheNight extends CardImpl {
public BumpInTheNight(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{B}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}");
// Target opponent loses 3 life.
this.getSpellAbility().addEffect(new LoseLifeTargetEffect(3));
diff --git a/Mage.Sets/src/mage/cards/b/BurlfistOak.java b/Mage.Sets/src/mage/cards/b/BurlfistOak.java
new file mode 100644
index 00000000000..66bd617a800
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/b/BurlfistOak.java
@@ -0,0 +1,40 @@
+package mage.cards.b;
+
+import mage.MageInt;
+import mage.abilities.common.DrawCardControllerTriggeredAbility;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class BurlfistOak extends CardImpl {
+
+ public BurlfistOak(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
+
+ this.subtype.add(SubType.TREEFOLK);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Whenever you draw a card, Burlfist Oak gets +2/+2 until end of turn.
+ this.addAbility(new DrawCardControllerTriggeredAbility(
+ new BoostSourceEffect(2, 2, Duration.EndOfTurn), false
+ ));
+ }
+
+ private BurlfistOak(final BurlfistOak card) {
+ super(card);
+ }
+
+ @Override
+ public BurlfistOak copy() {
+ return new BurlfistOak(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/b/BurningEyeZubera.java b/Mage.Sets/src/mage/cards/b/BurningEyeZubera.java
index e916504a73b..d8d34f9dd0a 100644
--- a/Mage.Sets/src/mage/cards/b/BurningEyeZubera.java
+++ b/Mage.Sets/src/mage/cards/b/BurningEyeZubera.java
@@ -4,7 +4,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -31,7 +31,7 @@ public final class BurningEyeZubera extends CardImpl {
this.toughness = new MageInt(3);
// When Burning-Eye Zubera dies, if 4 or more damage was dealt to it this turn, Burning-Eye Zubera deals 3 damage to any target.
- Ability ability = new ConditionalInterveningIfTriggeredAbility(new DiesTriggeredAbility(new DamageTargetEffect(3)),new SourceGotFourDamage(),
+ Ability ability = new ConditionalInterveningIfTriggeredAbility(new DiesSourceTriggeredAbility(new DamageTargetEffect(3)),new SourceGotFourDamage(),
"When {this} dies, if 4 or more damage was dealt to it this turn, Burning-Eye Zubera deals 3 damage to any target");
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/b/BurningInquiry.java b/Mage.Sets/src/mage/cards/b/BurningInquiry.java
index 6691d8323b3..b8f1670d93d 100644
--- a/Mage.Sets/src/mage/cards/b/BurningInquiry.java
+++ b/Mage.Sets/src/mage/cards/b/BurningInquiry.java
@@ -1,7 +1,5 @@
-
package mage.cards.b;
-import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.discard.DiscardEachPlayerEffect;
@@ -9,24 +7,24 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class BurningInquiry extends CardImpl {
public BurningInquiry(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{R}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}");
// Each player draws three cards, then discards three cards at random.
this.getSpellAbility().addEffect(new DrawCardAllEffect(3));
Effect effect = new DiscardEachPlayerEffect(3, true);
- effect.setText("then discards three cards at random");
+ effect.setText(", then discards three cards at random");
this.getSpellAbility().addEffect(effect);
}
- public BurningInquiry(final BurningInquiry card) {
+ private BurningInquiry(final BurningInquiry card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/b/BywayCourier.java b/Mage.Sets/src/mage/cards/b/BywayCourier.java
index 6e66b6a06d2..dbf1f1d5f01 100644
--- a/Mage.Sets/src/mage/cards/b/BywayCourier.java
+++ b/Mage.Sets/src/mage/cards/b/BywayCourier.java
@@ -3,7 +3,7 @@ package mage.cards.b;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.keyword.InvestigateEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class BywayCourier extends CardImpl {
this.toughness = new MageInt(2);
// When Byway Courier dies, investigate.
- this.addAbility(new DiesTriggeredAbility(new InvestigateEffect(), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new InvestigateEffect(), false));
}
public BywayCourier(final BywayCourier card) {
diff --git a/Mage.Sets/src/mage/cards/c/CabalTherapist.java b/Mage.Sets/src/mage/cards/c/CabalTherapist.java
index 96978c84ee8..66ed076a807 100644
--- a/Mage.Sets/src/mage/cards/c/CabalTherapist.java
+++ b/Mage.Sets/src/mage/cards/c/CabalTherapist.java
@@ -3,23 +3,23 @@ package mage.cards.c;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
-import mage.abilities.effects.common.DoIfCostPaid;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
+import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.keyword.MenaceAbility;
import mage.cards.*;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.filter.StaticFilters;
import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetControlledPermanent;
-import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.UUID;
@@ -40,16 +40,17 @@ public final class CabalTherapist extends CardImpl {
this.addAbility(new MenaceAbility());
// At the beginning of your precombat main phase, you may sacrifice a creature. When you do, choose a nonland card name, then target player reveals their hand and discards all cards with that name.
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME),
+ false, "choose a nonland card name, then target player " +
+ "reveals their hand and discards all cards with that name"
+ );
+ ability.addEffect(new CabalTherapistDiscardEffect());
+ ability.addTarget(new TargetPlayer());
this.addAbility(new BeginningOfPreCombatMainTriggeredAbility(
- new DoIfCostPaid(
- new CabalTherapistCreateReflexiveTriggerEffect(),
- new SacrificeTargetCost(new TargetControlledPermanent(
- StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT
- )), "Sacrifice a creature?"
- ).setText("you may sacrifice a creature. When you do, " +
- "choose a nonland card name, then target player reveals their hand " +
- "and discards all cards with that name."),
- TargetController.YOU, false
+ new DoWhenCostPaid(ability, new SacrificeTargetCost(
+ new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT)
+ ), "Sacrifice a creature?"), TargetController.YOU, false
));
}
@@ -63,62 +64,6 @@ public final class CabalTherapist extends CardImpl {
}
}
-class CabalTherapistCreateReflexiveTriggerEffect extends OneShotEffect {
-
- CabalTherapistCreateReflexiveTriggerEffect() {
- super(Outcome.Benefit);
- }
-
- private CabalTherapistCreateReflexiveTriggerEffect(final CabalTherapistCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public CabalTherapistCreateReflexiveTriggerEffect copy() {
- return new CabalTherapistCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new CabalTherapistReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class CabalTherapistReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- CabalTherapistReflexiveTriggeredAbility() {
- super(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME), Duration.OneUse, true);
- this.addEffect(new CabalTherapistDiscardEffect());
- this.addTarget(new TargetPlayer());
- }
-
- private CabalTherapistReflexiveTriggeredAbility(final CabalTherapistReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public CabalTherapistReflexiveTriggeredAbility copy() {
- return new CabalTherapistReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "Choose a nonland card name, then target player reveals their hand and discards all cards with that name.";
- }
-}
-
class CabalTherapistDiscardEffect extends OneShotEffect {
CabalTherapistDiscardEffect() {
@@ -138,22 +83,16 @@ class CabalTherapistDiscardEffect extends OneShotEffect {
return false;
}
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- Cards hand = targetPlayer.getHand();
-
- for (Card card : hand.getCards(game)) {
- if (card.isSplitCard()) {
- SplitCard splitCard = (SplitCard) card;
- if (CardUtil.haveSameNames(splitCard.getLeftHalfCard().getName(), cardName)) {
- targetPlayer.discard(card, source, game);
- } else if (CardUtil.haveSameNames(splitCard.getRightHalfCard().getName(), cardName)) {
- targetPlayer.discard(card, source, game);
- }
+ Cards hand = targetPlayer.getHand().copy();
+ targetPlayer.revealCards(source, hand, game);
+ hand.removeIf(uuid -> {
+ Card card = hand.get(uuid, game);
+ if (card == null) {
+ return true;
}
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
- targetPlayer.discard(card, source, game);
- }
- }
- targetPlayer.revealCards("Cabal Therapist", hand, game);
+ return !CardUtil.haveSameNames(card, cardName, game);
+ });
+ targetPlayer.discard(hand, source, game);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/c/CabalTherapy.java b/Mage.Sets/src/mage/cards/c/CabalTherapy.java
index ba03643b0a7..0a25b54b9c0 100644
--- a/Mage.Sets/src/mage/cards/c/CabalTherapy.java
+++ b/Mage.Sets/src/mage/cards/c/CabalTherapy.java
@@ -64,25 +64,20 @@ class CabalTherapyEffect extends OneShotEffect {
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
- if (targetPlayer != null && controller != null && sourceObject != null) {
- String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- Cards hand = targetPlayer.getHand();
-
- for (Card card : hand.getCards(game)) {
- if (card.isSplitCard()) {
- SplitCard splitCard = (SplitCard) card;
- if (CardUtil.haveSameNames(splitCard.getLeftHalfCard().getName(), cardName)) {
- targetPlayer.discard(card, source, game);
- } else if (CardUtil.haveSameNames(splitCard.getRightHalfCard().getName(), cardName)) {
- targetPlayer.discard(card, source, game);
- }
- }
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
- targetPlayer.discard(card, source, game);
- }
- }
- targetPlayer.revealCards("Cabal Therapy", hand, game);
+ if (targetPlayer == null || controller == null || sourceObject == null) {
+ return false;
}
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ Cards hand = targetPlayer.getHand().copy();
+ targetPlayer.revealCards(source, hand, game);
+ hand.removeIf(uuid -> {
+ Card card = hand.get(uuid, game);
+ if (card == null) {
+ return true;
+ }
+ return !CardUtil.haveSameNames(card, cardName, game);
+ });
+ targetPlayer.discard(hand, source, game);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/c/CagedZombie.java b/Mage.Sets/src/mage/cards/c/CagedZombie.java
new file mode 100644
index 00000000000..a505d648ad8
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/CagedZombie.java
@@ -0,0 +1,48 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.condition.common.MorbidCondition;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.decorator.ConditionalActivatedAbility;
+import mage.abilities.effects.common.LoseLifeOpponentsEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.watchers.common.MorbidWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class CagedZombie extends CardImpl {
+
+ public CagedZombie(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
+
+ this.subtype.add(SubType.ZOMBIE);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // {1}{B}, {T}: Each opponent loses 2 life. Activate this ability only if a creature died this turn.
+ Ability ability = new ConditionalActivatedAbility(
+ Zone.BATTLEFIELD, new LoseLifeOpponentsEffect(2),
+ new ManaCostsImpl("{1}{B}"), MorbidCondition.instance
+ );
+ ability.addCost(new TapSourceCost());
+ this.addAbility(ability, new MorbidWatcher());
+ }
+
+ private CagedZombie(final CagedZombie card) {
+ super(card);
+ }
+
+ @Override
+ public CagedZombie copy() {
+ return new CagedZombie(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/CallapheBelovedOfTheSea.java b/Mage.Sets/src/mage/cards/c/CallapheBelovedOfTheSea.java
index 4e245e095f1..1baa9de971d 100644
--- a/Mage.Sets/src/mage/cards/c/CallapheBelovedOfTheSea.java
+++ b/Mage.Sets/src/mage/cards/c/CallapheBelovedOfTheSea.java
@@ -2,23 +2,18 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.DevotionCount;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.common.continuous.SetPowerSourceEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
+import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
-import mage.game.Game;
-import mage.target.Target;
-import mage.util.CardUtil;
-import java.util.Collection;
import java.util.UUID;
/**
@@ -51,11 +46,12 @@ public final class CallapheBelovedOfTheSea extends CardImpl {
).addHint(DevotionCount.U.getHint()));
// Creatures and enchantments you control have "Spells your opponents cast that target this permanent cost {1} more to cast".
- this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
- new SimpleStaticAbility(
- new CallapheBelovedOfTheSeaEffect()
- ), Duration.WhileOnBattlefield, filter)
- .withForceQuotes()
+ Ability gainAbility = new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(1, new FilterCard("Spells"), TargetController.OPPONENT)
+ .withTargetName("this permanent")
+ );
+ this.addAbility(new SimpleStaticAbility(
+ new GainAbilityControlledEffect(gainAbility, Duration.WhileOnBattlefield, filter).withForceQuotes()
));
}
@@ -68,45 +64,3 @@ public final class CallapheBelovedOfTheSea extends CardImpl {
return new CallapheBelovedOfTheSea(this);
}
}
-
-class CallapheBelovedOfTheSeaEffect extends CostModificationEffectImpl {
-
- CallapheBelovedOfTheSeaEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Spells your opponents cast that target this permanent cost {1} more to cast";
- }
-
- private CallapheBelovedOfTheSeaEffect(CallapheBelovedOfTheSeaEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -1);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (!(abilityToModify instanceof SpellAbility)
- || !game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- return false;
- }
- return abilityToModify
- .getModes()
- .getSelectedModes()
- .stream()
- .map(uuid -> abilityToModify.getModes().get(uuid))
- .map(Mode::getTargets)
- .flatMap(Collection::stream)
- .map(Target::getTargets)
- .flatMap(Collection::stream)
- .anyMatch(uuid -> uuid.equals(source.getSourceId()));
- }
-
- @Override
- public CallapheBelovedOfTheSeaEffect copy() {
- return new CallapheBelovedOfTheSeaEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/c/CanopyStalker.java b/Mage.Sets/src/mage/cards/c/CanopyStalker.java
new file mode 100644
index 00000000000..6a8c4fd2d47
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/CanopyStalker.java
@@ -0,0 +1,47 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.common.DiesSourceTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.common.CreaturesDiedThisTurnCount;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.watchers.common.CreaturesDiedWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class CanopyStalker extends CardImpl {
+
+ public CanopyStalker(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
+
+ this.subtype.add(SubType.CAT);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(2);
+
+ // Canopy Stalker must be blocked if able.
+ this.addAbility(new SimpleStaticAbility(new MustBeBlockedByAtLeastOneSourceEffect()));
+
+ // When Canopy Stalker dies, you gain 1 life for each creature that died this turn.
+ this.addAbility(new DiesSourceTriggeredAbility(
+ new GainLifeEffect(CreaturesDiedThisTurnCount.instance)
+ .setText("you gain 1 life for each creature that died this turn")
+ ), new CreaturesDiedWatcher());
+ }
+
+ private CanopyStalker(final CanopyStalker card) {
+ super(card);
+ }
+
+ @Override
+ public CanopyStalker copy() {
+ return new CanopyStalker(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/CarelessCelebrant.java b/Mage.Sets/src/mage/cards/c/CarelessCelebrant.java
index 6b97dd3bd2f..c2fbb8e0b10 100644
--- a/Mage.Sets/src/mage/cards/c/CarelessCelebrant.java
+++ b/Mage.Sets/src/mage/cards/c/CarelessCelebrant.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -40,7 +40,7 @@ public final class CarelessCelebrant extends CardImpl {
this.toughness = new MageInt(1);
// When Careless Celebrant dies, it deals 2 damage to target creature or planeswalker an opponent controls.
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(2, "it"));
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(2, "it"));
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/c/CarnageTyrant.java b/Mage.Sets/src/mage/cards/c/CarnageTyrant.java
index d252b783900..ed47c44b286 100644
--- a/Mage.Sets/src/mage/cards/c/CarnageTyrant.java
+++ b/Mage.Sets/src/mage/cards/c/CarnageTyrant.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.HexproofAbility;
import mage.cards.CardImpl;
@@ -25,7 +25,7 @@ public final class CarnageTyrant extends CardImpl {
this.toughness = new MageInt(6);
// Carnage Tyrant can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Trample
this.addAbility(TrampleAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/c/CarrierThrall.java b/Mage.Sets/src/mage/cards/c/CarrierThrall.java
index d6bc7cea232..94e3bf2813a 100644
--- a/Mage.Sets/src/mage/cards/c/CarrierThrall.java
+++ b/Mage.Sets/src/mage/cards/c/CarrierThrall.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class CarrierThrall extends CardImpl {
// When Carrier Thrall dies, create a 1/1 colorless Eldrazi Scion creature token. It has "Sacrifice this creature. Add {C}."
Effect effect = new CreateTokenEffect(new EldraziScionToken());
effect.setText("create a 1/1 colorless Eldrazi Scion creature token. It has \"Sacrifice this creature: Add {C}.\"");
- this.addAbility(new DiesTriggeredAbility(effect, false));
+ this.addAbility(new DiesSourceTriggeredAbility(effect, false));
}
diff --git a/Mage.Sets/src/mage/cards/c/CarrionBeetles.java b/Mage.Sets/src/mage/cards/c/CarrionBeetles.java
index beb63b63669..a8eb3bd5703 100644
--- a/Mage.Sets/src/mage/cards/c/CarrionBeetles.java
+++ b/Mage.Sets/src/mage/cards/c/CarrionBeetles.java
@@ -1,40 +1,36 @@
-
package mage.cards.c;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
+import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Outcome;
import mage.constants.Zone;
-import mage.filter.FilterCard;
-import mage.game.Game;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInASingleGraveyard;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class CarrionBeetles extends CardImpl {
public CarrionBeetles(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
this.subtype.add(SubType.INSECT);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
- // {2}{B}, {tap}: Exile up to three target cards from a single graveyard.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CarrionBeetlesExileEffect(), new ManaCostsImpl("{2}{B}"));
+ // {2}{B}, {T}: Exile up to three target cards from a single graveyard.
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new ManaCostsImpl("{2}{B}"));
ability.addCost(new TapSourceCost());
- ability.addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("up to three target cards from a single graveyard")));
+ ability.addTarget(new TargetCardInASingleGraveyard(0, 3, StaticFilters.FILTER_CARD_CARDS));
this.addAbility(ability);
}
@@ -47,31 +43,3 @@ public final class CarrionBeetles extends CardImpl {
return new CarrionBeetles(this);
}
}
-
-class CarrionBeetlesExileEffect extends OneShotEffect {
-
- public CarrionBeetlesExileEffect() {
- super(Outcome.Exile);
- this.staticText = "Exile up to three target cards from a single graveyard";
- }
-
- public CarrionBeetlesExileEffect(final CarrionBeetlesExileEffect effect) {
- super(effect);
- }
-
- @Override
- public CarrionBeetlesExileEffect copy() {
- return new CarrionBeetlesExileEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (UUID targetID : source.getTargets().get(0).getTargets()) {
- Card card = game.getCard(targetID);
- if (card != null) {
- card.moveToExile(null, "", source.getSourceId(), game);
- }
- }
- return true;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/c/CarrionGrub.java b/Mage.Sets/src/mage/cards/c/CarrionGrub.java
new file mode 100644
index 00000000000..b0f52fc7911
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/CarrionGrub.java
@@ -0,0 +1,89 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.StaticValue;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.game.Game;
+import mage.players.Player;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class CarrionGrub extends CardImpl {
+
+ public CarrionGrub(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
+
+ this.subtype.add(SubType.INSECT);
+ this.power = new MageInt(0);
+ this.toughness = new MageInt(5);
+
+ // Carrion Grub gets +X/+0, where X is the greatest power among creature cards in your graveyard.
+ this.addAbility(new SimpleStaticAbility(new BoostSourceEffect(
+ CarrionGrubValue.instance, StaticValue.get(0), Duration.WhileOnBattlefield
+ )));
+
+ // When Carrion Grub enters the battlefield, mill four cards.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new PutTopCardOfLibraryIntoGraveControllerEffect(4)));
+ }
+
+ private CarrionGrub(final CarrionGrub card) {
+ super(card);
+ }
+
+ @Override
+ public CarrionGrub copy() {
+ return new CarrionGrub(this);
+ }
+}
+
+enum CarrionGrubValue implements DynamicValue {
+ instance;
+
+ @Override
+ public int calculate(Game game, Ability sourceAbility, Effect effect) {
+ Player player = game.getPlayer(sourceAbility.getControllerId());
+ if (player == null) {
+ return 0;
+ }
+ return player.getGraveyard()
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(MageObject::isCreature)
+ .map(MageObject::getPower)
+ .mapToInt(MageInt::getValue)
+ .max()
+ .orElse(0);
+ }
+
+ @Override
+ public CarrionGrubValue copy() {
+ return instance;
+ }
+
+ @Override
+ public String getMessage() {
+ return "the greatest power among creature cards in your graveyard";
+ }
+
+ @Override
+ public String toString() {
+ return "X";
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/c/CarrionThrash.java b/Mage.Sets/src/mage/cards/c/CarrionThrash.java
index 0bc6afc9f8c..62b96da57ef 100644
--- a/Mage.Sets/src/mage/cards/c/CarrionThrash.java
+++ b/Mage.Sets/src/mage/cards/c/CarrionThrash.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
@@ -36,7 +36,7 @@ public final class CarrionThrash extends CardImpl {
this.toughness = new MageInt(4);
// When Carrion Thrash dies, you may pay {2}. If you do, return another target creature card from your graveyard to your hand.
- DiesTriggeredAbility ability = new DiesTriggeredAbility(new DoIfCostPaid(new ReturnToHandTargetEffect(), new GenericManaCost(2)), false);
+ DiesSourceTriggeredAbility ability = new DiesSourceTriggeredAbility(new DoIfCostPaid(new ReturnToHandTargetEffect(), new GenericManaCost(2)), false);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/c/CastThroughTime.java b/Mage.Sets/src/mage/cards/c/CastThroughTime.java
index 1693ae89d58..14b0171384f 100644
--- a/Mage.Sets/src/mage/cards/c/CastThroughTime.java
+++ b/Mage.Sets/src/mage/cards/c/CastThroughTime.java
@@ -89,7 +89,7 @@ class GainReboundEffect extends ContinuousEffectImpl {
private void addReboundAbility(Card card, Game game) {
if (CastThroughTime.filter.match(card, game)) {
- boolean found = card.getAbilities(game).stream().anyMatch(ability -> ability instanceof ReboundAbility);
+ boolean found = card.getAbilities(game).containsClass(ReboundAbility.class);
if (!found) {
Ability ability = new ReboundAbility();
game.getState().addOtherAbility(card, ability);
diff --git a/Mage.Sets/src/mage/cards/c/CatharsCompanion.java b/Mage.Sets/src/mage/cards/c/CatharsCompanion.java
index d26614f24ff..f42b71fd1e1 100644
--- a/Mage.Sets/src/mage/cards/c/CatharsCompanion.java
+++ b/Mage.Sets/src/mage/cards/c/CatharsCompanion.java
@@ -27,7 +27,7 @@ public final class CatharsCompanion extends CardImpl {
public CatharsCompanion(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/c/Cathodion.java b/Mage.Sets/src/mage/cards/c/Cathodion.java
index 7de6f730f6e..212d3a68727 100644
--- a/Mage.Sets/src/mage/cards/c/Cathodion.java
+++ b/Mage.Sets/src/mage/cards/c/Cathodion.java
@@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.Mana;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -22,7 +22,7 @@ public final class Cathodion extends CardImpl {
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
- this.addAbility(new DiesTriggeredAbility(new BasicManaEffect(Mana.ColorlessMana(3)), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new BasicManaEffect(Mana.ColorlessMana(3)), false));
}
public Cathodion(final Cathodion card) {
diff --git a/Mage.Sets/src/mage/cards/c/CauldronsGift.java b/Mage.Sets/src/mage/cards/c/CauldronsGift.java
index 923e9568a8d..6d936425fff 100644
--- a/Mage.Sets/src/mage/cards/c/CauldronsGift.java
+++ b/Mage.Sets/src/mage/cards/c/CauldronsGift.java
@@ -47,8 +47,7 @@ class CauldronsGiftEffect extends OneShotEffect {
CauldronsGiftEffect() {
super(Outcome.Benefit);
staticText = "Adamant — If at least three black mana was spent to cast this spell, " +
- "put the top four cards of your library into your graveyard." +
- "
You may choose a creature card in your graveyard. " +
+ "mill four cards.
You may choose a creature card in your graveyard. " +
"If you do, return it to the battlefield with an additional +1/+1 counter on it.";
}
@@ -68,7 +67,7 @@ class CauldronsGiftEffect extends OneShotEffect {
return false;
}
if (AdamantCondition.BLACK.apply(game, source)) {
- player.moveCards(player.getLibrary().getTopCards(game, 4), Zone.GRAVEYARD, source, game);
+ player.millCards(4, source, game);
}
if (player.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game) == 0
|| !player.chooseUse(outcome, "Choose a creature card in your graveyard to return to the battlefield?", source, game)) {
diff --git a/Mage.Sets/src/mage/cards/c/CausticHound.java b/Mage.Sets/src/mage/cards/c/CausticHound.java
index 021f30af70a..f01e20fae40 100644
--- a/Mage.Sets/src/mage/cards/c/CausticHound.java
+++ b/Mage.Sets/src/mage/cards/c/CausticHound.java
@@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.LoseLifeAllPlayersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -19,11 +19,11 @@ public final class CausticHound extends CardImpl {
public CausticHound (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{B}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
- this.addAbility(new DiesTriggeredAbility(new LoseLifeAllPlayersEffect(4)));
+ this.addAbility(new DiesSourceTriggeredAbility(new LoseLifeAllPlayersEffect(4)));
}
public CausticHound (final CausticHound card) {
diff --git a/Mage.Sets/src/mage/cards/c/CavalierOfDawn.java b/Mage.Sets/src/mage/cards/c/CavalierOfDawn.java
index 2eba411769f..a77ae3e3fd2 100644
--- a/Mage.Sets/src/mage/cards/c/CavalierOfDawn.java
+++ b/Mage.Sets/src/mage/cards/c/CavalierOfDawn.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@@ -51,7 +51,7 @@ public final class CavalierOfDawn extends CardImpl {
this.addAbility(ability);
// When Cavalier of Dawn dies, return target artifact or enchantment card from your graveyard to your hand.
- ability = new DiesTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
+ ability = new DiesSourceTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/c/CavalierOfFlame.java b/Mage.Sets/src/mage/cards/c/CavalierOfFlame.java
index 01e5b3e0705..4de1d6c0877 100644
--- a/Mage.Sets/src/mage/cards/c/CavalierOfFlame.java
+++ b/Mage.Sets/src/mage/cards/c/CavalierOfFlame.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -16,6 +16,7 @@ import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
@@ -60,7 +61,7 @@ public final class CavalierOfFlame extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new CavalierOfFlameEffect()));
// When Cavalier of Flame dies, it deals X damage to each opponent and each planeswalker they control, where X is the number of land cards in your graveyard.
- ability = new DiesTriggeredAbility(new DamagePlayersEffect(
+ ability = new DiesSourceTriggeredAbility(new DamagePlayersEffect(
Outcome.Damage, xValue, TargetController.OPPONENT
).setText("it deals X damage to each opponent"));
ability.addEffect(new DamageAllEffect(
@@ -103,14 +104,9 @@ class CavalierOfFlameEffect extends OneShotEffect {
}
TargetCardInHand target = new TargetCardInHand(0, player.getHand().size(), StaticFilters.FILTER_CARD);
if (player.choose(Outcome.Discard, player.getHand(), target, game)) {
- int counter = target
- .getTargets()
- .stream()
- .map(uuid -> game.getCard(uuid))
- .mapToInt(card -> card != null && player.discard(card, source, game) ? 1 : 0)
- .sum();
+ int counter = player.discard(new CardsImpl(target.getTargets()), source, game).size();
player.drawCards(counter, source.getSourceId(), game);
}
return true;
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/c/CavalierOfGales.java b/Mage.Sets/src/mage/cards/c/CavalierOfGales.java
index e972f50c393..76f16388fab 100644
--- a/Mage.Sets/src/mage/cards/c/CavalierOfGales.java
+++ b/Mage.Sets/src/mage/cards/c/CavalierOfGales.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.BrainstormEffect;
import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect;
@@ -35,7 +35,7 @@ public final class CavalierOfGales extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new BrainstormEffect()));
// When Cavalier of Gales dies, shuffle it into its owner's library, then scry 2.
- Ability ability = new DiesTriggeredAbility(new ShuffleIntoLibrarySourceEffect());
+ Ability ability = new DiesSourceTriggeredAbility(new ShuffleIntoLibrarySourceEffect());
ability.addEffect(new ScryEffect(2).concatBy(", then"));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/c/CavalierOfNight.java b/Mage.Sets/src/mage/cards/c/CavalierOfNight.java
index 47437215ba5..2020c78e3d8 100644
--- a/Mage.Sets/src/mage/cards/c/CavalierOfNight.java
+++ b/Mage.Sets/src/mage/cards/c/CavalierOfNight.java
@@ -2,27 +2,25 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
-import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.ComparisonType;
+import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.filter.predicate.permanent.AnotherPredicate;
-import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
@@ -56,13 +54,17 @@ public final class CavalierOfNight extends CardImpl {
this.addAbility(LifelinkAbility.getInstance());
// When Cavalier of Night enters the battlefield, you may sacrifice another creature. When you do, destroy target creature an opponent controls.
- this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(
- new CavalierOfNightCreateReflexiveTriggerEffect(),
- new SacrificeTargetCost(new TargetControlledPermanent(filter))
- ).setText("you may sacrifice another creature. When you do, destroy target creature an opponent controls.")));
+ ReflexiveTriggeredAbility triggeredAbility = new ReflexiveTriggeredAbility(
+ new DestroyTargetEffect(), false, "Sacrifice a creature?"
+ );
+ triggeredAbility.addTarget(new TargetOpponentsCreaturePermanent());
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new DoWhenCostPaid(
+ triggeredAbility, new SacrificeTargetCost(new TargetControlledPermanent(filter)),
+ "destroy target creature an opponent controls"
+ )));
// When Cavalier of Night dies, return target creature card with converted mana cost 3 or less from your graveyard to the battlefield.
- Ability ability = new DiesTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect());
+ Ability ability = new DiesSourceTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect());
ability.addTarget(new TargetCardInYourGraveyard(filter2));
this.addAbility(ability);
}
@@ -76,58 +78,3 @@ public final class CavalierOfNight extends CardImpl {
return new CavalierOfNight(this);
}
}
-
-class CavalierOfNightCreateReflexiveTriggerEffect extends OneShotEffect {
-
- CavalierOfNightCreateReflexiveTriggerEffect() {
- super(Outcome.Benefit);
- }
-
- private CavalierOfNightCreateReflexiveTriggerEffect(final CavalierOfNightCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public CavalierOfNightCreateReflexiveTriggerEffect copy() {
- return new CavalierOfNightCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new CavalierOfNightReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class CavalierOfNightReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- CavalierOfNightReflexiveTriggeredAbility() {
- super(new DestroyTargetEffect(), Duration.OneUse, true);
- this.addTarget(new TargetOpponentsCreaturePermanent());
- }
-
- private CavalierOfNightReflexiveTriggeredAbility(final CavalierOfNightReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public CavalierOfNightReflexiveTriggeredAbility copy() {
- return new CavalierOfNightReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "Destroy target creature an opponent controls";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/c/CavalierOfThorns.java b/Mage.Sets/src/mage/cards/c/CavalierOfThorns.java
index eabcf3643db..14b84ac4a13 100644
--- a/Mage.Sets/src/mage/cards/c/CavalierOfThorns.java
+++ b/Mage.Sets/src/mage/cards/c/CavalierOfThorns.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.effects.OneShotEffect;
@@ -50,7 +50,7 @@ public final class CavalierOfThorns extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new CavalierOfThornsEffect()));
// When Cavalier of Thorns dies, you may exile it. If you do, put another target card from your graveyard on top of your library.
- Ability ability = new DiesTriggeredAbility(new DoIfCostPaid(
+ Ability ability = new DiesSourceTriggeredAbility(new DoIfCostPaid(
new PutOnLibraryTargetEffect(true), new ExileSourceFromGraveCost()
).setText("you may exile it. If you do, put another target card from your graveyard on top of your library."));
ability.addTarget(new TargetCardInYourGraveyard(filter));
diff --git a/Mage.Sets/src/mage/cards/c/CavernOfSouls.java b/Mage.Sets/src/mage/cards/c/CavernOfSouls.java
index 1700ea17be9..bea0f012e58 100644
--- a/Mage.Sets/src/mage/cards/c/CavernOfSouls.java
+++ b/Mage.Sets/src/mage/cards/c/CavernOfSouls.java
@@ -1,11 +1,11 @@
package mage.cards.c;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
+import java.util.*;
+
import mage.ConditionalMana;
import mage.MageObject;
+import mage.MageObjectReference;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
@@ -121,7 +121,7 @@ class CavernOfSoulsManaCondition extends CreatureCastManaCondition {
class CavernOfSoulsWatcher extends Watcher {
- private List spells = new ArrayList<>();
+ private final Set spells = new HashSet<>();
private final UUID originalId;
public CavernOfSoulsWatcher(UUID originalId) {
@@ -132,14 +132,14 @@ class CavernOfSoulsWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.MANA_PAID) {
- if (event.getData() != null && event.getData().equals(originalId.toString())) {
- spells.add(event.getTargetId());
+ if (event.getData() != null && event.getData().equals(originalId.toString()) && event.getTargetId() != null) {
+ spells.add(new MageObjectReference(game.getObject(event.getTargetId()), game));
}
}
}
- public boolean spellCantBeCountered(UUID spellId) {
- return spells.contains(spellId);
+ public boolean spellCantBeCountered(MageObjectReference mor) {
+ return spells.contains(mor);
}
@Override
@@ -188,6 +188,6 @@ class CavernOfSoulsCantCounterEffect extends ContinuousRuleModifyingEffectImpl {
public boolean applies(GameEvent event, Ability source, Game game) {
CavernOfSoulsWatcher watcher = game.getState().getWatcher(CavernOfSoulsWatcher.class, source.getSourceId());
Spell spell = game.getStack().getSpell(event.getTargetId());
- return spell != null && watcher != null && watcher.spellCantBeCountered(spell.getId());
+ return spell != null && watcher != null && watcher.spellCantBeCountered(new MageObjectReference(spell, game));
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CelestialEnforcer.java b/Mage.Sets/src/mage/cards/c/CelestialEnforcer.java
new file mode 100644
index 00000000000..5bf8ffdea17
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/CelestialEnforcer.java
@@ -0,0 +1,63 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.ActivateIfConditionActivatedAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class CelestialEnforcer extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterCreaturePermanent("if you control a creature with flying");
+
+ static {
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ }
+
+ private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
+
+ public CelestialEnforcer(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // {1}{W}, {T}: Tap target creature. Activate this ability only if you control a creature with flying.
+ Ability ability = new ActivateIfConditionActivatedAbility(
+ Zone.BATTLEFIELD, new TapTargetEffect(), new ManaCostsImpl("{1}{W}"), condition
+ );
+ ability.addCost(new TapSourceCost());
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ }
+
+ private CelestialEnforcer(final CelestialEnforcer card) {
+ super(card);
+ }
+
+ @Override
+ public CelestialEnforcer copy() {
+ return new CelestialEnforcer(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/CelestialGatekeeper.java b/Mage.Sets/src/mage/cards/c/CelestialGatekeeper.java
index 4acadb8fc56..4a66a77b389 100644
--- a/Mage.Sets/src/mage/cards/c/CelestialGatekeeper.java
+++ b/Mage.Sets/src/mage/cards/c/CelestialGatekeeper.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
@@ -47,7 +47,7 @@ public final class CelestialGatekeeper extends CardImpl {
// When Celestial Gatekeeper dies, exile it, then return up to two target Bird and/or Cleric permanent cards from your graveyard to the battlefield.
Effect effect = new ExileSourceEffect();
effect.setText("");
- DiesTriggeredAbility ability = new DiesTriggeredAbility(effect);
+ DiesSourceTriggeredAbility ability = new DiesSourceTriggeredAbility(effect);
effect = new ReturnFromGraveyardToBattlefieldTargetEffect();
effect.setText("exile it, then return up to two target Bird and/or Cleric permanent cards from your graveyard to the battlefield");
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/c/CentaurSafeguard.java b/Mage.Sets/src/mage/cards/c/CentaurSafeguard.java
index 1ebeea72090..475abe297b2 100644
--- a/Mage.Sets/src/mage/cards/c/CentaurSafeguard.java
+++ b/Mage.Sets/src/mage/cards/c/CentaurSafeguard.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class CentaurSafeguard extends CardImpl {
this.toughness = new MageInt(1);
// When Centaur Safeguard dies, you may gain 3 life.
- this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(3), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(3), true));
}
public CentaurSafeguard(final CentaurSafeguard card) {
diff --git a/Mage.Sets/src/mage/cards/c/CephalidVandal.java b/Mage.Sets/src/mage/cards/c/CephalidVandal.java
index 780863a404a..627b3c11a98 100644
--- a/Mage.Sets/src/mage/cards/c/CephalidVandal.java
+++ b/Mage.Sets/src/mage/cards/c/CephalidVandal.java
@@ -54,7 +54,7 @@ class CephalidVandalEffect extends OneShotEffect {
public CephalidVandalEffect() {
super(Outcome.Neutral);
- staticText = "Then put the top card of your library into your graveyard for each shred counter on {this}";
+ staticText = "Then mill a card for each shred counter on {this}";
}
public CephalidVandalEffect(final CephalidVandalEffect effect) {
@@ -72,7 +72,7 @@ class CephalidVandalEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null && controller != null) {
int amount = permanent.getCounters(game).getCount(CounterType.SHRED);
- controller.moveCards(controller.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ controller.millCards(amount, source, game);
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/c/ChainToMemory.java b/Mage.Sets/src/mage/cards/c/ChainToMemory.java
index 9a58196956a..4e3637b748a 100644
--- a/Mage.Sets/src/mage/cards/c/ChainToMemory.java
+++ b/Mage.Sets/src/mage/cards/c/ChainToMemory.java
@@ -19,7 +19,7 @@ public final class ChainToMemory extends CardImpl {
// Target creature gets -4/-0 until end of turn. Scry 2.
this.getSpellAbility().addEffect(new BoostTargetEffect(-4, 0));
- this.getSpellAbility().addEffect(new ScryEffect(2).setText("Scry 2"));
+ this.getSpellAbility().addEffect(new ScryEffect(2, false));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
diff --git a/Mage.Sets/src/mage/cards/c/ChainedBrute.java b/Mage.Sets/src/mage/cards/c/ChainedBrute.java
new file mode 100644
index 00000000000..6d3134d5118
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChainedBrute.java
@@ -0,0 +1,56 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.ActivateIfConditionActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.MyTurnCondition;
+import mage.abilities.costs.common.SacrificeTargetCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect;
+import mage.abilities.effects.common.UntapSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.filter.StaticFilters;
+import mage.target.common.TargetControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ChainedBrute extends CardImpl {
+
+ public ChainedBrute(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
+
+ this.subtype.add(SubType.DEVIL);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(3);
+
+ // Chained Brute doesn't untap during your untap step.
+ this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepSourceEffect()));
+
+ // {1}, Sacrifice another creature: Untap Chained Brute. Activate this ability only during your turn.
+ Ability ability = new ActivateIfConditionActivatedAbility(
+ Zone.BATTLEFIELD, new UntapSourceEffect(),
+ new GenericManaCost(1), MyTurnCondition.instance
+ );
+ ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(
+ StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE
+ )));
+ this.addAbility(ability);
+ }
+
+ private ChainedBrute(final ChainedBrute card) {
+ super(card);
+ }
+
+ @Override
+ public ChainedBrute copy() {
+ return new ChainedBrute(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/ChainerNightmareAdept.java b/Mage.Sets/src/mage/cards/c/ChainerNightmareAdept.java
index 86a5d53c4fe..a2d1e11dfb5 100644
--- a/Mage.Sets/src/mage/cards/c/ChainerNightmareAdept.java
+++ b/Mage.Sets/src/mage/cards/c/ChainerNightmareAdept.java
@@ -177,6 +177,15 @@ class ChainerNightmareAdeptTriggeredAbility extends EntersBattlefieldAllTriggere
super(Zone.BATTLEFIELD, gainHasteUntilNextTurnEffect, filter, false, SetTargetPointer.PERMANENT, abilityText);
}
+ ChainerNightmareAdeptTriggeredAbility(final ChainerNightmareAdeptTriggeredAbility effect) {
+ super(effect);
+ }
+
+ @Override
+ public ChainerNightmareAdeptTriggeredAbility copy() {
+ return new ChainerNightmareAdeptTriggeredAbility(this);
+ }
+
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!super.checkTrigger(event, game)) {
diff --git a/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java b/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java
index 97210ba99b0..d1e26d77506 100644
--- a/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java
+++ b/Mage.Sets/src/mage/cards/c/ChainsOfMephistopheles.java
@@ -43,7 +43,7 @@ class ChainsOfMephistophelesReplacementEffect extends ReplacementEffectImpl {
public ChainsOfMephistophelesReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
- staticText = "If a player would draw a card except the first one they draw in their draw step each turn, that player discards a card instead. If the player discards a card this way, they draw a card. If the player doesn't discard a card this way, they put the top card of their library into their graveyard";
+ staticText = "If a player would draw a card except the first one they draw in their draw step each turn, that player discards a card instead. If the player discards a card this way, they draw a card. If the player doesn't discard a card this way, they mill a card";
}
public ChainsOfMephistophelesReplacementEffect(final ChainsOfMephistophelesReplacementEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/c/ChakramRetriever.java b/Mage.Sets/src/mage/cards/c/ChakramRetriever.java
index 5f606092e5e..19fc2daf8e5 100644
--- a/Mage.Sets/src/mage/cards/c/ChakramRetriever.java
+++ b/Mage.Sets/src/mage/cards/c/ChakramRetriever.java
@@ -25,7 +25,7 @@ public final class ChakramRetriever extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}");
this.subtype.add(SubType.ELEMENTAL);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(4);
diff --git a/Mage.Sets/src/mage/cards/c/ChamberedNautilus.java b/Mage.Sets/src/mage/cards/c/ChamberedNautilus.java
index e3b917be6cc..a4c20b19e11 100644
--- a/Mage.Sets/src/mage/cards/c/ChamberedNautilus.java
+++ b/Mage.Sets/src/mage/cards/c/ChamberedNautilus.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class ChamberedNautilus extends CardImpl {
this.toughness = new MageInt(2);
// Whenever Chambered Nautilus becomes blocked, you may draw a card.
- this.addAbility(new BecomesBlockedTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
}
public ChamberedNautilus(final ChamberedNautilus card) {
diff --git a/Mage.Sets/src/mage/cards/c/ChampionOfArashin.java b/Mage.Sets/src/mage/cards/c/ChampionOfArashin.java
index 52d66a318cc..a9941dacae9 100644
--- a/Mage.Sets/src/mage/cards/c/ChampionOfArashin.java
+++ b/Mage.Sets/src/mage/cards/c/ChampionOfArashin.java
@@ -17,7 +17,7 @@ public final class ChampionOfArashin extends CardImpl {
public ChampionOfArashin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/c/ChancellorOfTheSpires.java b/Mage.Sets/src/mage/cards/c/ChancellorOfTheSpires.java
index 689fd0bf190..d575eb23c70 100644
--- a/Mage.Sets/src/mage/cards/c/ChancellorOfTheSpires.java
+++ b/Mage.Sets/src/mage/cards/c/ChancellorOfTheSpires.java
@@ -1,36 +1,33 @@
-
package mage.cards.c;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.ChancellorAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PlayTargetWithoutPayingManaEffect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.TargetController;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
-import mage.players.Player;
import mage.target.common.TargetCardInOpponentsGraveyard;
+import java.util.UUID;
+
/**
- *
* @author BetaSteward
*/
public final class ChancellorOfTheSpires extends CardImpl {
- private static final String abilityText = "at the beginning of the first upkeep, each opponent puts the top seven cards of their library into their graveyard";
+ private static final String abilityText = "at the beginning of the first upkeep, each opponent mills seven cards";
private static final FilterCard filter = new FilterCard("instant or sorcery card from an opponent's graveyard");
@@ -41,7 +38,7 @@ public final class ChancellorOfTheSpires extends CardImpl {
}
public ChancellorOfTheSpires(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}{U}");
this.subtype.add(SubType.SPHINX);
this.power = new MageInt(5);
@@ -58,7 +55,7 @@ public final class ChancellorOfTheSpires extends CardImpl {
this.addAbility(ability);
}
- public ChancellorOfTheSpires(final ChancellorOfTheSpires card) {
+ private ChancellorOfTheSpires(final ChancellorOfTheSpires card) {
super(card);
}
@@ -70,11 +67,11 @@ public final class ChancellorOfTheSpires extends CardImpl {
class ChancellorOfTheSpiresDelayedTriggeredAbility extends DelayedTriggeredAbility {
- ChancellorOfTheSpiresDelayedTriggeredAbility () {
- super(new ChancellorOfTheSpiresEffect());
+ ChancellorOfTheSpiresDelayedTriggeredAbility() {
+ super(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(7, TargetController.OPPONENT));
}
- ChancellorOfTheSpiresDelayedTriggeredAbility(ChancellorOfTheSpiresDelayedTriggeredAbility ability) {
+ private ChancellorOfTheSpiresDelayedTriggeredAbility(ChancellorOfTheSpiresDelayedTriggeredAbility ability) {
super(ability);
}
@@ -82,43 +79,14 @@ class ChancellorOfTheSpiresDelayedTriggeredAbility extends DelayedTriggeredAbili
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.UPKEEP_STEP_PRE;
}
-
+
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return true;
}
+
@Override
public ChancellorOfTheSpiresDelayedTriggeredAbility copy() {
return new ChancellorOfTheSpiresDelayedTriggeredAbility(this);
}
}
-
-class ChancellorOfTheSpiresEffect extends OneShotEffect {
-
- ChancellorOfTheSpiresEffect () {
- super(Outcome.Benefit);
- staticText = "each opponent puts the top seven cards of their library into their graveyard";
- }
-
- ChancellorOfTheSpiresEffect(ChancellorOfTheSpiresEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (UUID opponentId : game.getOpponents(source.getControllerId())) {
- Player opponent = game.getPlayer(opponentId);
- if (opponent != null) {
- opponent.moveCards(opponent.getLibrary().getTopCards(game, 7), Zone.GRAVEYARD, source, game);
- }
- }
- return true;
- }
-
- @Override
- public ChancellorOfTheSpiresEffect copy() {
- return new ChancellorOfTheSpiresEffect(this);
- }
-
-}
-
diff --git a/Mage.Sets/src/mage/cards/c/ChandraAblaze.java b/Mage.Sets/src/mage/cards/c/ChandraAblaze.java
index 803758c7035..4128d0687f0 100644
--- a/Mage.Sets/src/mage/cards/c/ChandraAblaze.java
+++ b/Mage.Sets/src/mage/cards/c/ChandraAblaze.java
@@ -172,7 +172,6 @@ class ChandraAblazeEffect5 extends OneShotEffect {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
player.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game));
- player.getGraveyard().remove(card);
cards.remove(card);
}
}
diff --git a/Mage.Sets/src/mage/cards/c/ChandraAcolyteOfFlame.java b/Mage.Sets/src/mage/cards/c/ChandraAcolyteOfFlame.java
index 635252fbf31..131bc23a7e6 100644
--- a/Mage.Sets/src/mage/cards/c/ChandraAcolyteOfFlame.java
+++ b/Mage.Sets/src/mage/cards/c/ChandraAcolyteOfFlame.java
@@ -19,7 +19,6 @@ import mage.counters.CounterType;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPlaneswalkerPermanent;
-import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
import mage.filter.common.FilterInstantOrSorceryCard;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
@@ -27,8 +26,8 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
+import mage.game.permanent.token.RedElementalToken;
import mage.game.permanent.token.Token;
-import mage.game.permanent.token.YoungPyromancerElementalToken;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetpointer.FixedTarget;
@@ -100,7 +99,7 @@ class ChandraAcolyteOfFlameEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Token token = new YoungPyromancerElementalToken();
+ Token token = new RedElementalToken();
token.putOntoBattlefield(2, game, source.getSourceId(), source.getControllerId());
token.getLastAddedTokenIds().stream().forEach(permId -> {
diff --git a/Mage.Sets/src/mage/cards/c/ChandraAwakenedInferno.java b/Mage.Sets/src/mage/cards/c/ChandraAwakenedInferno.java
index c0f61cb557c..8a28de03eb0 100644
--- a/Mage.Sets/src/mage/cards/c/ChandraAwakenedInferno.java
+++ b/Mage.Sets/src/mage/cards/c/ChandraAwakenedInferno.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.PayVariableLoyaltyCost;
@@ -46,7 +46,7 @@ public final class ChandraAwakenedInferno extends CardImpl {
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(6));
// This spell can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// +2: Each opponent gets an emblem with "At the beginning of your upkeep, this emblem deals 1 damage to you."
this.addAbility(new LoyaltyAbility(new ChandraAwakenedInfernoEffect(), 2));
diff --git a/Mage.Sets/src/mage/cards/c/ChandraFlamecaller.java b/Mage.Sets/src/mage/cards/c/ChandraFlamecaller.java
index ce7de428f6a..a4e54c3fd3a 100644
--- a/Mage.Sets/src/mage/cards/c/ChandraFlamecaller.java
+++ b/Mage.Sets/src/mage/cards/c/ChandraFlamecaller.java
@@ -10,7 +10,6 @@ import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DamageAllEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -19,10 +18,9 @@ import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.StaticFilters;
import mage.game.Game;
-import mage.game.permanent.token.ElementalToken;
+import mage.game.permanent.token.ElementalTokenWithHaste;
import mage.players.Player;
-import java.util.Set;
import java.util.UUID;
/**
@@ -77,7 +75,7 @@ class ChandraElementalEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- CreateTokenEffect effect = new CreateTokenEffect(new ElementalToken("OGW", 2, true), 2);
+ CreateTokenEffect effect = new CreateTokenEffect(new ElementalTokenWithHaste(), 2);
effect.apply(game, source);
effect.exileTokensCreatedAtNextEndStep(game, source);
return true;
@@ -106,16 +104,12 @@ class ChandraDrawEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- Set cardsInHand = player.getHand().getCards(game);
- int amount = cardsInHand.size();
- for (Card card : cardsInHand) {
- player.discard(card, source, game);
- }
- player.drawCards(amount + 1, source.getSourceId(), game);
- return true;
+ if (player == null) {
+ return false;
}
- return false;
+ int amount = player.discard(player.getHand(), source, game).size();
+ player.drawCards(amount + 1, source.getSourceId(), game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/c/ChandraFlamesCatalyst.java b/Mage.Sets/src/mage/cards/c/ChandraFlamesCatalyst.java
new file mode 100644
index 00000000000..9c78e245a3e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChandraFlamesCatalyst.java
@@ -0,0 +1,75 @@
+package mage.cards.c;
+
+import mage.ObjectColor;
+import mage.abilities.Ability;
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.effects.CastCardFromGraveyardThenExileItEffect;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.DamagePlayersEffect;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.continuous.CastFromHandWithoutPayingManaCostEffect;
+import mage.abilities.effects.common.discard.DiscardHandControllerEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.ColorPredicate;
+import mage.target.common.TargetCardInYourGraveyard;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class ChandraFlamesCatalyst extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard();
+
+ static {
+ filter.add(new ColorPredicate(ObjectColor.RED));
+ filter.add(Predicates.or(CardType.INSTANT.getPredicate(), CardType.SORCERY.getPredicate()));
+ }
+
+ public ChandraFlamesCatalyst(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{R}{R}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.CHANDRA);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
+
+ // +1: Chandra, Flame's Catalyst deals 3 damage to each opponent.
+ this.addAbility(new LoyaltyAbility(new DamagePlayersEffect(3, TargetController.OPPONENT), 1));
+
+ // −2: You may cast target red instant or sorcery card from your graveyard. If that spell would be put into your graveyard this turn, exile it instead.
+ CastCardFromGraveyardThenExileItEffect minusEffect = new CastCardFromGraveyardThenExileItEffect();
+ minusEffect.setText("You may cast target red instant or sorcery card from your graveyard. If that spell would be put into your graveyard this turn, exile it instead");
+ Ability ability = new LoyaltyAbility(minusEffect, -2);
+ ability.addTarget(new TargetCardInYourGraveyard(filter));
+ this.addAbility(ability);
+
+ // −8: Discard your hand, then draw seven cards. Until end of turn, you may cast spells from your hand without paying their mana costs.
+ Effect discardHandEffect = new DiscardHandControllerEffect();
+ Effect drawEffect = new DrawCardSourceControllerEffect(7);
+ drawEffect.setText(", then draw seven cards");
+ Effect castSpellsFromHandEffect = new CastFromHandWithoutPayingManaCostEffect(
+ StaticFilters.FILTER_CARD_NON_LAND, true, Duration.EndOfTurn);
+ castSpellsFromHandEffect.setText("Until end of turn, you may cast spells from your hand without paying their mana costs");
+ Ability ultimateAbility = new LoyaltyAbility(discardHandEffect, -8);
+ ultimateAbility.addEffect(drawEffect);
+ ultimateAbility.addEffect(castSpellsFromHandEffect);
+ this.addAbility(ultimateAbility);
+ }
+
+ private ChandraFlamesCatalyst(final ChandraFlamesCatalyst card) {
+ super(card);
+ }
+
+ @Override
+ public ChandraFlamesCatalyst copy() {
+ return new ChandraFlamesCatalyst(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/ChandraHeartOfFire.java b/Mage.Sets/src/mage/cards/c/ChandraHeartOfFire.java
new file mode 100644
index 00000000000..169b6fcd4ae
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChandraHeartOfFire.java
@@ -0,0 +1,134 @@
+package mage.cards.c;
+
+import mage.Mana;
+import mage.ObjectColor;
+import mage.abilities.Ability;
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.ExileTop3MayPlayUntilEndOfTurnEffect;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
+import mage.abilities.effects.common.discard.DiscardHandControllerEffect;
+import mage.abilities.effects.mana.BasicManaEffect;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
+import mage.constants.*;
+import mage.filter.FilterCard;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.mageobject.ColorPredicate;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.Target;
+import mage.target.common.TargetAnyTarget;
+import mage.target.common.TargetCardInLibrary;
+import mage.target.common.TargetCardInYourGraveyard;
+import mage.target.targetpointer.FixedTargets;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author htrajan
+ */
+public final class ChandraHeartOfFire extends CardImpl {
+
+ public ChandraHeartOfFire(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}{R}{R}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.CHANDRA);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
+
+ // +1: Discard your hand, then exile the top three cards of your library. Until end of turn, you may play cards exiled this way.
+ Ability ability = new LoyaltyAbility(new DiscardHandControllerEffect(), 1);
+ ability.addEffect(new ExileTop3MayPlayUntilEndOfTurnEffect().concatBy(", then"));
+ this.addAbility(ability);
+
+ // +1: Chandra, Heart of Fire deals 2 damage to any target.
+ Ability damageAbility = new LoyaltyAbility(new DamageTargetEffect(2), 1);
+ damageAbility.addTarget(new TargetAnyTarget());
+ this.addAbility(damageAbility);
+
+ // −9: Search your graveyard and library for any number of red instant and/or sorcery spells, exile them, then shuffle your library. You may cast them this turn. Add six {R}.
+ Ability ultimateAbility = new LoyaltyAbility(new ChandraHeartOfFireUltimateEffect(), -9);
+ ultimateAbility.addEffect(new BasicManaEffect(Mana.RedMana(6)).setText("Add six {R}"));
+ this.addAbility(ultimateAbility);
+ }
+
+ private ChandraHeartOfFire(final ChandraHeartOfFire card) {
+ super(card);
+ }
+
+ @Override
+ public ChandraHeartOfFire copy() {
+ return new ChandraHeartOfFire(this);
+ }
+}
+
+class ChandraHeartOfFireUltimateEffect extends OneShotEffect {
+
+ private static final FilterCard filter = new FilterCard("red instant or sorcery");
+
+ static {
+ filter.add(new ColorPredicate(ObjectColor.RED));
+ filter.add(Predicates.or(CardType.INSTANT.getPredicate(), CardType.SORCERY.getPredicate()));
+ }
+
+ ChandraHeartOfFireUltimateEffect() {
+ super(Outcome.Benefit);
+ staticText = "Search your graveyard and library for any number of red instant and/or sorcery spells, exile them, then shuffle your library. You may cast them this turn";
+ }
+
+ private ChandraHeartOfFireUltimateEffect(ChandraHeartOfFireUltimateEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ChandraHeartOfFireUltimateEffect copy() {
+ return new ChandraHeartOfFireUltimateEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ Set exiledCards = new HashSet<>();
+
+ // from graveyard
+ Target target = new TargetCardInYourGraveyard(0, Integer.MAX_VALUE, filter, true).withChooseHint("from graveyard");
+ if (target.canChoose(source.getSourceId(), controller.getId(), game)
+ && target.choose(Outcome.AIDontUseIt, controller.getId(), source.getSourceId(), game)) {
+ Set cards = new CardsImpl(target.getTargets()).getCards(game);
+ controller.moveCards(cards, Zone.EXILED, source, game);
+ exiledCards.addAll(cards);
+ }
+
+ // from library
+ target = new TargetCardInLibrary(0, Integer.MAX_VALUE, filter).withChooseHint("from library");
+ if (target.canChoose(source.getSourceId(), controller.getId(), game)
+ && target.choose(Outcome.AIDontUseIt, controller.getId(), source.getSourceId(), game)) {
+ Set cards = new CardsImpl(target.getTargets()).getCards(game);
+ controller.moveCards(cards, Zone.EXILED, source, game);
+ exiledCards.addAll(cards);
+ }
+ controller.shuffleLibrary(source, game);
+
+ exiledCards.removeIf(card -> !Zone.EXILED.equals(game.getState().getZone(card.getId())));
+
+ if (!exiledCards.isEmpty()) {
+ ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
+ effect.setTargetPointer(new FixedTargets(exiledCards, game));
+ game.addEffect(effect, source);
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/c/ChandrasFiremaw.java b/Mage.Sets/src/mage/cards/c/ChandrasFiremaw.java
new file mode 100644
index 00000000000..0a87253ad98
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChandrasFiremaw.java
@@ -0,0 +1,49 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect;
+import mage.abilities.keyword.HasteAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterCard;
+import mage.filter.predicate.mageobject.NamePredicate;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ChandrasFiremaw extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard("Chandra, Flame's Catalyst");
+
+ static {
+ filter.add(new NamePredicate("Chandra, Flame's Catalyst"));
+ }
+
+ public ChandrasFiremaw(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}");
+
+ this.subtype.add(SubType.HELLION);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(2);
+
+ // Haste
+ this.addAbility(HasteAbility.getInstance());
+
+ // When Chandra's Firemaw enters the battlefield, you may search your library and/or graveyard for a card named Chandra, Flame's Catalyst, reveal it, and put it into your hand. If you search your library this way, shuffle it.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryGraveyardPutInHandEffect(filter),true));
+ }
+
+ private ChandrasFiremaw(final ChandrasFiremaw card) {
+ super(card);
+ }
+
+ @Override
+ public ChandrasFiremaw copy() {
+ return new ChandrasFiremaw(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/ChandrasIncinerator.java b/Mage.Sets/src/mage/cards/c/ChandrasIncinerator.java
new file mode 100644
index 00000000000..5fd71a51efb
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChandrasIncinerator.java
@@ -0,0 +1,169 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.SpellAbility;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
+import mage.filter.predicate.permanent.ControllerIdPredicate;
+import mage.game.Game;
+import mage.game.events.DamagedPlayerEvent;
+import mage.game.events.GameEvent;
+import mage.target.TargetPermanent;
+import mage.util.CardUtil;
+import mage.watchers.Watcher;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ChandrasIncinerator extends CardImpl {
+
+ public ChandrasIncinerator(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}");
+
+ this.subtype.add(SubType.ELEMENTAL);
+ this.power = new MageInt(6);
+ this.toughness = new MageInt(6);
+
+ // This spell costs {X} less to cast, where X is the total amount of noncombat damage dealt to your opponents this turn.
+ this.addAbility(new SimpleStaticAbility(
+ Zone.ALL, new ChandrasIncineratorCostReductionEffect()
+ ), new ChandrasIncineratorWatcher());
+
+ // Trample
+ this.addAbility(TrampleAbility.getInstance());
+
+ // Whenever a source you control deals noncombat damage to an opponent, Chandra's Incinerator deals that much damage to target creature or planeswalker that player controls.
+ this.addAbility(new ChandrasIncineratorTriggeredAbility());
+ }
+
+ private ChandrasIncinerator(final ChandrasIncinerator card) {
+ super(card);
+ }
+
+ @Override
+ public ChandrasIncinerator copy() {
+ return new ChandrasIncinerator(this);
+ }
+}
+
+class ChandrasIncineratorCostReductionEffect extends CostModificationEffectImpl {
+
+ ChandrasIncineratorCostReductionEffect() {
+ super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
+ staticText = "This spell costs {X} less to cast, where X is the total amount of noncombat damage dealt to your opponents this turn";
+ }
+
+ private ChandrasIncineratorCostReductionEffect(final ChandrasIncineratorCostReductionEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source, Ability abilityToModify) {
+ ChandrasIncineratorWatcher watcher = game.getState().getWatcher(ChandrasIncineratorWatcher.class);
+ if (watcher == null) {
+ return true;
+ }
+ int reductionAmount = watcher.getDamage(source.getControllerId());
+ CardUtil.reduceCost(abilityToModify, Math.max(0, reductionAmount));
+ return true;
+ }
+
+ @Override
+ public boolean applies(Ability abilityToModify, Ability source, Game game) {
+ return abilityToModify instanceof SpellAbility
+ && abilityToModify.getSourceId().equals(source.getSourceId())
+ && game.getCard(abilityToModify.getSourceId()) != null;
+ }
+
+ @Override
+ public ChandrasIncineratorCostReductionEffect copy() {
+ return new ChandrasIncineratorCostReductionEffect(this);
+ }
+}
+
+class ChandrasIncineratorWatcher extends Watcher {
+
+ private final Map damageMap = new HashMap<>();
+
+ ChandrasIncineratorWatcher() {
+ super(WatcherScope.GAME);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() != GameEvent.EventType.DAMAGED_PLAYER
+ || ((DamagedPlayerEvent) event).isCombatDamage()) {
+ return;
+ }
+ for (UUID playerId : game.getOpponents(event.getTargetId())) {
+ damageMap.compute(playerId, ((u, i) -> i == null ? event.getAmount() : Integer.sum(i, event.getAmount())));
+ }
+ }
+
+ @Override
+ public void reset() {
+ damageMap.clear();
+ super.reset();
+ }
+
+ int getDamage(UUID playerId) {
+ return damageMap.getOrDefault(playerId, 0);
+ }
+}
+
+class ChandrasIncineratorTriggeredAbility extends TriggeredAbilityImpl {
+
+ ChandrasIncineratorTriggeredAbility() {
+ super(Zone.BATTLEFIELD, null);
+ }
+
+ private ChandrasIncineratorTriggeredAbility(final ChandrasIncineratorTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event;
+ if (dEvent.isCombatDamage()
+ || !game.getOpponents(event.getTargetId()).contains(getControllerId())
+ || !game.getControllerId(event.getSourceId()).equals(getControllerId())) {
+ return false;
+ }
+ this.getEffects().clear();
+ this.addEffect(new DamageTargetEffect(event.getAmount()));
+ FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker");
+ filter.add(new ControllerIdPredicate(event.getTargetId()));
+ this.getTargets().clear();
+ this.addTarget(new TargetPermanent(filter));
+ return true;
+ }
+
+ @Override
+ public ChandrasIncineratorTriggeredAbility copy() {
+ return new ChandrasIncineratorTriggeredAbility(this);
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever a source you control deals noncombat damage to an opponent, " +
+ "{this} deals that much damage to target creature or planeswalker that player controls.";
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/ChandrasMagmutt.java b/Mage.Sets/src/mage/cards/c/ChandrasMagmutt.java
new file mode 100644
index 00000000000..e4e617c127b
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChandrasMagmutt.java
@@ -0,0 +1,43 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.target.common.TargetPlayerOrPlaneswalker;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ChandrasMagmutt extends CardImpl {
+
+ public ChandrasMagmutt(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
+
+ this.subtype.add(SubType.ELEMENTAL);
+ this.subtype.add(SubType.DOG);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // {T}: Chandra's Magmutt deals 1 damage to target player or planeswalker.
+ Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost());
+ ability.addTarget(new TargetPlayerOrPlaneswalker());
+ this.addAbility(ability);
+ }
+
+ private ChandrasMagmutt(final ChandrasMagmutt card) {
+ super(card);
+ }
+
+ @Override
+ public ChandrasMagmutt copy() {
+ return new ChandrasMagmutt(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/ChandrasPhoenix.java b/Mage.Sets/src/mage/cards/c/ChandrasPhoenix.java
index af3ba402a72..5efc3043906 100644
--- a/Mage.Sets/src/mage/cards/c/ChandrasPhoenix.java
+++ b/Mage.Sets/src/mage/cards/c/ChandrasPhoenix.java
@@ -1,4 +1,3 @@
-
package mage.cards.c;
import java.util.UUID;
@@ -8,6 +7,7 @@ import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility;
+import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -26,7 +26,7 @@ import mage.game.stack.StackObject;
public final class ChandrasPhoenix extends CardImpl {
public ChandrasPhoenix(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}");
this.subtype.add(SubType.PHOENIX);
this.power = new MageInt(2);
@@ -34,9 +34,13 @@ public final class ChandrasPhoenix extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
+
// Haste (This creature can attack and as soon as it comes under your control.)
this.addAbility(HasteAbility.getInstance());
- // Whenever an opponent is dealt damage by a red instant or sorcery spell you control or by a red planeswalker you control, return Chandra's Phoenix from your graveyard to your hand.
+
+ // Whenever an opponent is dealt damage by a red instant or sorcery spell
+ // you control or by a red planeswalker you control, return Chandra's
+ // Phoenix from your graveyard to your hand.
this.addAbility(new ChandrasPhoenixTriggeredAbility());
}
@@ -72,7 +76,9 @@ class ChandrasPhoenixTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- if (game.getOpponents(this.controllerId).contains(event.getPlayerId())) {
+ Card chandrasPhoenix = game.getCard(this.getSourceId());
+ if (chandrasPhoenix != null
+ && game.getOpponents(chandrasPhoenix.getOwnerId()).contains(event.getPlayerId())) {
StackObject stackObject = game.getStack().getStackObject(event.getSourceId());
if (stackObject != null) {
MageObject sourceObjectDamage;
@@ -96,6 +102,7 @@ class ChandrasPhoenixTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever an opponent is dealt damage by a red instant or sorcery spell you control or by a red planeswalker you control, return {this} from your graveyard to your hand.";
+ return "Whenever an opponent is dealt damage by a red instant or sorcery spell "
+ + "you control or by a red planeswalker you control, return {this} from your graveyard to your hand.";
}
}
diff --git a/Mage.Sets/src/mage/cards/c/ChandrasPyreling.java b/Mage.Sets/src/mage/cards/c/ChandrasPyreling.java
new file mode 100644
index 00000000000..bca970e2a67
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChandrasPyreling.java
@@ -0,0 +1,82 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.DoubleStrikeAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.DamagedPlayerEvent;
+import mage.game.events.GameEvent;
+import mage.game.events.GameEvent.EventType;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * @author htrajan
+ */
+public final class ChandrasPyreling extends CardImpl {
+
+ public ChandrasPyreling(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
+
+ this.subtype.add(SubType.ELEMENTAL);
+ this.subtype.add(SubType.LIZARD);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(3);
+
+ // Whenever a source you control deals noncombat damage to an opponent, Chandra's Pyreling gets +1/+0 and gains double strike until end of turn.
+ this.addAbility(new ChandrasPyrelingAbility());
+ }
+
+ private ChandrasPyreling(final ChandrasPyreling card) {
+ super(card);
+ }
+
+ @Override
+ public ChandrasPyreling copy() {
+ return new ChandrasPyreling(this);
+ }
+}
+
+class ChandrasPyrelingAbility extends TriggeredAbilityImpl {
+
+ ChandrasPyrelingAbility() {
+ super(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn));
+ addEffect(new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn));
+ }
+
+ private ChandrasPyrelingAbility(final ChandrasPyrelingAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public ChandrasPyrelingAbility copy() {
+ return new ChandrasPyrelingAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.DAMAGED_PLAYER;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event;
+ return !damageEvent.isCombatDamage()
+ && game.getOpponents(controllerId).contains(event.getTargetId())
+ && Objects.equals(controllerId, game.getControllerId(event.getSourceId()));
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever a source you control deals noncombat damage to an opponent, {source} gets +1/+0 and gains double strike until end of turn.";
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/c/ChandrasRegulator.java b/Mage.Sets/src/mage/cards/c/ChandrasRegulator.java
index 29a5a4b730b..53010c2af07 100644
--- a/Mage.Sets/src/mage/cards/c/ChandrasRegulator.java
+++ b/Mage.Sets/src/mage/cards/c/ChandrasRegulator.java
@@ -2,14 +2,12 @@ package mage.cards.c;
import mage.ObjectColor;
import mage.abilities.Ability;
-import mage.abilities.LoyaltyAbility;
-import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.ActivatePlaneswalkerLoyaltyAbilityTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
@@ -19,7 +17,6 @@ import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.players.Player;
@@ -47,7 +44,7 @@ public final class ChandrasRegulator extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
// Whenever you activate a loyalty ability of a Chandra planeswalker, you may pay {1}. If you do, copy that ability. You may choose new targets for the copy.
- this.addAbility(new ChandrasRegulatorTriggeredAbility());
+ this.addAbility(new ActivatePlaneswalkerLoyaltyAbilityTriggeredAbility(new ChandrasRegulatorEffect(), SubType.CHANDRA));
// {1}, {T}, Discard a Mountain card or a red card: Draw a card.
Ability ability = new SimpleActivatedAbility(
@@ -68,56 +65,11 @@ public final class ChandrasRegulator extends CardImpl {
}
}
-class ChandrasRegulatorTriggeredAbility extends TriggeredAbilityImpl {
-
- ChandrasRegulatorTriggeredAbility() {
- super(Zone.BATTLEFIELD, new ChandrasRegulatorEffect(), false);
- }
-
- private ChandrasRegulatorTriggeredAbility(final ChandrasRegulatorTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public ChandrasRegulatorTriggeredAbility copy() {
- return new ChandrasRegulatorTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- if (!event.getPlayerId().equals(getControllerId())) {
- return false;
- }
- StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
- if (stackAbility == null || !(stackAbility.getStackAbility() instanceof LoyaltyAbility)) {
- return false;
- }
- Permanent permanent = stackAbility.getSourcePermanentOrLKI(game);
- if (permanent == null || !permanent.isPlaneswalker()
- || !permanent.hasSubtype(SubType.CHANDRA, game)) {
- return false;
- }
- Effect effect = this.getEffects().get(0);
- effect.setValue("stackAbility", stackAbility);
- return true;
- }
-
- @Override
- public String getRule() {
- return "Whenever you activate a loyalty ability of a Chandra planeswalker, you may pay {1}. " +
- "If you do, copy that ability. You may choose new targets for the copy.";
- }
-}
-
class ChandrasRegulatorEffect extends OneShotEffect {
ChandrasRegulatorEffect() {
super(Outcome.Benefit);
+ staticText = "you may pay {1}. If you do, copy that ability. You may choose new targets for the copy";
}
private ChandrasRegulatorEffect(final ChandrasRegulatorEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/c/Chaosphere.java b/Mage.Sets/src/mage/cards/c/Chaosphere.java
index 12511380fc7..73ed95605d7 100644
--- a/Mage.Sets/src/mage/cards/c/Chaosphere.java
+++ b/Mage.Sets/src/mage/cards/c/Chaosphere.java
@@ -82,7 +82,7 @@ class ChaosphereEffect extends RestrictionEffect {
if (attacker == null) {
return true;
}
- return attacker.hasAbility(FlyingAbility.getInstance().getId(), game);
+ return attacker.hasAbility(FlyingAbility.getInstance(), game);
}
@Override
diff --git a/Mage.Sets/src/mage/cards/c/ChargeOfTheForeverBeast.java b/Mage.Sets/src/mage/cards/c/ChargeOfTheForeverBeast.java
index 2ef93a847fe..6e878e63de3 100644
--- a/Mage.Sets/src/mage/cards/c/ChargeOfTheForeverBeast.java
+++ b/Mage.Sets/src/mage/cards/c/ChargeOfTheForeverBeast.java
@@ -26,7 +26,7 @@ public final class ChargeOfTheForeverBeast extends CardImpl {
// As an additional cost to cast this spell, reveal a creature card from your hand.
this.getSpellAbility().addCost(new RevealTargetFromHandCost(
- new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE_A)
+ new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE_YOUR_HAND)
));
// Charge of the Forever-Beast deals damage to target creature or planeswalker equal to the revealed card's power.
@@ -64,7 +64,7 @@ class ChargeOfTheForeverBeastEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
RevealTargetFromHandCost cost = (RevealTargetFromHandCost) source.getCosts().get(0);
- if (permanent == null && cost == null) {
+ if (permanent == null || cost == null) {
return false;
}
Card card = cost.getRevealedCards().get(0);
diff --git a/Mage.Sets/src/mage/cards/c/Charisma.java b/Mage.Sets/src/mage/cards/c/Charisma.java
index c2fe9091bcc..235ab9e8641 100644
--- a/Mage.Sets/src/mage/cards/c/Charisma.java
+++ b/Mage.Sets/src/mage/cards/c/Charisma.java
@@ -6,6 +6,7 @@ import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToACreatureAttachedTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.SourceOnBattlefieldCondition;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
@@ -16,6 +17,7 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.Zone;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
@@ -40,8 +42,8 @@ public final class Charisma extends CardImpl {
this.addAbility(ability);
// Whenever enchanted creature deals damage to a creature, gain control of the other creature for as long as Charisma remains on the battlefield.
- Condition condition = SourceOnBattlefieldCondition.instance;
- ConditionalContinuousEffect conditionalEffect = new ConditionalContinuousEffect(new GainControlTargetEffect(Duration.Custom), condition, rule);
+ ConditionalContinuousEffect conditionalEffect = new ConditionalContinuousEffect(new GainControlTargetEffect(Duration.Custom),
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD), rule);
this.addAbility(new DealsDamageToACreatureAttachedTriggeredAbility(conditionalEffect, false, "enchanted creature", false, true));
}
diff --git a/Mage.Sets/src/mage/cards/c/ChasmSkulker.java b/Mage.Sets/src/mage/cards/c/ChasmSkulker.java
index 880546b17ce..8a86c45285a 100644
--- a/Mage.Sets/src/mage/cards/c/ChasmSkulker.java
+++ b/Mage.Sets/src/mage/cards/c/ChasmSkulker.java
@@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.DrawCardControllerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -39,7 +39,7 @@ public final class ChasmSkulker extends CardImpl {
this.addAbility(new DrawCardControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false));
// When Chasm Skulker dies, create X 1/1 blue Squid creature tokens with islandwalk, where X is the number of +1/+1 counters on Chasm Skulker.
- this.addAbility(new DiesTriggeredAbility(new ChasmSkulkerEffect(), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new ChasmSkulkerEffect(), false));
}
public ChasmSkulker(final ChasmSkulker card) {
diff --git a/Mage.Sets/src/mage/cards/c/CherishedHatchling.java b/Mage.Sets/src/mage/cards/c/CherishedHatchling.java
index 81c972d53f3..f8c3c4835eb 100644
--- a/Mage.Sets/src/mage/cards/c/CherishedHatchling.java
+++ b/Mage.Sets/src/mage/cards/c/CherishedHatchling.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -45,7 +45,7 @@ public final class CherishedHatchling extends CardImpl {
this.toughness = new MageInt(1);
// When Cherished Hatchling dies, you may cast Dinosaur spells this turn as though they had flash, and whenever you cast a Dinosaur spell this turn, it gains "When this creature enters the battlefield, you may have it fight another target creature."
- Ability ability = new DiesTriggeredAbility(new CastAsThoughItHadFlashAllEffect(Duration.EndOfTurn, filterCard, false));
+ Ability ability = new DiesSourceTriggeredAbility(new CastAsThoughItHadFlashAllEffect(Duration.EndOfTurn, filterCard, false));
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new CherishedHatchlingTriggeredAbility()));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/c/ChildOfAlara.java b/Mage.Sets/src/mage/cards/c/ChildOfAlara.java
index d980f243a19..f739ddb60f3 100644
--- a/Mage.Sets/src/mage/cards/c/ChildOfAlara.java
+++ b/Mage.Sets/src/mage/cards/c/ChildOfAlara.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
@@ -31,7 +31,7 @@ public final class ChildOfAlara extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// When Child of Alara dies, destroy all nonland permanents. They can't be regenerated.
- this.addAbility(new DiesTriggeredAbility(new DestroyAllEffect(new FilterNonlandPermanent("nonland permanents"), true)));
+ this.addAbility(new DiesSourceTriggeredAbility(new DestroyAllEffect(new FilterNonlandPermanent("nonland permanents"), true)));
}
diff --git a/Mage.Sets/src/mage/cards/c/Chill.java b/Mage.Sets/src/mage/cards/c/Chill.java
index 557a0a2a476..083999cc7c5 100644
--- a/Mage.Sets/src/mage/cards/c/Chill.java
+++ b/Mage.Sets/src/mage/cards/c/Chill.java
@@ -1,33 +1,34 @@
-
package mage.cards.c;
-import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author Quercitron
*/
public final class Chill extends CardImpl {
private static final FilterCard filter = new FilterCard("Red spells");
+
static {
filter.add(new ColorPredicate(ObjectColor.RED));
}
public Chill(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}");
// Red spells cost {2} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasementAllEffect(filter, 2)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(2, filter, TargetController.ANY)));
}
public Chill(final Chill card) {
diff --git a/Mage.Sets/src/mage/cards/c/ChillOfForeboding.java b/Mage.Sets/src/mage/cards/c/ChillOfForeboding.java
index 5f7d4323eb7..98f9bbc67d2 100644
--- a/Mage.Sets/src/mage/cards/c/ChillOfForeboding.java
+++ b/Mage.Sets/src/mage/cards/c/ChillOfForeboding.java
@@ -1,36 +1,32 @@
-
package mage.cards.c;
-import java.util.UUID;
-import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.constants.TimingRule;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.players.Player;
+
+import java.util.UUID;
/**
- *
* @author North
*/
public final class ChillOfForeboding extends CardImpl {
public ChillOfForeboding(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}");
// Each player puts the top five cards of their library into their graveyard.
- this.getSpellAbility().addEffect(new ChillOfForebodingEffect());
+ this.getSpellAbility().addEffect(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(5, TargetController.ANY));
+
// Flashback {7}{U}
this.addAbility(new FlashbackAbility(new ManaCostsImpl("{7}{U}"), TimingRule.SORCERY));
}
- public ChillOfForeboding(final ChillOfForeboding card) {
+ private ChillOfForeboding(final ChillOfForeboding card) {
super(card);
}
@@ -39,32 +35,3 @@ public final class ChillOfForeboding extends CardImpl {
return new ChillOfForeboding(this);
}
}
-
-class ChillOfForebodingEffect extends OneShotEffect {
-
- public ChillOfForebodingEffect() {
- super(Outcome.Detriment);
- this.staticText = "Each player puts the top five cards of their library into their graveyard";
- }
-
- public ChillOfForebodingEffect(final ChillOfForebodingEffect effect) {
- super(effect);
- }
-
- @Override
- public ChillOfForebodingEffect copy() {
- return new ChillOfForebodingEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player sourcePlayer = game.getPlayer(source.getControllerId());
- for (UUID playerId : game.getState().getPlayersInRange(sourcePlayer.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, 5), Zone.GRAVEYARD, source, game);
- }
- }
- return true;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/c/ChimneyImp.java b/Mage.Sets/src/mage/cards/c/ChimneyImp.java
index 6e9489b290b..455b303dda8 100644
--- a/Mage.Sets/src/mage/cards/c/ChimneyImp.java
+++ b/Mage.Sets/src/mage/cards/c/ChimneyImp.java
@@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
@@ -35,7 +35,7 @@ public final class ChimneyImp extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Chimney Imp dies, target opponent puts a card from their hand on top of their library.
- Ability ability = new DiesTriggeredAbility(new ChimneyImpEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new ChimneyImpEffect(), false);
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/c/ChokingVines.java b/Mage.Sets/src/mage/cards/c/ChokingVines.java
new file mode 100644
index 00000000000..3dce3af1475
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChokingVines.java
@@ -0,0 +1,105 @@
+package mage.cards.c;
+
+import java.util.UUID;
+
+import mage.abilities.Ability;
+import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.PhaseStep;
+import mage.game.Game;
+import mage.game.combat.CombatGroup;
+import mage.players.Player;
+import mage.target.Target;
+import mage.target.Targets;
+import mage.target.common.TargetCreaturePermanent;
+import mage.target.targetadjustment.TargetAdjuster;
+
+import static mage.filter.StaticFilters.FILTER_ATTACKING_CREATURES;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+
+/**
+ * @author arcox
+ */
+public final class ChokingVines extends CardImpl {
+
+ public ChokingVines(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{G}");
+
+ // Cast only during the declare blockers step.
+ this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null,
+ PhaseStep.DECLARE_BLOCKERS, null, "Cast this spell only during the declare blockers step"));
+
+ // X target attacking creatures become blocked. Choking Vines deals 1 damage to each of those creatures.
+ this.getSpellAbility().addEffect(new ChokingVinesEffect());
+ this.getSpellAbility().addEffect(new DamageTargetEffect(1)
+ .setText("{this} deals 1 damage to each of those creatures"));
+ this.getSpellAbility().setTargetAdjuster(ChokingVinesAdjuster.instance);
+ }
+
+ public ChokingVines(final ChokingVines card) {
+ super(card);
+ }
+
+ @Override
+ public ChokingVines copy() {
+ return new ChokingVines(this);
+ }
+}
+
+enum ChokingVinesAdjuster implements TargetAdjuster {
+ instance;
+
+ @Override
+ public void adjustTargets(Ability ability, Game game) {
+ ability.getTargets().clear();
+ int x = ability.getManaCostsToPay().getX();
+ ability.addTarget(new TargetCreaturePermanent(x, x, FILTER_ATTACKING_CREATURES, false));
+ }
+}
+
+class ChokingVinesEffect extends OneShotEffect {
+
+ public ChokingVinesEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "X target attacking creatures become blocked";
+ }
+
+ public ChokingVinesEffect(final ChokingVinesEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ChokingVinesEffect copy() {
+ return new ChokingVinesEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ Targets targets = source.getTargets();
+
+ if (controller != null && !targets.isEmpty()) {
+ for (Target target : targets) {
+ for (UUID id : target.getTargets()) {
+ CombatGroup combatGroup = game.getCombat().findGroup(id);
+ if (combatGroup != null) {
+ combatGroup.setBlocked(true); // non-banded creatures
+ combatGroup.setBlocked(true, game); // this only works for banded creatures and needs to be checked out
+ Permanent attacker = game.getPermanent(id);
+ if (attacker != null) {
+ game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, attacker.getId(), null));
+ }
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/ChromaticOrrery.java b/Mage.Sets/src/mage/cards/c/ChromaticOrrery.java
new file mode 100644
index 00000000000..d69cbdcdff6
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChromaticOrrery.java
@@ -0,0 +1,84 @@
+package mage.cards.c;
+
+import mage.Mana;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.AsThoughEffectImpl;
+import mage.abilities.effects.AsThoughManaEffect;
+import mage.abilities.effects.common.DrawCardForEachColorAmongControlledPermanentsEffect;
+import mage.abilities.mana.SimpleManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.game.Game;
+import mage.players.ManaPoolItem;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class ChromaticOrrery extends CardImpl {
+
+ public ChromaticOrrery(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{7}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+
+ // You may spend mana as though it were mana of any color.
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ChromaticOrreryEffect()));
+
+ // {T}: Add {C}{C}{C}{C}{C}.
+ this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.ColorlessMana(5), new TapSourceCost()));
+
+ // {5}, {T}: Draw a card for each color among permanents you control.
+ Ability ability = new SimpleActivatedAbility(new DrawCardForEachColorAmongControlledPermanentsEffect(), new GenericManaCost(5));
+ ability.addCost(new TapSourceCost());
+ this.addAbility(ability);
+ }
+
+ private ChromaticOrrery(final ChromaticOrrery card) {
+ super(card);
+ }
+
+ @Override
+ public ChromaticOrrery copy() {
+ return new ChromaticOrrery(this);
+ }
+}
+
+class ChromaticOrreryEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
+
+ ChromaticOrreryEffect() {
+ super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.WhileOnBattlefield, Outcome.Benefit);
+ staticText = "You may spend mana as though it were mana of any color";
+ }
+
+ private ChromaticOrreryEffect(ChromaticOrreryEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ChromaticOrreryEffect copy() {
+ return new ChromaticOrreryEffect(this);
+ }
+
+ @Override
+ public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
+ return true;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
+ return mana.getFirstAvailable();
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/c/ChromeReplicator.java b/Mage.Sets/src/mage/cards/c/ChromeReplicator.java
new file mode 100644
index 00000000000..712eef718e0
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ChromeReplicator.java
@@ -0,0 +1,80 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.permanent.TokenPredicate;
+import mage.game.Game;
+import mage.game.permanent.token.RetrofitterFoundryToken;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ChromeReplicator extends CardImpl {
+
+ public ChromeReplicator(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}");
+
+ this.subtype.add(SubType.CONSTRUCT);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(4);
+
+ // When Chrome Replicator enters the battlefield, if you control two or more nonland, nontoken permanents with the same name as one another, create a 4/4 colorless Construct artifact creature token.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new RetrofitterFoundryToken())),
+ ChromeReplicatorCondition.instance, "When {this} enters the battlefield, " +
+ "if you control two or more nonland, nontoken permanents with the same name as one another, " +
+ "create a 4/4 colorless Construct artifact creature token."
+ ));
+ }
+
+ private ChromeReplicator(final ChromeReplicator card) {
+ super(card);
+ }
+
+ @Override
+ public ChromeReplicator copy() {
+ return new ChromeReplicator(this);
+ }
+}
+
+enum ChromeReplicatorCondition implements Condition {
+ instance;
+ private static final FilterPermanent filter = new FilterControlledPermanent();
+
+ static {
+ filter.add(Predicates.not(CardType.LAND.getPredicate()));
+ filter.add(Predicates.not(TokenPredicate.instance));
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Map nameMap = new HashMap<>();
+ return game
+ .getBattlefield()
+ .getActivePermanents(
+ filter, source.getControllerId(), source.getSourceId(), game
+ ).stream()
+ .filter(Objects::nonNull)
+ .map(MageObject::getName)
+ .filter(Objects::nonNull)
+ .filter(s -> !"".equals(s))
+ .anyMatch(s -> nameMap.compute(s, (x, i) -> i == null ? 1 : Integer.sum(i, 1)) >= 2);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/ChromiumTheMutable.java b/Mage.Sets/src/mage/cards/c/ChromiumTheMutable.java
index 61909703f3f..826d556786e 100644
--- a/Mage.Sets/src/mage/cards/c/ChromiumTheMutable.java
+++ b/Mage.Sets/src/mage/cards/c/ChromiumTheMutable.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect;
@@ -38,7 +38,7 @@ public final class ChromiumTheMutable extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// This spell can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Flying
this.addAbility(FlyingAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/c/ChronicFlooding.java b/Mage.Sets/src/mage/cards/c/ChronicFlooding.java
index 62f452388d3..131327bd244 100644
--- a/Mage.Sets/src/mage/cards/c/ChronicFlooding.java
+++ b/Mage.Sets/src/mage/cards/c/ChronicFlooding.java
@@ -91,6 +91,6 @@ class ChronicFloodingAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever enchanted land becomes tapped, its controller puts the top three cards of their library into their graveyard.";
+ return "Whenever enchanted land becomes tapped, its controller mills three cards.";
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/c/Chronozoa.java b/Mage.Sets/src/mage/cards/c/Chronozoa.java
index 81a6153913c..2ade15a2fea 100644
--- a/Mage.Sets/src/mage/cards/c/Chronozoa.java
+++ b/Mage.Sets/src/mage/cards/c/Chronozoa.java
@@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.condition.common.LastTimeCounterRemovedCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
@@ -46,7 +46,7 @@ public final class Chronozoa extends CardImpl {
// When Chronozoa is put into a graveyard from play, if it had no time counters on it, create two tokens that are copies of it.
Effect effect = new CreateTokenCopySourceEffect(2);
effect.setText("create two tokens that are copies of it");
- this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesTriggeredAbility(effect, false),
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesSourceTriggeredAbility(effect, false),
LastTimeCounterRemovedCondition.instance,
"When {this} dies, if it had no time counters on it, create two tokens that are copies of it."));
}
diff --git a/Mage.Sets/src/mage/cards/c/ChubToad.java b/Mage.Sets/src/mage/cards/c/ChubToad.java
index 8cc95ab1556..ab57c1310b9 100644
--- a/Mage.Sets/src/mage/cards/c/ChubToad.java
+++ b/Mage.Sets/src/mage/cards/c/ChubToad.java
@@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class ChubToad extends CardImpl {
// Whenever Chub Toad blocks or becomes blocked, it gets +2/+2 until end of turn.
Effect effect = new BoostSourceEffect(+2, +2, Duration.EndOfTurn);
effect.setText("it gets +2/+2 until end of turn");
- Ability ability = new BlocksOrBecomesBlockedTriggeredAbility(effect, false);
+ Ability ability = new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, false);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/c/CinderCloud.java b/Mage.Sets/src/mage/cards/c/CinderCloud.java
index 95a401befd3..a2208fc8ade 100644
--- a/Mage.Sets/src/mage/cards/c/CinderCloud.java
+++ b/Mage.Sets/src/mage/cards/c/CinderCloud.java
@@ -59,7 +59,7 @@ class CinderCloudEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null && permanent.destroy(source.getSourceId(), game, false) && permanent.getColor(game).equals(ObjectColor.WHITE)) {
- game.applyEffects();
+ game.getState().processAction(game);
if (permanent.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(permanent.getId())
&& game.getState().getZone(permanent.getId()) != Zone.GRAVEYARD) {
// A replacement effect has moved the card to another zone as grvayard
diff --git a/Mage.Sets/src/mage/cards/c/CitywatchSphinx.java b/Mage.Sets/src/mage/cards/c/CitywatchSphinx.java
index 3bfe96bc8db..0fe4108f9aa 100644
--- a/Mage.Sets/src/mage/cards/c/CitywatchSphinx.java
+++ b/Mage.Sets/src/mage/cards/c/CitywatchSphinx.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.keyword.SurveilEffect;
import mage.constants.SubType;
import mage.abilities.keyword.FlyingAbility;
@@ -27,7 +27,7 @@ public final class CitywatchSphinx extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Citywatch Sphinx dies, surveil 2.
- this.addAbility(new DiesTriggeredAbility(new SurveilEffect(2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new SurveilEffect(2)));
}
public CitywatchSphinx(final CitywatchSphinx card) {
diff --git a/Mage.Sets/src/mage/cards/c/CloneShell.java b/Mage.Sets/src/mage/cards/c/CloneShell.java
index 84171a085bd..7ce9a397b9b 100644
--- a/Mage.Sets/src/mage/cards/c/CloneShell.java
+++ b/Mage.Sets/src/mage/cards/c/CloneShell.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
@@ -36,7 +36,7 @@ public final class CloneShell extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new CloneShellEffect(), false));
// When Clone Shell dies, turn the exiled card face up. If it's a creature card, put it onto the battlefield under your control.
- this.addAbility(new DiesTriggeredAbility(new CloneShellDiesEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new CloneShellDiesEffect()));
}
public CloneShell(final CloneShell card) {
diff --git a/Mage.Sets/src/mage/cards/c/ClotSliver.java b/Mage.Sets/src/mage/cards/c/ClotSliver.java
index e7bd0f90394..d3ba912fbbf 100644
--- a/Mage.Sets/src/mage/cards/c/ClotSliver.java
+++ b/Mage.Sets/src/mage/cards/c/ClotSliver.java
@@ -1,7 +1,6 @@
package mage.cards.c;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
@@ -16,6 +15,8 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
+import java.util.UUID;
+
/**
* @author Loki
*/
@@ -33,7 +34,7 @@ public final class ClotSliver extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new GenericManaCost(2)), Duration.WhileOnBattlefield, filter, false)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect("this permanent"), new GenericManaCost(2)), Duration.WhileOnBattlefield, filter, false)));
}
public ClotSliver(final ClotSliver card) {
diff --git a/Mage.Sets/src/mage/cards/c/CloudKey.java b/Mage.Sets/src/mage/cards/c/CloudKey.java
index 5a9bd8158e1..78d18090cfa 100644
--- a/Mage.Sets/src/mage/cards/c/CloudKey.java
+++ b/Mage.Sets/src/mage/cards/c/CloudKey.java
@@ -98,7 +98,7 @@ class CloudKeyCostModificationEffect extends CostModificationEffectImpl {
public CloudKeyCostModificationEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
- this.staticText = "Spells you cast of the chosen type cost {1} less to cast.";
+ this.staticText = "Spells you cast of the chosen type cost {1} less to cast";
}
public CloudKeyCostModificationEffect(final CloudKeyCostModificationEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/c/CloudhoofKirin.java b/Mage.Sets/src/mage/cards/c/CloudhoofKirin.java
index c0fc199a8c7..ea015a23d3c 100644
--- a/Mage.Sets/src/mage/cards/c/CloudhoofKirin.java
+++ b/Mage.Sets/src/mage/cards/c/CloudhoofKirin.java
@@ -1,7 +1,6 @@
package mage.cards.c;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
@@ -9,11 +8,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Outcome;
-import mage.constants.SuperType;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.stack.Spell;
@@ -21,8 +16,9 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPlayer;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class CloudhoofKirin extends CardImpl {
@@ -44,7 +40,7 @@ public final class CloudhoofKirin extends CardImpl {
this.addAbility(ability);
}
- public CloudhoofKirin(final CloudhoofKirin card) {
+ private CloudhoofKirin(final CloudhoofKirin card) {
super(card);
}
@@ -56,12 +52,12 @@ public final class CloudhoofKirin extends CardImpl {
class CloudhoofKirinEffect extends OneShotEffect {
- public CloudhoofKirinEffect() {
+ CloudhoofKirinEffect() {
super(Outcome.Detriment);
- this.staticText = "you may have target player put the top X cards of their library into their graveyard, where X is that spell's converted mana cost";
+ this.staticText = "have target player mill X cards, where X is that spell's converted mana cost";
}
- public CloudhoofKirinEffect(final CloudhoofKirinEffect effect) {
+ private CloudhoofKirinEffect(final CloudhoofKirinEffect effect) {
super(effect);
}
@@ -80,8 +76,10 @@ class CloudhoofKirinEffect extends OneShotEffect {
targetPlayer = game.getPlayer(target.getFirstTarget());
}
}
- if (targetPlayer != null) {
- return targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, spell.getConvertedManaCost()), Zone.GRAVEYARD, source, game);
+ int cmc = spell.getConvertedManaCost();
+ if (targetPlayer != null && cmc > 0) {
+ targetPlayer.millCards(cmc, source, game);
+ return true;
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/c/CoalStoker.java b/Mage.Sets/src/mage/cards/c/CoalStoker.java
index 17ead83cd53..26787c90d66 100644
--- a/Mage.Sets/src/mage/cards/c/CoalStoker.java
+++ b/Mage.Sets/src/mage/cards/c/CoalStoker.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.Mana;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.cards.CardImpl;
@@ -29,7 +29,7 @@ public final class CoalStoker extends CardImpl {
// When Coal Stoker enters the battlefield, if you cast it from your hand, add {R}{R}{R}.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new BasicManaEffect(Mana.RedMana(3)), false),
- CastFromHandSourceCondition.instance,
+ CastFromHandSourcePermanentCondition.instance,
"When {this} enters the battlefield, if you cast it from your hand, add {R}{R}{R}."),
new CastFromHandWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/c/Cockatrice.java b/Mage.Sets/src/mage/cards/c/Cockatrice.java
index cd45ae14a3b..d8cf0bb72d2 100644
--- a/Mage.Sets/src/mage/cards/c/Cockatrice.java
+++ b/Mage.Sets/src/mage/cards/c/Cockatrice.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -41,7 +41,7 @@ public final class Cockatrice extends CardImpl {
// Whenever Cockatrice blocks or becomes blocked by a non-Wall creature, destroy that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true);
effect.setText("destroy that creature at end of combat");
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, filter, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, filter, false));
}
public Cockatrice(final Cockatrice card) {
diff --git a/Mage.Sets/src/mage/cards/c/CoercedConfession.java b/Mage.Sets/src/mage/cards/c/CoercedConfession.java
index 128ddb264f7..db453582136 100644
--- a/Mage.Sets/src/mage/cards/c/CoercedConfession.java
+++ b/Mage.Sets/src/mage/cards/c/CoercedConfession.java
@@ -1,10 +1,10 @@
-
package mage.cards.c;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.*;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -12,22 +12,23 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class CoercedConfession extends CardImpl {
public CoercedConfession(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{U/B}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U/B}");
// Target player puts the top four cards of their library into their graveyard. You draw a card for each creature card put into a graveyard this way.
getSpellAbility().addEffect(new CoercedConfessionMillEffect());
getSpellAbility().addTarget(new TargetPlayer());
}
- public CoercedConfession(final CoercedConfession card) {
+ private CoercedConfession(final CoercedConfession card) {
super(card);
}
@@ -39,12 +40,12 @@ public final class CoercedConfession extends CardImpl {
class CoercedConfessionMillEffect extends OneShotEffect {
- public CoercedConfessionMillEffect() {
+ CoercedConfessionMillEffect() {
super(Outcome.DrawCard);
- this.staticText = "Target player puts the top four cards of their library into their graveyard. You draw a card for each creature card put into a graveyard this way";
+ this.staticText = "Target player mills four cards. You draw a card for each creature card put into their graveyard this way";
}
- public CoercedConfessionMillEffect(final CoercedConfessionMillEffect effect) {
+ private CoercedConfessionMillEffect(final CoercedConfessionMillEffect effect) {
super(effect);
}
@@ -56,24 +57,26 @@ class CoercedConfessionMillEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
- if (player != null) {
- int foundCreatures = 0;
- Cards cards = new CardsImpl();
- for(Card card: player.getLibrary().getTopCards(game, 4)) {
- cards.add(card);
- if (card.isCreature()) {
- ++foundCreatures;
- }
- }
- player.moveCards(cards, Zone.GRAVEYARD, source, game);
- if (foundCreatures > 0) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- controller.drawCards(foundCreatures, source.getSourceId(), game);
- }
- }
+ if (player == null) {
+ return false;
+ }
+ int creaturesMilled = player
+ .millCards(4, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(card -> game.getState().getZone(card.getId()) == Zone.GRAVEYARD)
+ .filter(MageObject::isCreature)
+ .mapToInt(x -> 1)
+ .sum();
+ if (creaturesMilled < 1) {
return true;
}
- return false;
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller == null) {
+ return true;
+ }
+ controller.drawCards(creaturesMilled, source.getSourceId(), game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CoilsOfTheMedusa.java b/Mage.Sets/src/mage/cards/c/CoilsOfTheMedusa.java
new file mode 100644
index 00000000000..fe0bbe9c313
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/CoilsOfTheMedusa.java
@@ -0,0 +1,104 @@
+package mage.cards.c;
+
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.common.SacrificeSourceCost;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.AttachEffect;
+import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
+import mage.abilities.keyword.DefenderAbility;
+import mage.abilities.keyword.EnchantAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.game.Game;
+import mage.game.combat.CombatGroup;
+import mage.game.permanent.Permanent;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ *
+ * @author arcox
+ */
+public final class CoilsOfTheMedusa extends CardImpl {
+ public CoilsOfTheMedusa(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}");
+ this.subtype.add(SubType.AURA);
+
+ // Enchant creature
+ TargetPermanent auraTarget = new TargetCreaturePermanent();
+ this.getSpellAbility().addTarget(auraTarget);
+ this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
+ this.addAbility(new EnchantAbility(auraTarget.getTargetName()));
+
+ // Enchanted creature gets +1/-1.
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, -1, Duration.WhileOnBattlefield)));
+
+ // Sacrifice Coils of the Medusa: Destroy all non-Wall creatures blocking enchanted creature.
+ this.addAbility(new SimpleActivatedAbility(
+ Zone.BATTLEFIELD,
+ new CoilsOfTheMedusaDestroyEffect(),
+ new SacrificeSourceCost())
+ );
+ }
+
+ public CoilsOfTheMedusa(final CoilsOfTheMedusa card) {
+ super(card);
+ }
+
+ @Override
+ public CoilsOfTheMedusa copy() {
+ return new CoilsOfTheMedusa(this);
+ }
+}
+
+class CoilsOfTheMedusaDestroyEffect extends OneShotEffect {
+ public CoilsOfTheMedusaDestroyEffect() {
+ super(Outcome.DestroyPermanent);
+ this.staticText = "Destroy all non-Wall creatures blocking enchanted creature.";
+ }
+
+ public CoilsOfTheMedusaDestroyEffect(final CoilsOfTheMedusaDestroyEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public CoilsOfTheMedusaDestroyEffect copy() {
+ return new CoilsOfTheMedusaDestroyEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent coils = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
+ List blockers = new ArrayList<>();
+
+ if (coils != null && coils.getAttachedTo() != null) {
+ // grab all creatures blocking enchanted creature
+ Permanent enchantedCreature = game.getPermanent(coils.getAttachedTo());
+ if (enchantedCreature != null && enchantedCreature.isBlocked(game)) {
+ for (CombatGroup group : game.getCombat().getGroups()) {
+ if (group.getAttackers().contains(enchantedCreature.getId())) {
+ blockers = group.getBlockers();
+ break;
+ }
+ }
+
+ // filter out defenders, destroying the rest
+ while (!blockers.isEmpty()) {
+ Permanent blocker = game.getPermanent(blockers.remove(0));
+ if (!blocker.hasAbility(DefenderAbility.getInstance(), game)) {
+ blocker.destroy(source.getSourceId(), game, false);
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/CollectiveBrutality.java b/Mage.Sets/src/mage/cards/c/CollectiveBrutality.java
index 9d60e693abc..985fbac5161 100644
--- a/Mage.Sets/src/mage/cards/c/CollectiveBrutality.java
+++ b/Mage.Sets/src/mage/cards/c/CollectiveBrutality.java
@@ -3,7 +3,6 @@ package mage.cards.c;
import mage.abilities.Mode;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.DiscardCardCost;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
@@ -15,11 +14,9 @@ import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.TargetController;
import mage.filter.FilterCard;
-import mage.filter.FilterPlayer;
-import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
-import mage.target.TargetPlayer;
import mage.target.common.TargetCreaturePermanent;
+import mage.target.common.TargetOpponent;
import java.util.UUID;
@@ -28,16 +25,11 @@ import java.util.UUID;
*/
public final class CollectiveBrutality extends CardImpl {
- private static final FilterCard filter = new FilterCard("instant or sorcery card");
- private static final FilterPlayer filterDiscard = new FilterPlayer("opponent to discard");
- private static final FilterCreaturePermanent filterCreatureMinus = new FilterCreaturePermanent("creature to get -2/-2");
- private static final FilterPlayer filterLoseLife = new FilterPlayer("opponent to lose life");
+ private static final FilterCard filter = new FilterCard("an instant or sorcery card");
static {
filter.add(Predicates.or(CardType.INSTANT.getPredicate(),
CardType.SORCERY.getPredicate()));
- filterDiscard.add(TargetController.OPPONENT.getPlayerPredicate());
- filterLoseLife.add(TargetController.OPPONENT.getPlayerPredicate());
}
public CollectiveBrutality(UUID ownerId, CardSetInfo setInfo) {
@@ -52,28 +44,21 @@ public final class CollectiveBrutality extends CardImpl {
this.getSpellAbility().getModes().setMinModes(1);
this.getSpellAbility().getModes().setMaxModes(3);
- // Target opponent reveals their hand. You choose an instant or sorcery card from it. That player discards that card.;
- Effect effect = new DiscardCardYouChooseTargetEffect(filter, TargetController.ANY);
- effect.setText("Target opponent reveals their hand. You choose an instant or sorcery card from it. That player discards that card");
- this.getSpellAbility().addEffect(effect);
- this.getSpellAbility().addTarget(new TargetPlayer(1, 1, false, filterDiscard).withChooseHint("reveals hand, you choose to discard"));
+ // Target opponent reveals their hand. You choose an instant or sorcery card from it. That player discards that card.
+ this.getSpellAbility().addEffect(new DiscardCardYouChooseTargetEffect(filter, TargetController.OPPONENT));
+ this.getSpellAbility().addTarget(new TargetOpponent().withChooseHint("reveals hand, you choose to discard"));
- // Target creature gets -2/-2 until end of turn.;
+ // Target creature gets -2/-2 until end of turn.
Mode mode = new Mode();
- effect = new BoostTargetEffect(-2, -2, Duration.EndOfTurn);
- effect.setText("Target creature gets -2/-2 until end of turn");
- mode.addEffect(effect);
- mode.addTarget(new TargetCreaturePermanent(filterCreatureMinus).withChooseHint("gets -2/-2 until end of turn"));
+ mode.addEffect(new BoostTargetEffect(-2, -2, Duration.EndOfTurn));
+ mode.addTarget(new TargetCreaturePermanent().withChooseHint("gets -2/-2 until end of turn"));
this.getSpellAbility().addMode(mode);
// Target opponent loses 2 life and you gain 2 life.
mode = new Mode();
- effect = new LoseLifeTargetEffect(2);
- effect.setText("Target opponent loses 2 life");
- mode.addEffect(effect);
- mode.addTarget(new TargetPlayer(1, 1, false, filterLoseLife).withChooseHint("loses 2 life"));
- effect = new GainLifeEffect(2);
- mode.addEffect(effect.concatBy("and"));
+ mode.addEffect(new LoseLifeTargetEffect(2));
+ mode.addEffect(new GainLifeEffect(2).concatBy("and"));
+ mode.addTarget(new TargetOpponent().withChooseHint("loses 2 life"));
this.getSpellAbility().addMode(mode);
}
diff --git a/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java b/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java
index 553a8acec7e..81f3abefa9f 100644
--- a/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java
+++ b/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java
@@ -7,7 +7,6 @@ import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.EscalateAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -90,14 +89,11 @@ class CollectiveDefianceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
- if (targetPlayer != null) {
- int count = targetPlayer.getHand().size();
- for (Card card : targetPlayer.getHand().getCards(game)) {
- targetPlayer.discard(card, source, game);
- }
- targetPlayer.drawCards(count, source.getSourceId(), game);
- return true;
+ if (targetPlayer == null) {
+ return false;
}
- return false;
+ int count = targetPlayer.discard(targetPlayer.getHand(), source, game).size();
+ targetPlayer.drawCards(count, source.getSourceId(), game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CombustibleGearhulk.java b/Mage.Sets/src/mage/cards/c/CombustibleGearhulk.java
index f8d33deabeb..dbc8f48801c 100644
--- a/Mage.Sets/src/mage/cards/c/CombustibleGearhulk.java
+++ b/Mage.Sets/src/mage/cards/c/CombustibleGearhulk.java
@@ -1,24 +1,22 @@
package mage.cards.c;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.FirstStrikeAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
-import java.util.Set;
import java.util.UUID;
/**
@@ -97,7 +95,7 @@ class CombustibleGearhulkMillAndDamageEffect extends OneShotEffect {
public CombustibleGearhulkMillAndDamageEffect() {
super(Outcome.Damage);
- staticText = "put the top three cards of your library into your graveyard, then {this} deals damage to that player equal to the total converted mana cost of those cards.";
+ staticText = "mill three cards, then {this} deals damage to that player equal to the total converted mana cost of those cards.";
}
public CombustibleGearhulkMillAndDamageEffect(final CombustibleGearhulkMillAndDamageEffect effect) {
@@ -108,13 +106,12 @@ class CombustibleGearhulkMillAndDamageEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- int sumCMC = 0;
- Set cardList = controller.getLibrary().getTopCards(game, 3);
- for (Card card : cardList) {
- int test = card.getConvertedManaCost();
- sumCMC += test;
- }
- controller.moveCards(cardList, Zone.GRAVEYARD, source, game);
+ int sumCMC = controller
+ .millCards(3, source, game)
+ .getCards(game)
+ .stream()
+ .mapToInt(MageObject::getConvertedManaCost)
+ .sum();
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
if (targetPlayer != null) {
targetPlayer.damage(sumCMC, source.getSourceId(), game);
diff --git a/Mage.Sets/src/mage/cards/c/CommenceTheEndgame.java b/Mage.Sets/src/mage/cards/c/CommenceTheEndgame.java
index b9d1fe568cb..1c58d22cf9f 100644
--- a/Mage.Sets/src/mage/cards/c/CommenceTheEndgame.java
+++ b/Mage.Sets/src/mage/cards/c/CommenceTheEndgame.java
@@ -1,7 +1,7 @@
package mage.cards.c;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.keyword.AmassEffect;
import mage.cards.CardImpl;
@@ -22,7 +22,7 @@ public final class CommenceTheEndgame extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{U}{U}");
// This spell can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Draw two cards, then amass X, where X is the number of cards in your hand.
this.getSpellAbility().addEffect(new CommenceTheEndgameEffect());
diff --git a/Mage.Sets/src/mage/cards/c/CompellingDeterrence.java b/Mage.Sets/src/mage/cards/c/CompellingDeterrence.java
index 4fb628199e5..246c434497b 100644
--- a/Mage.Sets/src/mage/cards/c/CompellingDeterrence.java
+++ b/Mage.Sets/src/mage/cards/c/CompellingDeterrence.java
@@ -63,7 +63,7 @@ class CompellingDeterrenceEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && player != null) {
player.moveCards(target, Zone.HAND, source, game);
- game.applyEffects();
+ game.getState().processAction(game);
FilterPermanent zombieFilter = new FilterPermanent();
zombieFilter.add(SubType.ZOMBIE.getPredicate());
if (game.getState().getBattlefield().countAll(zombieFilter, controller.getId(), game) > 0) {
diff --git a/Mage.Sets/src/mage/cards/c/CompulsiveResearch.java b/Mage.Sets/src/mage/cards/c/CompulsiveResearch.java
index d132be25f8b..11e97e13c6c 100644
--- a/Mage.Sets/src/mage/cards/c/CompulsiveResearch.java
+++ b/Mage.Sets/src/mage/cards/c/CompulsiveResearch.java
@@ -1,7 +1,5 @@
-
package mage.cards.c;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardTargetEffect;
@@ -10,20 +8,21 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetDiscard;
+import java.util.UUID;
+
/**
- *
* @author Plopman
*/
public final class CompulsiveResearch extends CardImpl {
public CompulsiveResearch(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{U}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}");
// Target player draws three cards. Then that player discards two cards unless they discard a land card.
this.getSpellAbility().addTarget(new TargetPlayer());
@@ -31,7 +30,7 @@ public final class CompulsiveResearch extends CardImpl {
this.getSpellAbility().addEffect(new CompulsiveResearchDiscardEffect());
}
- public CompulsiveResearch(final CompulsiveResearch card) {
+ private CompulsiveResearch(final CompulsiveResearch card) {
super(card);
}
@@ -40,14 +39,15 @@ public final class CompulsiveResearch extends CardImpl {
return new CompulsiveResearch(this);
}
}
+
class CompulsiveResearchDiscardEffect extends OneShotEffect {
- public CompulsiveResearchDiscardEffect() {
+ CompulsiveResearchDiscardEffect() {
super(Outcome.Discard);
this.staticText = "Then that player discards two cards unless they discard a land card";
}
- public CompulsiveResearchDiscardEffect(final CompulsiveResearchDiscardEffect effect) {
+ private CompulsiveResearchDiscardEffect(final CompulsiveResearchDiscardEffect effect) {
super(effect);
}
@@ -59,18 +59,19 @@ class CompulsiveResearchDiscardEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source));
- if (targetPlayer != null && !targetPlayer.getHand().isEmpty()) {
- TargetDiscard target = new TargetDiscard(targetPlayer.getId());
- targetPlayer.choose(Outcome.Discard, target, source.getSourceId(), game);
- Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
- if (card != null) {
- targetPlayer.discard(card, source, game);
- if (!card.isLand() && !targetPlayer.getHand().isEmpty()) {
- targetPlayer.discard(1, false, source, game);
- }
- return true;
- }
+ if (targetPlayer == null || targetPlayer.getHand().isEmpty()) {
+ return false;
}
- return false;
+ if (targetPlayer.getHand().count(StaticFilters.FILTER_CARD_LAND, game) < 1
+ || !targetPlayer.chooseUse(outcome, "Discard a land card?", source, game)) {
+ return !targetPlayer.discard(2, false, source, game).isEmpty();
+ }
+ TargetDiscard target = new TargetDiscard(StaticFilters.FILTER_CARD_LAND_A, targetPlayer.getId());
+ targetPlayer.choose(Outcome.Discard, target, source.getSourceId(), game);
+ Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
+ if (card != null && targetPlayer.discard(card, source, game)) {
+ return true;
+ }
+ return !targetPlayer.discard(2, false, source, game).isEmpty();
}
}
diff --git a/Mage.Sets/src/mage/cards/c/ConclaveCavalier.java b/Mage.Sets/src/mage/cards/c/ConclaveCavalier.java
index f8035d718c5..144808dd33c 100644
--- a/Mage.Sets/src/mage/cards/c/ConclaveCavalier.java
+++ b/Mage.Sets/src/mage/cards/c/ConclaveCavalier.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.constants.SubType;
import mage.abilities.keyword.VigilanceAbility;
@@ -29,7 +29,7 @@ public final class ConclaveCavalier extends CardImpl {
this.addAbility(VigilanceAbility.getInstance());
// When Conclave Cavalier dies, create two green and white 2/2 Elf Knight creature tokens with vigilance.
- this.addAbility(new DiesTriggeredAbility(
+ this.addAbility(new DiesSourceTriggeredAbility(
new CreateTokenEffect(new ElfKnightToken(), 2)
));
}
diff --git a/Mage.Sets/src/mage/cards/c/ConclaveMentor.java b/Mage.Sets/src/mage/cards/c/ConclaveMentor.java
new file mode 100644
index 00000000000..28c1f1217a7
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ConclaveMentor.java
@@ -0,0 +1,101 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DiesSourceTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ConclaveMentor extends CardImpl {
+
+ private static final DynamicValue xValue = new SourcePermanentPowerCount(false);
+
+ public ConclaveMentor(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}");
+
+ this.subtype.add(SubType.CENTAUR);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // If one or more +1/+1 counters would be put on a creature you control, that many plus one +1/+1 counters are put on that creature instead.
+ this.addAbility(new SimpleStaticAbility(new ConclaveMentorEffect()));
+
+ // When Conclave Mentor dies, you gain life equal to its power.
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(xValue, "you gain life equal to its power")));
+ }
+
+ private ConclaveMentor(final ConclaveMentor card) {
+ super(card);
+ }
+
+ @Override
+ public ConclaveMentor copy() {
+ return new ConclaveMentor(this);
+ }
+}
+
+class ConclaveMentorEffect extends ReplacementEffectImpl {
+
+ ConclaveMentorEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.BoostCreature, false);
+ staticText = "If one or more +1/+1 counters would be put on a creature you control, " +
+ "that many plus one +1/+1 counters are put on that creature instead";
+ }
+
+ private ConclaveMentorEffect(final ConclaveMentorEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ event.setAmountForCounters(event.getAmount() + 1, true);
+ return false;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ADD_COUNTERS;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (event.getData().equals(CounterType.P1P1.getName()) && event.getAmount() > 0) {
+ Permanent permanent = game.getPermanent(event.getTargetId());
+ if (permanent == null) {
+ permanent = game.getPermanentEntering(event.getTargetId());
+ }
+ return permanent != null && permanent.isControlledBy(source.getControllerId())
+ && permanent.isCreature();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public ConclaveMentorEffect copy() {
+ return new ConclaveMentorEffect(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/ConfrontTheAssault.java b/Mage.Sets/src/mage/cards/c/ConfrontTheAssault.java
index 985bc5f919a..2c45b4c15d7 100644
--- a/Mage.Sets/src/mage/cards/c/ConfrontTheAssault.java
+++ b/Mage.Sets/src/mage/cards/c/ConfrontTheAssault.java
@@ -31,7 +31,7 @@ public final class ConfrontTheAssault extends CardImpl {
this.addAbility(ability);
// Create three 1/1 white Spirit creature tokens with flying.
- this.getSpellAbility().addEffect(new CreateTokenEffect(new SpiritWhiteToken("ANA"), 3));
+ this.getSpellAbility().addEffect(new CreateTokenEffect(new SpiritWhiteToken(), 3));
}
public ConfrontTheAssault(final ConfrontTheAssault card) {
diff --git a/Mage.Sets/src/mage/cards/c/ConjurersBan.java b/Mage.Sets/src/mage/cards/c/ConjurersBan.java
index db7b0bd5a14..ee03ad72530 100644
--- a/Mage.Sets/src/mage/cards/c/ConjurersBan.java
+++ b/Mage.Sets/src/mage/cards/c/ConjurersBan.java
@@ -12,6 +12,7 @@ import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
+import mage.util.CardUtil;
import java.util.UUID;
@@ -66,18 +67,19 @@ class ConjurersBanEffect extends ContinuousRuleModifyingEffectImpl {
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.CAST_SPELL || event.getType() == GameEvent.EventType.PLAY_LAND) {
MageObject object = game.getObject(event.getSourceId());
- return object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY));
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ return CardUtil.haveSameNames(object, cardName, game);
}
return false;
}
@Override
public String getInfoMessage(Ability source, GameEvent event, Game game) {
- String namedCard = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
String playerName = game.getPlayer(source.getControllerId()).getName();
- if (namedCard == null || playerName == null || source.getSourceObject(game) == null) {
+ if (cardName == null || playerName == null || source.getSourceObject(game) == null) {
return super.getInfoMessage(source, event, game);
}
- return "Until " + playerName + "'s next turn, spells named " + namedCard + " can't be cast and lands named " + namedCard + " can't be played (" + source.getSourceObject(game).getIdName() + ").";
+ return "Until " + playerName + "'s next turn, spells named " + cardName + " can't be cast and lands named " + cardName + " can't be played (" + source.getSourceObject(game).getIdName() + ").";
}
}
diff --git a/Mage.Sets/src/mage/cards/c/ConsignToDream.java b/Mage.Sets/src/mage/cards/c/ConsignToDream.java
index 451c0819ea6..32946ea4ebd 100644
--- a/Mage.Sets/src/mage/cards/c/ConsignToDream.java
+++ b/Mage.Sets/src/mage/cards/c/ConsignToDream.java
@@ -11,6 +11,7 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
+import mage.players.Player;
import mage.target.TargetPermanent;
/**
@@ -58,15 +59,15 @@ class ConsignToDreamEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- boolean applied = false;
Permanent target = game.getPermanent(source.getFirstTarget());
- if (target != null) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (target != null && controller != null) {
if (target.getColor(game).isRed() || target.getColor(game).isGreen()) {
- applied = target.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
+ return controller.putCardsOnTopOfLibrary(target, game, source, true);
} else {
- applied = target.moveToZone(Zone.HAND, source.getSourceId(), game, false);
+ return controller.moveCards(target, Zone.HAND, source, game);
}
}
- return applied;
+ return false;
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/c/ConspicuousSnoop.java b/Mage.Sets/src/mage/cards/c/ConspicuousSnoop.java
new file mode 100644
index 00000000000..1edb15357c2
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/ConspicuousSnoop.java
@@ -0,0 +1,54 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.GainActivatedAbilitiesOfTopCardEffect;
+import mage.abilities.effects.common.continuous.PlayTheTopCardEffect;
+import mage.abilities.effects.common.continuous.PlayWithTheTopCardRevealedEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterCard;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class ConspicuousSnoop extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard("cast Goblin spells");
+
+ static {
+ filter.add(SubType.GOBLIN.getPredicate());
+ }
+
+ public ConspicuousSnoop(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{R}");
+
+ this.subtype.add(SubType.GOBLIN);
+ this.subtype.add(SubType.ROGUE);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Play with the top card of your library revealed.
+ this.addAbility(new SimpleStaticAbility(new PlayWithTheTopCardRevealedEffect()));
+
+ // You may cast Goblin spells from the top of your library.
+ this.addAbility(new SimpleStaticAbility(new PlayTheTopCardEffect(filter)));
+
+ // As long as the top card of your library is a Goblin card, Conspicuous Snoop has all activated abilities of that card.
+ this.addAbility(new SimpleStaticAbility(new GainActivatedAbilitiesOfTopCardEffect(filter.copy().withMessage("a Goblin card"))));
+ }
+
+ private ConspicuousSnoop(final ConspicuousSnoop card) {
+ super(card);
+ }
+
+ @Override
+ public ConspicuousSnoop copy() {
+ return new ConspicuousSnoop(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java b/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java
index 6baed0ceb09..4bddff8c30a 100644
--- a/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java
+++ b/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java
@@ -85,7 +85,7 @@ class ConundrumSphinxEffect extends OneShotEffect {
if (card != null) {
Cards cards = new CardsImpl(card);
player.revealCards(source, player.getName(), cards, game);
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
player.moveCards(cards, Zone.HAND, source, game);
} else {
player.putCardsOnBottomOfLibrary(cards, game, source, false);
diff --git a/Mage.Sets/src/mage/cards/c/CopyEnchantment.java b/Mage.Sets/src/mage/cards/c/CopyEnchantment.java
index a17d5da5263..ed3202936db 100644
--- a/Mage.Sets/src/mage/cards/c/CopyEnchantment.java
+++ b/Mage.Sets/src/mage/cards/c/CopyEnchantment.java
@@ -3,26 +3,12 @@ package mage.cards.c;
import java.util.UUID;
-import mage.MageObject;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.EntersBattlefieldAbility;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.CopyPermanentEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Outcome;
-import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.game.permanent.PermanentCard;
-import mage.players.Player;
-import mage.target.Target;
-import mage.util.functions.EmptyApplyToPermanent;
/**
*
@@ -34,7 +20,6 @@ public final class CopyEnchantment extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}");
// You may have Copy Enchantment enter the battlefield as a copy of any enchantment on the battlefield.
- //this.addAbility(new EntersBattlefieldAbility(new CopyEnchantmentEffect(new FilterEnchantmentPermanent("any enchantment")), true));
this.addAbility(new EntersBattlefieldAbility(new CopyPermanentEffect(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), true));
}
diff --git a/Mage.Sets/src/mage/cards/c/CoreProwler.java b/Mage.Sets/src/mage/cards/c/CoreProwler.java
index 963b642bbe0..708adb93a07 100644
--- a/Mage.Sets/src/mage/cards/c/CoreProwler.java
+++ b/Mage.Sets/src/mage/cards/c/CoreProwler.java
@@ -1,7 +1,7 @@
package mage.cards.c;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.abilities.keyword.InfectAbility;
import mage.cards.CardImpl;
@@ -26,7 +26,7 @@ public final class CoreProwler extends CardImpl {
this.addAbility(InfectAbility.getInstance());
// When Core Prowler dies, proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)
- this.addAbility(new DiesTriggeredAbility(new ProliferateEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new ProliferateEffect()));
}
public CoreProwler(final CoreProwler card) {
diff --git a/Mage.Sets/src/mage/cards/c/CorpseAugur.java b/Mage.Sets/src/mage/cards/c/CorpseAugur.java
index 01f0dea7d4f..4cb6722c91e 100644
--- a/Mage.Sets/src/mage/cards/c/CorpseAugur.java
+++ b/Mage.Sets/src/mage/cards/c/CorpseAugur.java
@@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.CardsInTargetPlayersGraveyardCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
@@ -33,7 +33,7 @@ public final class CorpseAugur extends CardImpl {
CardsInTargetPlayersGraveyardCount dynamicValue = new CardsInTargetPlayersGraveyardCount(new FilterCreatureCard("the number of creature cards"));
Effect effect = new DrawCardSourceControllerEffect(dynamicValue);
effect.setText("You draw X cards");
- Ability ability = new DiesTriggeredAbility(effect, false);
+ Ability ability = new DiesSourceTriggeredAbility(effect, false);
effect = new LoseLifeSourceControllerEffect(dynamicValue);
effect.setText("and you lose X life, where X is the number of creature cards in target player's graveyard");
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/c/CorpseCur.java b/Mage.Sets/src/mage/cards/c/CorpseCur.java
index 617c2602158..79144ef43c0 100644
--- a/Mage.Sets/src/mage/cards/c/CorpseCur.java
+++ b/Mage.Sets/src/mage/cards/c/CorpseCur.java
@@ -30,7 +30,7 @@ public final class CorpseCur extends CardImpl {
public CorpseCur (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.addAbility(InfectAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java b/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java
index d6845d3243b..eaae709b7c5 100644
--- a/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java
+++ b/Mage.Sets/src/mage/cards/c/CorrosiveOoze.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@@ -44,7 +44,7 @@ public final class CorrosiveOoze extends CardImpl {
// Whenever Corrosive Ooze blocks or becomes blocked by an equipped creature, destroy all Equipment attached to that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new CorrosiveOozeEffect()), true);
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, filter, false), new CorrosiveOozeCombatWatcher());
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, filter, false), new CorrosiveOozeCombatWatcher());
}
public CorrosiveOoze(final CorrosiveOoze card) {
@@ -133,7 +133,7 @@ class CorrosiveOozeCombatWatcher extends Watcher {
if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) {
Permanent attacker = game.getPermanent(event.getTargetId());
Permanent blocker = game.getPermanent(event.getSourceId());
- if (attacker != null && CardUtil.haveSameNames(attacker.getName(), "Corrosive Ooze")) { // To check for name is not working if Ooze is copied but name changed
+ if (attacker != null && CardUtil.haveSameNames(attacker, "Corrosive Ooze", game)) { // To check for name is not working if Ooze is copied but name changed
if (blocker != null && hasAttachedEquipment(game, blocker)) {
MageObjectReference oozeMor = new MageObjectReference(attacker, game);
Set relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>());
@@ -141,7 +141,7 @@ class CorrosiveOozeCombatWatcher extends Watcher {
oozeBlocksOrBlocked.put(oozeMor, relatedCreatures);
}
}
- if (blocker != null && CardUtil.haveSameNames(blocker.getName(), "Corrosive Ooze")) {
+ if (blocker != null && CardUtil.haveSameNames(blocker, "Corrosive Ooze", game)) {
if (attacker != null && hasAttachedEquipment(game, attacker)) {
MageObjectReference oozeMor = new MageObjectReference(blocker, game);
Set relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>());
diff --git a/Mage.Sets/src/mage/cards/c/CorruptOfficial.java b/Mage.Sets/src/mage/cards/c/CorruptOfficial.java
index 4c8aed08ecf..c5cdd88794a 100644
--- a/Mage.Sets/src/mage/cards/c/CorruptOfficial.java
+++ b/Mage.Sets/src/mage/cards/c/CorruptOfficial.java
@@ -1,10 +1,9 @@
-
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
@@ -16,6 +15,7 @@ import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
+import mage.game.combat.Combat;
import mage.game.permanent.Permanent;
import mage.players.Player;
@@ -26,7 +26,7 @@ import mage.players.Player;
public final class CorruptOfficial extends CardImpl {
public CorruptOfficial(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.MINION);
this.power = new MageInt(3);
@@ -34,9 +34,9 @@ public final class CorruptOfficial extends CardImpl {
// {2}{B}: Regenerate Corrupt Official.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{2}{B}")));
-
+
// Whenever Corrupt Official becomes blocked, defending player discards a card at random.
- this.addAbility(new BecomesBlockedByCreatureTriggeredAbility(new CorruptOfficialDiscardEffect(), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new CorruptOfficialDiscardEffect(), false));
}
public CorruptOfficial(final CorruptOfficial card) {
@@ -67,11 +67,12 @@ class CorruptOfficialDiscardEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Permanent blockingCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
- if (blockingCreature != null) {
- Player opponent = game.getPlayer(blockingCreature.getControllerId());
- if (opponent != null) {
- opponent.discard(1, true, source, game);
+ Permanent corruptOfficial = game.getPermanent(source.getSourceId());
+ if (corruptOfficial != null) {
+ Combat combat = game.getCombat();
+ Player defendingPlayer = game.getPlayer(combat.getDefendingPlayerId(corruptOfficial.getId(), game));
+ if (defendingPlayer != null) {
+ defendingPlayer.discard(1, true, source, game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CorsairCaptain.java b/Mage.Sets/src/mage/cards/c/CorsairCaptain.java
new file mode 100644
index 00000000000..f23412279b8
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/CorsairCaptain.java
@@ -0,0 +1,50 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.game.permanent.token.TreasureToken;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class CorsairCaptain extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.PIRATE, "Pirates");
+
+ public CorsairCaptain(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.PIRATE);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // When Corsair Captain enters the battlefield, create a treasure token.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TreasureToken())));
+
+ // Other Pirates you control get +1/+1.
+ this.addAbility(new SimpleStaticAbility(
+ new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter, true)
+ ));
+ }
+
+ private CorsairCaptain(final CorsairCaptain card) {
+ super(card);
+ }
+
+ @Override
+ public CorsairCaptain copy() {
+ return new CorsairCaptain(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java b/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java
index a6e289d8f46..483f058a501 100644
--- a/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java
+++ b/Mage.Sets/src/mage/cards/c/CouncilOfTheAbsolute.java
@@ -78,7 +78,7 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifyingEffec
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
- return "You can't cast a spell with that name (" + mageObject.getLogName() + " in play).";
+ return "You can't cast a spell with that name (" + mageObject.getName() + " in play).";
}
return null;
}
@@ -92,8 +92,8 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifyingEffec
public boolean applies(GameEvent event, Ability source, Game game) {
if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
MageObject object = game.getObject(event.getSourceId());
- String needName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- return object != null && CardUtil.haveSameNames(object.getName(), needName);
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ return object != null && CardUtil.haveSameNames(object, cardName, game);
}
return false;
}
@@ -122,8 +122,8 @@ class CouncilOfTheAbsoluteCostReductionEffect extends CostModificationEffectImpl
&& abilityToModify.isControlledBy(source.getControllerId())) {
Card card = game.getCard(abilityToModify.getSourceId());
if (card != null) {
- String needName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- return CardUtil.haveSameNames(card.getName(), needName);
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ return CardUtil.haveSameNames(card, cardName, game);
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/c/Countermand.java b/Mage.Sets/src/mage/cards/c/Countermand.java
index 5c20b25a40f..d2dcff87401 100644
--- a/Mage.Sets/src/mage/cards/c/Countermand.java
+++ b/Mage.Sets/src/mage/cards/c/Countermand.java
@@ -1,28 +1,27 @@
package mage.cards.c;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetSpell;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class Countermand extends CardImpl {
public Countermand(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
// Counter target spell. Its controller puts the top four cards of their library into their graveyard.
@@ -39,6 +38,7 @@ public final class Countermand extends CardImpl {
return new Countermand(this);
}
}
+
class CountermandEffect extends OneShotEffect {
public CountermandEffect() {
@@ -65,7 +65,7 @@ class CountermandEffect extends OneShotEffect {
if (stackObject != null) {
Player controller = game.getPlayer(stackObject.getControllerId());
if (controller != null) {
- controller.moveCards(controller.getLibrary().getTopCards(game, 4), Zone.GRAVEYARD, source, game);
+ controller.millCards(4, source, game);
}
}
return countered;
diff --git a/Mage.Sets/src/mage/cards/c/CradleOfVitality.java b/Mage.Sets/src/mage/cards/c/CradleOfVitality.java
index 59d9d895cea..4640c6695ab 100644
--- a/Mage.Sets/src/mage/cards/c/CradleOfVitality.java
+++ b/Mage.Sets/src/mage/cards/c/CradleOfVitality.java
@@ -61,7 +61,10 @@ class CradleOfVitalityEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget());
- int lifeGained = (Integer) this.getValue("gainedLife");
+ int lifeGained = 0;
+ if (this.getValue("gainedLife") != null) {
+ lifeGained = (Integer) this.getValue("gainedLife");
+ }
return permanent != null && lifeGained > 0
&& permanent.addCounters(CounterType.P1P1.createInstance(lifeGained), source, game);
}
diff --git a/Mage.Sets/src/mage/cards/c/CranialPlating.java b/Mage.Sets/src/mage/cards/c/CranialPlating.java
index 4ff75ee0858..cdafd2c9ac2 100644
--- a/Mage.Sets/src/mage/cards/c/CranialPlating.java
+++ b/Mage.Sets/src/mage/cards/c/CranialPlating.java
@@ -1,47 +1,44 @@
-
package mage.cards.c;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.abilities.keyword.EquipAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.common.FilterControlledPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class CranialPlating extends CardImpl {
- private static final FilterControlledPermanent filterCounted = new FilterControlledPermanent("artifacts you control");
-
- static {
- filterCounted.add(CardType.ARTIFACT.getPredicate());
- }
public CranialPlating(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
this.subtype.add(SubType.EQUIPMENT);
// Equipped creature gets +1/+0 for each artifact you control.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(new PermanentsOnBattlefieldCount(filterCounted), StaticValue.get(0))));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(ArtifactYouControlCount.instance, StaticValue.get(0)))
+ .addHint(ArtifactYouControlHint.instance));
+
// {B}{B}: Attach Cranial Plating to target creature you control.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AttachEffect(Outcome.BoostCreature, "Attach {this} to target creature you control"), new ManaCostsImpl("{B}{B}"));
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
+
// Equip {1}
this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(1)));
}
diff --git a/Mage.Sets/src/mage/cards/c/CrawlingSensation.java b/Mage.Sets/src/mage/cards/c/CrawlingSensation.java
index f3c27887710..83f3cd4b745 100644
--- a/Mage.Sets/src/mage/cards/c/CrawlingSensation.java
+++ b/Mage.Sets/src/mage/cards/c/CrawlingSensation.java
@@ -1,8 +1,5 @@
-
-
package mage.cards.c;
-import java.util.Set;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.OnEventTriggeredAbility;
@@ -69,11 +66,8 @@ class CrawlingSensationTriggeredAbility extends TriggeredAbilityImpl {
for (Card card : zEvent.getCards()) {
if (card != null) {
UUID cardOwnerId = card.getOwnerId();
- Set cardType = card.getCardType();
-
if (cardOwnerId != null
&& card.isOwnedBy(getControllerId())
- && cardType != null
&& card.isLand()) {
game.getState().setValue("usedOnTurn" + getControllerId() + getOriginalId(), game.getTurnNum());
return true;
diff --git a/Mage.Sets/src/mage/cards/c/CrimsonRoc.java b/Mage.Sets/src/mage/cards/c/CrimsonRoc.java
index 6b7d68697cd..1dab5eb0ff2 100644
--- a/Mage.Sets/src/mage/cards/c/CrimsonRoc.java
+++ b/Mage.Sets/src/mage/cards/c/CrimsonRoc.java
@@ -71,7 +71,7 @@ class CrimsonRocTriggeredAbility extends TriggeredAbilityImpl {
Permanent permanent = game.getPermanent(event.getTargetId());
return permanent != null
&& permanent.isCreature()
- && !permanent.getAbilities(game).contains(FlyingAbility.getInstance());
+ && !permanent.hasAbility(FlyingAbility.getInstance(), game);
}
@Override
diff --git a/Mage.Sets/src/mage/cards/c/CrosisThePurger.java b/Mage.Sets/src/mage/cards/c/CrosisThePurger.java
index b2f87e2d6a0..02afdcfbccd 100644
--- a/Mage.Sets/src/mage/cards/c/CrosisThePurger.java
+++ b/Mage.Sets/src/mage/cards/c/CrosisThePurger.java
@@ -1,9 +1,5 @@
-
package mage.cards.c;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
@@ -11,23 +7,23 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.keyword.FlyingAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.choices.ChoiceColor;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
-import mage.filter.FilterCard;
-import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
/**
- *
* @author LoneFox
- *
*/
public final class CrosisThePurger extends CardImpl {
@@ -45,7 +41,7 @@ public final class CrosisThePurger extends CardImpl {
new ManaCostsImpl("{2}{B}")), false, true));
}
- public CrosisThePurger(final CrosisThePurger card) {
+ private CrosisThePurger(final CrosisThePurger card) {
super(card);
}
@@ -62,7 +58,7 @@ class CrosisThePurgerEffect extends OneShotEffect {
this.staticText = "choose a color, then that player reveals their hand and discards all cards of that color.";
}
- CrosisThePurgerEffect(final CrosisThePurgerEffect effect) {
+ private CrosisThePurgerEffect(final CrosisThePurgerEffect effect) {
super(effect);
}
@@ -74,30 +70,28 @@ class CrosisThePurgerEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- ChoiceColor choice = new ChoiceColor();
- player.choose(outcome, choice, game);
- if (choice.isChosen()) {
- game.informPlayers(player.getLogName() + " chooses " + choice.getColor());
- Player damagedPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source));
- if(damagedPlayer != null) {
- damagedPlayer.revealCards("hand of " + damagedPlayer.getName(), damagedPlayer.getHand(), game);
- FilterCard filter = new FilterCard();
- filter.add(new ColorPredicate(choice.getColor()));
- List toDiscard = new ArrayList<>();
- for (UUID cardId : damagedPlayer.getHand()) {
- Card card = game.getCard(cardId);
- if (filter.match(card, game)) {
- toDiscard.add(card);
- }
- }
- for (Card card : toDiscard) {
- damagedPlayer.discard(card, source, game);
- }
- return true;
- }
- }
+ if (player == null) {
+ return false;
}
- return false;
+ ChoiceColor choice = new ChoiceColor();
+ player.choose(outcome, choice, game);
+ if (!choice.isChosen()) {
+ return false;
+ }
+ game.informPlayers(player.getLogName() + " chooses " + choice.getColor());
+ Player damagedPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source));
+ if (damagedPlayer == null) {
+ return false;
+ }
+ damagedPlayer.revealCards("hand of " + damagedPlayer.getName(), damagedPlayer.getHand(), game);
+ Cards cards = new CardsImpl(
+ damagedPlayer.getHand()
+ .getCards(game)
+ .stream()
+ .filter(card -> card.getColor(game).shares(choice.getColor()))
+ .collect(Collectors.toSet())
+ );
+ damagedPlayer.discard(cards, source, game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CrosstownCourier.java b/Mage.Sets/src/mage/cards/c/CrosstownCourier.java
index 093357a261d..bb29e3e6986 100644
--- a/Mage.Sets/src/mage/cards/c/CrosstownCourier.java
+++ b/Mage.Sets/src/mage/cards/c/CrosstownCourier.java
@@ -80,7 +80,7 @@ public final class CrosstownCourier extends CardImpl {
@Override
public String getRule() {
- return "Whenever {this} deals combat damage to a player, that player puts that many cards from the top of their library into their graveyard.";
+ return "Whenever {this} deals combat damage to a player, that player mills that many cards.";
}
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java b/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java
index f5bfddfe290..9089c535cfc 100644
--- a/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java
+++ b/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java
@@ -61,9 +61,9 @@ class CrownOfEmpiresEffect extends OneShotEffect {
boolean scepter = false;
boolean throne = false;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
- if (CardUtil.haveSameNames(permanent.getName(), "Scepter of Empires")) {
+ if (CardUtil.haveSameNames(permanent, "Scepter of Empires", game)) {
scepter = true;
- } else if (CardUtil.haveSameNames(permanent.getName(), "Throne of Empires")) {
+ } else if (CardUtil.haveSameNames(permanent, "Throne of Empires", game)) {
throne = true;
}
if (scepter && throne) break;
diff --git a/Mage.Sets/src/mage/cards/c/CryptLurker.java b/Mage.Sets/src/mage/cards/c/CryptLurker.java
new file mode 100644
index 00000000000..153d25dbef3
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/c/CryptLurker.java
@@ -0,0 +1,52 @@
+package mage.cards.c;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.costs.OrCost;
+import mage.abilities.costs.common.DiscardTargetCost;
+import mage.abilities.costs.common.SacrificeTargetCost;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.StaticFilters;
+import mage.target.common.TargetCardInHand;
+import mage.target.common.TargetControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class CryptLurker extends CardImpl {
+
+ public CryptLurker(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
+
+ this.subtype.add(SubType.HORROR);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(4);
+
+ // When Crypt Lurker enters the battlefield, you may sacrifice a creature or discard a creature card. If you do, draw a card.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(
+ new DrawCardSourceControllerEffect(1),
+ new OrCost(
+ new SacrificeTargetCost(new TargetControlledPermanent(
+ StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT
+ )), new DiscardTargetCost(new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE_A)),
+ "sacrifice a creature or discard a creature card"
+ )
+ )));
+ }
+
+ private CryptLurker(final CryptLurker card) {
+ super(card);
+ }
+
+ @Override
+ public CryptLurker copy() {
+ return new CryptLurker(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/c/CrypticCommand.java b/Mage.Sets/src/mage/cards/c/CrypticCommand.java
index 0e18a518bad..53e291976e6 100644
--- a/Mage.Sets/src/mage/cards/c/CrypticCommand.java
+++ b/Mage.Sets/src/mage/cards/c/CrypticCommand.java
@@ -1,9 +1,9 @@
-
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
@@ -27,18 +27,21 @@ import mage.target.TargetSpell;
public final class CrypticCommand extends CardImpl {
public CrypticCommand(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}{U}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{U}{U}");
// Choose two -
this.getSpellAbility().getModes().setMinModes(2);
this.getSpellAbility().getModes().setMaxModes(2);
// Counter target spell;
- this.getSpellAbility().addEffect(new CounterTargetEffect());
+ Effect effect1 = new CounterTargetEffect();
+ effect1.setText("Counter target spell.");
+ this.getSpellAbility().addEffect(effect1);
this.getSpellAbility().addTarget(new TargetSpell());
// or return target permanent to its owner's hand;
Mode mode = new Mode();
- mode.addEffect(new ReturnToHandTargetEffect());
+ Effect effect2 = new ReturnToHandTargetEffect();
+ effect2.setText("Return target permanent to its owner's hand.");
+ mode.addEffect(effect2);
mode.addTarget(new TargetPermanent());
this.getSpellAbility().getModes().addMode(mode);
// or tap all creatures your opponents control;
@@ -47,7 +50,9 @@ public final class CrypticCommand extends CardImpl {
this.getSpellAbility().getModes().addMode(mode);
// or draw a card.
mode = new Mode();
- mode.addEffect(new DrawCardSourceControllerEffect(1));
+ Effect effect3 = new DrawCardSourceControllerEffect(1);
+ mode.addEffect(effect3);
+ effect3.setText("Draw a card.");
this.getSpellAbility().getModes().addMode(mode);
}
@@ -64,13 +69,14 @@ public final class CrypticCommand extends CardImpl {
class CrypticCommandEffect extends OneShotEffect {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls");
+
static {
- filter.add(TargetController.OPPONENT.getControllerPredicate());
+ filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public CrypticCommandEffect() {
super(Outcome.Tap);
- staticText = "tap all creatures your opponents control";
+ staticText = "Tap all creatures your opponents control";
}
public CrypticCommandEffect(final CrypticCommandEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/c/CrypticSerpent.java b/Mage.Sets/src/mage/cards/c/CrypticSerpent.java
index fb28357301a..bf498614575 100644
--- a/Mage.Sets/src/mage/cards/c/CrypticSerpent.java
+++ b/Mage.Sets/src/mage/cards/c/CrypticSerpent.java
@@ -1,10 +1,11 @@
package mage.cards.c;
import mage.MageInt;
+import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
-import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -12,7 +13,6 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
-import mage.filter.common.FilterInstantOrSorceryCard;
import java.util.UUID;
@@ -21,8 +21,6 @@ import java.util.UUID;
*/
public final class CrypticSerpent extends CardImpl {
- private static final DynamicValue cardsCount = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
-
public CrypticSerpent(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}");
@@ -31,8 +29,11 @@ public final class CrypticSerpent extends CardImpl {
this.toughness = new MageInt(5);
// Cryptic Serpent costs {1} less to cast for each instant and sorcery card in your graveyard.
- this.addAbility(new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(new FilterInstantOrSorceryCard()))
- .addHint(new ValueHint("Instant and sorcery card in your graveyard", cardsCount)));
+ DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
+ ability.setRuleAtTheTop(true);
+ ability.addHint(new ValueHint("Instant and sorcery card in your graveyard", xValue));
+ this.addAbility(ability);
}
public CrypticSerpent(final CrypticSerpent card) {
diff --git a/Mage.Sets/src/mage/cards/c/CrystallineGiant.java b/Mage.Sets/src/mage/cards/c/CrystallineGiant.java
index 47bd468750e..369d9b25c9d 100644
--- a/Mage.Sets/src/mage/cards/c/CrystallineGiant.java
+++ b/Mage.Sets/src/mage/cards/c/CrystallineGiant.java
@@ -92,8 +92,8 @@ class CrystallineGiantEffect extends OneShotEffect {
List counterTypes = new ArrayList();
counterTypes.addAll(counterTypeSet);
counterTypes.removeIf(counters::containsKey);
- if (counterTypes.size() == 0) {
- return false;
+ if (counterTypes.isEmpty()) {
+ return true;
}
return permanent.addCounters(counterTypes.get(
RandomUtil.nextInt(counterTypes.size())
diff --git a/Mage.Sets/src/mage/cards/c/CrystallineResonance.java b/Mage.Sets/src/mage/cards/c/CrystallineResonance.java
index b6e70121927..a9f78614e68 100644
--- a/Mage.Sets/src/mage/cards/c/CrystallineResonance.java
+++ b/Mage.Sets/src/mage/cards/c/CrystallineResonance.java
@@ -33,7 +33,7 @@ public final class CrystallineResonance extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
// Whenever you cycle a card, you may have Crystalline Resonance become a copy of another target permanent until your next turn, except it has this ability.
- this.addAbility(this.createAbility());
+ this.addAbility(CrystallineResonance.createAbility());
}
private CrystallineResonance(final CrystallineResonance card) {
diff --git a/Mage.Sets/src/mage/cards/c/Cubwarden.java b/Mage.Sets/src/mage/cards/c/Cubwarden.java
index 91897e4f145..0d5daa788d5 100644
--- a/Mage.Sets/src/mage/cards/c/Cubwarden.java
+++ b/Mage.Sets/src/mage/cards/c/Cubwarden.java
@@ -9,7 +9,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.game.permanent.token.CatToken;
+import mage.game.permanent.token.CatToken2;
import java.util.UUID;
@@ -32,7 +32,7 @@ public final class Cubwarden extends CardImpl {
this.addAbility(LifelinkAbility.getInstance());
// Whenever this creature mutates, create two 1/1 white Cat creature tokens with lifelink.
- this.addAbility(new MutatesSourceTriggeredAbility(new CreateTokenEffect(new CatToken(), 2)));
+ this.addAbility(new MutatesSourceTriggeredAbility(new CreateTokenEffect(new CatToken2(), 2)));
}
private Cubwarden(final Cubwarden card) {
diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java b/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java
index 1d12b1daf59..b1c0bd8ba66 100644
--- a/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java
+++ b/Mage.Sets/src/mage/cards/c/CurseOfTheBloodyTome.java
@@ -88,6 +88,6 @@ class CurseOfTheBloodyTomeAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "At the beginning of enchanted player's upkeep, that player puts the top two cards of their library into their graveyard.";
+ return "At the beginning of enchanted player's upkeep, that player mills two cards.";
}
}
diff --git a/Mage.Sets/src/mage/cards/c/CursedScroll.java b/Mage.Sets/src/mage/cards/c/CursedScroll.java
index 70d1e5f0485..6ed0c99568f 100644
--- a/Mage.Sets/src/mage/cards/c/CursedScroll.java
+++ b/Mage.Sets/src/mage/cards/c/CursedScroll.java
@@ -70,7 +70,7 @@ class CursedScrollEffect extends OneShotEffect {
}
revealed.add(card);
controller.revealCards(sourceObject.getIdName(), revealed, game);
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
if (creature != null) {
creature.damage(2, source.getSourceId(), game, false, true);
diff --git a/Mage.Sets/src/mage/cards/c/CustodiSoulbinders.java b/Mage.Sets/src/mage/cards/c/CustodiSoulbinders.java
index ab23d88f7d7..968e1360af2 100644
--- a/Mage.Sets/src/mage/cards/c/CustodiSoulbinders.java
+++ b/Mage.Sets/src/mage/cards/c/CustodiSoulbinders.java
@@ -1,7 +1,5 @@
-
package mage.cards.c;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
@@ -21,19 +19,21 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.permanent.token.SpiritWhiteToken;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class CustodiSoulbinders extends CardImpl {
-
+
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures");
+
static {
filter.add(AnotherPredicate.instance);
}
public CustodiSoulbinders(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.CLERIC);
this.power = new MageInt(0);
@@ -42,14 +42,14 @@ public final class CustodiSoulbinders extends CardImpl {
// Custodi Soulbinders enters the battlefield with X +1/+1 counters on it, where X is the number of other creatures on the battlefield.
this.addAbility(new EntersBattlefieldAbility(
new AddCountersSourceEffect(
- CounterType.P1P1.createInstance(),
- new PermanentsOnBattlefieldCount(filter),
- false),
+ CounterType.P1P1.createInstance(),
+ new PermanentsOnBattlefieldCount(filter),
+ false),
"with X +1/+1 counters on it, where X is the number of other creatures on the battlefield"));
-
+
// {2}{W}, Remove a +1/+1 counter from Custodi Soulbinders: Create a 1/1 white Spirit creature token with flying.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SpiritWhiteToken("CNS")), new ManaCostsImpl<>("{2}{W}"));
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SpiritWhiteToken()), new ManaCostsImpl<>("{2}{W}"));
ability.addCost(new RemoveCountersSourceCost(CounterType.P1P1.createInstance()));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/c/CycloneSire.java b/Mage.Sets/src/mage/cards/c/CycloneSire.java
index ea97032c91c..10b665840e7 100644
--- a/Mage.Sets/src/mage/cards/c/CycloneSire.java
+++ b/Mage.Sets/src/mage/cards/c/CycloneSire.java
@@ -4,7 +4,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
@@ -34,7 +34,7 @@ public final class CycloneSire extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Cyclone Sire dies, you may put three +1/+1 counters on target land you control. If you do, that land becomes a 0/0 Elemental creature with haste that's still a land.
- Ability ability = new DiesTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(3)), true);
+ Ability ability = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(3)), true);
Effect effect = new BecomesCreatureTargetEffect(new WallOfResurgenceToken(), false, true, Duration.Custom);
effect.setText("If you do, that land becomes a 0/0 Elemental creature with haste that's still a land");
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/c/CyclopeanGiant.java b/Mage.Sets/src/mage/cards/c/CyclopeanGiant.java
index 1c04cdb2a63..0842dcaa94d 100644
--- a/Mage.Sets/src/mage/cards/c/CyclopeanGiant.java
+++ b/Mage.Sets/src/mage/cards/c/CyclopeanGiant.java
@@ -2,7 +2,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect;
import mage.constants.Duration;
@@ -27,7 +27,7 @@ public final class CyclopeanGiant extends CardImpl {
this.toughness = new MageInt(2);
// When Cyclopean Giant dies, target land becomes a Swamp. Exile Cyclopean Giant.
- DiesTriggeredAbility ability = new DiesTriggeredAbility(new BecomesBasicLandTargetEffect(Duration.EndOfGame, SubType.SWAMP));
+ DiesSourceTriggeredAbility ability = new DiesSourceTriggeredAbility(new BecomesBasicLandTargetEffect(Duration.EndOfGame, SubType.SWAMP));
ability.addEffect(new ExileSourceEffect());
ability.addTarget(new TargetLandPermanent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/c/CyclopeanMummy.java b/Mage.Sets/src/mage/cards/c/CyclopeanMummy.java
index aa72a168785..e8f6458b48f 100644
--- a/Mage.Sets/src/mage/cards/c/CyclopeanMummy.java
+++ b/Mage.Sets/src/mage/cards/c/CyclopeanMummy.java
@@ -3,7 +3,7 @@ package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class CyclopeanMummy extends CardImpl {
this.toughness = new MageInt(1);
// When Cyclopean Mummy dies, exile it.
- this.addAbility(new DiesTriggeredAbility(new ExileSourceEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new ExileSourceEffect()));
}
public CyclopeanMummy(final CyclopeanMummy card) {
diff --git a/Mage.Sets/src/mage/cards/c/CytoplastManipulator.java b/Mage.Sets/src/mage/cards/c/CytoplastManipulator.java
index fa4db9dfc26..4954ae6e4a9 100644
--- a/Mage.Sets/src/mage/cards/c/CytoplastManipulator.java
+++ b/Mage.Sets/src/mage/cards/c/CytoplastManipulator.java
@@ -6,6 +6,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.common.SourceOnBattlefieldCondition;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalContinuousEffect;
@@ -47,7 +48,7 @@ public final class CytoplastManipulator extends CardImpl {
// {U}, {tap}: Gain control of target creature with a +1/+1 counter on it for as long as Cytoplast Manipulator remains on the battlefield.
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(
new GainControlTargetEffect(Duration.Custom, true),
- SourceOnBattlefieldCondition.instance,
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD),
"gain control of target creature with a +1/+1 counter on it for as long as {this} remains on the battlefield");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{U}"));
ability.addCost(new TapSourceCost());
diff --git a/Mage.Sets/src/mage/cards/d/DacksDuplicate.java b/Mage.Sets/src/mage/cards/d/DacksDuplicate.java
index 646597f79c2..ef7b0408370 100644
--- a/Mage.Sets/src/mage/cards/d/DacksDuplicate.java
+++ b/Mage.Sets/src/mage/cards/d/DacksDuplicate.java
@@ -56,8 +56,8 @@ class DacksDuplicateApplyToPermanent extends ApplyToPermanent {
* 29/05/2014 The ability of Dack's Duplicate doesn't target the
* creature.
*/
- permanent.addAbility(new DethroneAbility(), game);
- permanent.addAbility(HasteAbility.getInstance(), game);
+ permanent.addAbility(new DethroneAbility(), source.getSourceId(), game);
+ permanent.addAbility(HasteAbility.getInstance(), source.getSourceId(), game);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/d/DakmorGhoul.java b/Mage.Sets/src/mage/cards/d/DakmorGhoul.java
index 8afa10f66ac..34e559e4593 100644
--- a/Mage.Sets/src/mage/cards/d/DakmorGhoul.java
+++ b/Mage.Sets/src/mage/cards/d/DakmorGhoul.java
@@ -1,11 +1,8 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
@@ -14,24 +11,23 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class DakmorGhoul extends CardImpl {
public DakmorGhoul(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// When Dakmor Ghoul enters the battlefield, target opponent loses 2 life and you gain 2 life.
- Effect effect = new GainLifeEffect(2);
- effect.setText("and you gain 2 life");
Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(2), false);
+ ability.addEffect(new GainLifeEffect(2).concatBy("and"));
ability.addTarget(new TargetOpponent());
- ability.addEffect(effect);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/d/DampingSphere.java b/Mage.Sets/src/mage/cards/d/DampingSphere.java
index b4780d80d7f..c2177cc6907 100644
--- a/Mage.Sets/src/mage/cards/d/DampingSphere.java
+++ b/Mage.Sets/src/mage/cards/d/DampingSphere.java
@@ -1,19 +1,15 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.MageObject;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
+import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
@@ -21,8 +17,9 @@ import mage.game.events.ManaEvent;
import mage.util.CardUtil;
import mage.watchers.common.CastSpellLastTurnWatcher;
+import java.util.UUID;
+
/**
- *
* @author L_J
*/
public final class DampingSphere extends CardImpl {
@@ -90,10 +87,10 @@ class DampingSphereReplacementEffect extends ReplacementEffectImpl {
}
}
-class DampingSphereIncreasementAllEffect extends SpellsCostIncreasementAllEffect {
+class DampingSphereIncreasementAllEffect extends SpellsCostIncreasingAllEffect {
DampingSphereIncreasementAllEffect() {
- super(0);
+ super(1, new FilterCard(), TargetController.ANY);
this.staticText = "Each spell a player casts costs {1} more to cast for each other spell that player has cast this turn";
}
diff --git a/Mage.Sets/src/mage/cards/d/DanceOfTheDead.java b/Mage.Sets/src/mage/cards/d/DanceOfTheDead.java
index e5c70512b6b..53dd4fb3647 100644
--- a/Mage.Sets/src/mage/cards/d/DanceOfTheDead.java
+++ b/Mage.Sets/src/mage/cards/d/DanceOfTheDead.java
@@ -240,9 +240,7 @@ class DanceOfTheDeadChangeAbilityEffect extends ContinuousEffectImpl implements
abilityToRemove = ability;
}
}
- if (abilityToRemove != null) {
- permanent.getAbilities().remove(abilityToRemove);
- }
+ permanent.removeAbility(abilityToRemove, source.getSourceId(), game);
permanent.addAbility(newAbility, source.getSourceId(), game);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/d/DangerousWager.java b/Mage.Sets/src/mage/cards/d/DangerousWager.java
index 1d328c8c063..1e98390b3eb 100644
--- a/Mage.Sets/src/mage/cards/d/DangerousWager.java
+++ b/Mage.Sets/src/mage/cards/d/DangerousWager.java
@@ -1,34 +1,27 @@
-
package mage.cards.d;
-import java.util.UUID;
-import mage.abilities.Ability;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
-import mage.cards.Card;
+import mage.abilities.effects.common.discard.DiscardHandControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
-import mage.game.Game;
-import mage.players.Player;
+
+import java.util.UUID;
/**
- *
* @author North
*/
public final class DangerousWager extends CardImpl {
public DangerousWager(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}");
// Discard your hand, then draw two cards.
- this.getSpellAbility().addEffect(new DangerousWagerEffect());
- this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2));
+ this.getSpellAbility().addEffect(new DiscardHandControllerEffect());
+ this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2).setText(", then draw two cards"));
}
- public DangerousWager(final DangerousWager card) {
+ private DangerousWager(final DangerousWager card) {
super(card);
}
@@ -37,32 +30,3 @@ public final class DangerousWager extends CardImpl {
return new DangerousWager(this);
}
}
-
-class DangerousWagerEffect extends OneShotEffect {
-
- public DangerousWagerEffect() {
- super(Outcome.Discard);
- this.staticText = "Discard your hand";
- }
-
- public DangerousWagerEffect(final DangerousWagerEffect effect) {
- super(effect);
- }
-
- @Override
- public DangerousWagerEffect copy() {
- return new DangerousWagerEffect(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.Sets/src/mage/cards/d/DarettiScrapSavant.java b/Mage.Sets/src/mage/cards/d/DarettiScrapSavant.java
index 03bf92605cd..294589fc0c3 100644
--- a/Mage.Sets/src/mage/cards/d/DarettiScrapSavant.java
+++ b/Mage.Sets/src/mage/cards/d/DarettiScrapSavant.java
@@ -1,7 +1,5 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.CanBeYourCommanderAbility;
@@ -14,12 +12,8 @@ import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffec
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Outcome;
-import mage.constants.SuperType;
-import mage.constants.TargetController;
-import mage.constants.Zone;
+import mage.cards.CardsImpl;
+import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.common.FilterArtifactCard;
import mage.filter.common.FilterControlledArtifactPermanent;
@@ -33,8 +27,9 @@ import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetDiscard;
import mage.target.targetpointer.FixedTarget;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class DarettiScrapSavant extends CardImpl {
@@ -93,14 +88,7 @@ class DarettiDiscardDrawEffect extends OneShotEffect {
if (controller != null) {
TargetDiscard target = new TargetDiscard(0, 2, new FilterCard(), controller.getId());
target.choose(outcome, controller.getId(), source.getSourceId(), game);
- int count = 0;
- for (UUID cardId : target.getTargets()) {
- Card card = game.getCard(cardId);
- if (card != null) {
- controller.discard(card, source, game);
- count++;
- }
- }
+ int count = controller.discard(new CardsImpl(target.getTargets()), source, game).size();
controller.drawCards(count, source.getSourceId(), game);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/d/DarkBargain.java b/Mage.Sets/src/mage/cards/d/DarkBargain.java
index 769842cc372..f6fee752e79 100644
--- a/Mage.Sets/src/mage/cards/d/DarkBargain.java
+++ b/Mage.Sets/src/mage/cards/d/DarkBargain.java
@@ -44,7 +44,7 @@ class DarkBargainEffect extends OneShotEffect {
public DarkBargainEffect() {
super(Outcome.Benefit);
- this.staticText = "Look at the top three cards of your library. Put two of them into your hand and the rest into your graveyard";
+ this.staticText = "Look at the top three cards of your library. Put two of them into your hand and the other into your graveyard";
}
public DarkBargainEffect(final DarkBargainEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/d/DarkRevenant.java b/Mage.Sets/src/mage/cards/d/DarkRevenant.java
index 6741b40a2bd..58206923ac7 100644
--- a/Mage.Sets/src/mage/cards/d/DarkRevenant.java
+++ b/Mage.Sets/src/mage/cards/d/DarkRevenant.java
@@ -4,12 +4,13 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
@@ -34,7 +35,7 @@ public final class DarkRevenant extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Dark Revenant dies, put it on top of its owner's library.
- this.addAbility(new DiesTriggeredAbility(new DarkRevenantEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new DarkRevenantEffect()));
}
public DarkRevenant(final DarkRevenant card) {
@@ -67,10 +68,9 @@ class DarkRevenantEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Card card = game.getCard(source.getSourceId());
if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
- Player owner = game.getPlayer(card.getOwnerId());
- if(owner != null) {
- owner.getGraveyard().remove(card);
- return card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
+ Player controller = game.getPlayer(source.getControllerId());
+ if(controller != null) {
+ return controller.putCardsOnTopOfLibrary(card, game, source, true);
}
}
return true;
diff --git a/Mage.Sets/src/mage/cards/d/DarkslickDrake.java b/Mage.Sets/src/mage/cards/d/DarkslickDrake.java
index 33d29cf7df0..a47db43bfc6 100644
--- a/Mage.Sets/src/mage/cards/d/DarkslickDrake.java
+++ b/Mage.Sets/src/mage/cards/d/DarkslickDrake.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -25,7 +25,7 @@ public final class DarkslickDrake extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(4);
this.addAbility(FlyingAbility.getInstance());
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public DarkslickDrake (final DarkslickDrake card) {
diff --git a/Mage.Sets/src/mage/cards/d/DaruWarchief.java b/Mage.Sets/src/mage/cards/d/DaruWarchief.java
index 211b0173aa3..abee47c84f2 100644
--- a/Mage.Sets/src/mage/cards/d/DaruWarchief.java
+++ b/Mage.Sets/src/mage/cards/d/DaruWarchief.java
@@ -1,7 +1,5 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
@@ -15,8 +13,9 @@ import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class DaruWarchief extends CardImpl {
@@ -30,7 +29,7 @@ public final class DaruWarchief extends CardImpl {
}
public DaruWarchief(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SOLDIER);
@@ -39,6 +38,7 @@ public final class DaruWarchief extends CardImpl {
// Soldier spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
+
// Soldier creatures you control get +1/+2.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 2, Duration.WhileOnBattlefield, filterCreatures, false)));
}
diff --git a/Mage.Sets/src/mage/cards/d/DaybreakCharger.java b/Mage.Sets/src/mage/cards/d/DaybreakCharger.java
new file mode 100644
index 00000000000..21bca3ec70e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/d/DaybreakCharger.java
@@ -0,0 +1,44 @@
+package mage.cards.d;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class DaybreakCharger extends CardImpl {
+
+ public DaybreakCharger(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
+
+ this.subtype.add(SubType.UNICORN);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(1);
+
+ // When Daybreak Charger enters the battlefield, target creature gets +2/+0 until end of turn.
+ Ability ability = new EntersBattlefieldTriggeredAbility(
+ new BoostTargetEffect(2, 0, Duration.EndOfTurn)
+ );
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ }
+
+ private DaybreakCharger(final DaybreakCharger card) {
+ super(card);
+ }
+
+ @Override
+ public DaybreakCharger copy() {
+ return new DaybreakCharger(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/d/DaybreakChimera.java b/Mage.Sets/src/mage/cards/d/DaybreakChimera.java
index 32eeb17e45b..b8035bf7db6 100644
--- a/Mage.Sets/src/mage/cards/d/DaybreakChimera.java
+++ b/Mage.Sets/src/mage/cards/d/DaybreakChimera.java
@@ -1,17 +1,15 @@
package mage.cards.d;
import mage.MageInt;
-import mage.Mana;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.DevotionCount;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
import java.util.UUID;
@@ -28,7 +26,9 @@ public final class DaybreakChimera extends CardImpl {
this.toughness = new MageInt(3);
// This spell costs {X} less to cast, where X is your devotion to white.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new DaybreakChimeraEffect()).addHint(DevotionCount.W.getHint()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(DevotionCount.W))
+ .addHint(DevotionCount.W.getHint())
+ );
// Flying
this.addAbility(FlyingAbility.getInstance());
@@ -43,40 +43,3 @@ public final class DaybreakChimera extends CardImpl {
return new DaybreakChimera(this);
}
}
-
-class DaybreakChimeraEffect extends CostModificationEffectImpl {
-
- DaybreakChimeraEffect() {
- super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {X} less to cast, where X is your devotion to white. " +
- "(Each {W} in the mana costs of permanents you control counts toward your devotion to white.)";
- }
-
- private DaybreakChimeraEffect(final DaybreakChimeraEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- Mana mana = spellAbility.getManaCostsToPay().getMana();
- if (mana.getGeneric() == 0) {
- return false;
- }
- int count = DevotionCount.W.calculate(game, source, this);
- mana.setGeneric(Math.max(mana.getGeneric() - count, 0));
- spellAbility.getManaCostsToPay().load(mana.toString());
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- return abilityToModify instanceof SpellAbility
- && abilityToModify.getSourceId().equals(source.getSourceId());
- }
-
- @Override
- public DaybreakChimeraEffect copy() {
- return new DaybreakChimeraEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/d/DeadReckoning.java b/Mage.Sets/src/mage/cards/d/DeadReckoning.java
index 1e3843ae00c..a12b0bd82fb 100644
--- a/Mage.Sets/src/mage/cards/d/DeadReckoning.java
+++ b/Mage.Sets/src/mage/cards/d/DeadReckoning.java
@@ -7,6 +7,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -59,22 +60,22 @@ class DeadReckoningEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player you = game.getPlayer(source.getControllerId());
+ Player controller = game.getPlayer(source.getControllerId());
TargetCardInYourGraveyard target1 = new TargetCardInYourGraveyard(new FilterCreatureCard("creature card in your graveyard"));
TargetCreaturePermanent target2 = new TargetCreaturePermanent();
- if (you != null) {
+ if (controller != null) {
if (target1.canChoose(source.getControllerId(), game)
- && you.choose(Outcome.Benefit, target1, source.getSourceId(), game)
+ && controller.choose(Outcome.Benefit, target1, source.getSourceId(), game)
&& target2.canChoose(source.getControllerId(), game)
- && you.choose(Outcome.Damage, target2, source.getSourceId(), game)) {
+ && controller.choose(Outcome.Damage, target2, source.getSourceId(), game)) {
Card creatureInGraveyard = game.getCard(target1.getFirstTarget());
if (creatureInGraveyard != null) {
- if (creatureInGraveyard.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true)) {
+ if (controller.putCardsOnTopOfLibrary(creatureInGraveyard, game, source, true)) {
int power = creatureInGraveyard.getPower().getValue();
Permanent creature = game.getPermanent(target2.getFirstTarget());
if (creature != null) {
- creature.damage(power, source.getSourceId(), game, true, true);
+ creature.damage(power, source.getSourceId(), game, false, true);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DeadbridgeShaman.java b/Mage.Sets/src/mage/cards/d/DeadbridgeShaman.java
index 8c8f834a9ba..473fed7dfaa 100644
--- a/Mage.Sets/src/mage/cards/d/DeadbridgeShaman.java
+++ b/Mage.Sets/src/mage/cards/d/DeadbridgeShaman.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class DeadbridgeShaman extends CardImpl {
this.toughness = new MageInt(1);
// When Deadbridge Shaman dies, target opponent discards a card.
- Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(1));
+ Ability ability = new DiesSourceTriggeredAbility(new DiscardTargetEffect(1));
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/d/DeadeyePlunderers.java b/Mage.Sets/src/mage/cards/d/DeadeyePlunderers.java
index 121c9501904..180c7cf2b49 100644
--- a/Mage.Sets/src/mage/cards/d/DeadeyePlunderers.java
+++ b/Mage.Sets/src/mage/cards/d/DeadeyePlunderers.java
@@ -1,37 +1,28 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
-import mage.constants.TargetController;
+import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.FilterPermanent;
import mage.game.permanent.token.TreasureToken;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class DeadeyePlunderers extends CardImpl {
- private static final FilterPermanent filter = new FilterPermanent("artifact you control");
-
- static {
- filter.add(CardType.ARTIFACT.getPredicate());
- filter.add(TargetController.YOU.getControllerPredicate());
- }
-
public DeadeyePlunderers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{B}");
@@ -41,8 +32,9 @@ public final class DeadeyePlunderers extends CardImpl {
this.toughness = new MageInt(3);
// Deadeye Plunderers gets +1/+1 for each artifact you control.
- PermanentsOnBattlefieldCount count = new PermanentsOnBattlefieldCount(filter);
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(count, count, Duration.WhileOnBattlefield)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new BoostSourceEffect(ArtifactYouControlCount.instance, ArtifactYouControlCount.instance, Duration.WhileOnBattlefield)
+ ).addHint(ArtifactYouControlHint.instance));
// {2}{U}{B}: Create a colorless artifact token named Treasure with "{T}, Sacrifice this artifact: Add one mana of any color."
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new TreasureToken()), new ManaCostsImpl("{2}{U}{B}")));
diff --git a/Mage.Sets/src/mage/cards/d/DeadlyGrub.java b/Mage.Sets/src/mage/cards/d/DeadlyGrub.java
index ddf8afee2da..1e836e67311 100644
--- a/Mage.Sets/src/mage/cards/d/DeadlyGrub.java
+++ b/Mage.Sets/src/mage/cards/d/DeadlyGrub.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.condition.common.LastTimeCounterRemovedCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
@@ -38,7 +38,7 @@ public final class DeadlyGrub extends CardImpl {
this.addAbility(new VanishingUpkeepAbility(3));
this.addAbility(new VanishingSacrificeAbility());
// When Deadly Grub dies, if it had no time counters on it, create a 6/1 green Insect creature token with shroud.
- this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesTriggeredAbility(new CreateTokenEffect(new DeadlyGrubToken(), 1)),
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new DeadlyGrubToken(), 1)),
LastTimeCounterRemovedCondition.instance, "When {this} dies, if it had no time counters on it, create a 6/1 green Insect creature token with shroud."));
}
diff --git a/Mage.Sets/src/mage/cards/d/DeadlyRecluse.java b/Mage.Sets/src/mage/cards/d/DeadlyRecluse.java
index b39c37d9dc4..4c5d0420b49 100644
--- a/Mage.Sets/src/mage/cards/d/DeadlyRecluse.java
+++ b/Mage.Sets/src/mage/cards/d/DeadlyRecluse.java
@@ -22,8 +22,12 @@ public final class DeadlyRecluse extends CardImpl {
this.subtype.add(SubType.SPIDER);
this.power = new MageInt(1);
- this.toughness = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Reach (This creature can block creatures with flying.)
this.addAbility(ReachAbility.getInstance());
+
+ // Deathtouch (Any amount of damage this deals to a creature is enough to destroy it.)
this.addAbility(DeathtouchAbility.getInstance());
}
diff --git a/Mage.Sets/src/mage/cards/d/DeathbellowWarCry.java b/Mage.Sets/src/mage/cards/d/DeathbellowWarCry.java
index 18824247a4b..1655ec9108d 100644
--- a/Mage.Sets/src/mage/cards/d/DeathbellowWarCry.java
+++ b/Mage.Sets/src/mage/cards/d/DeathbellowWarCry.java
@@ -72,6 +72,6 @@ class DeathbellowWarCryTarget extends TargetCardInLibrary {
.map(game::getCard)
.filter(Objects::nonNull)
.map(Card::getName)
- .noneMatch(n -> CardUtil.haveSameNames(n, card.getName()));
+ .noneMatch(n -> CardUtil.haveSameNames(card, n, game));
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DeathbloomThallid.java b/Mage.Sets/src/mage/cards/d/DeathbloomThallid.java
index 31edb39de01..b8b8a048a1b 100644
--- a/Mage.Sets/src/mage/cards/d/DeathbloomThallid.java
+++ b/Mage.Sets/src/mage/cards/d/DeathbloomThallid.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
@@ -25,7 +25,7 @@ public final class DeathbloomThallid extends CardImpl {
this.toughness = new MageInt(2);
// When Deathbloom Thallid dies, create a 1/1 green Saproling creature token.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SaprolingToken()), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new SaprolingToken()), false));
}
public DeathbloomThallid(final DeathbloomThallid card) {
diff --git a/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java b/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java
index 023015b9e0d..d306c5e7a1f 100644
--- a/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java
+++ b/Mage.Sets/src/mage/cards/d/DeathbringerRegent.java
@@ -6,7 +6,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.keyword.FlyingAbility;
@@ -63,7 +63,7 @@ class DeathbringerRegentCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
- return CastFromHandSourceCondition.instance.apply(game, source)
+ return CastFromHandSourcePermanentCondition.instance.apply(game, source)
&& game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, game).size() >= 6;
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DeathcurseOgre.java b/Mage.Sets/src/mage/cards/d/DeathcurseOgre.java
index d6fd4f03702..6d5c1ba31f6 100644
--- a/Mage.Sets/src/mage/cards/d/DeathcurseOgre.java
+++ b/Mage.Sets/src/mage/cards/d/DeathcurseOgre.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.LoseLifeAllPlayersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class DeathcurseOgre extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(3);
- this.addAbility(new DiesTriggeredAbility(new LoseLifeAllPlayersEffect(3)));
+ this.addAbility(new DiesSourceTriggeredAbility(new LoseLifeAllPlayersEffect(3)));
}
public DeathcurseOgre (final DeathcurseOgre card) {
diff --git a/Mage.Sets/src/mage/cards/d/Deathgazer.java b/Mage.Sets/src/mage/cards/d/Deathgazer.java
index ac8463fba9e..4ff33fe2357 100644
--- a/Mage.Sets/src/mage/cards/d/Deathgazer.java
+++ b/Mage.Sets/src/mage/cards/d/Deathgazer.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -39,7 +39,7 @@ public final class Deathgazer extends CardImpl {
// Whenever Deathgazer blocks or becomes blocked by a nonblack creature, destroy that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true);
effect.setText("destroy that creature at end of combat");
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, filter, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, filter, false));
}
diff --git a/Mage.Sets/src/mage/cards/d/DeathpactAngel.java b/Mage.Sets/src/mage/cards/d/DeathpactAngel.java
index ebcca304eaf..8b6378a8f7f 100644
--- a/Mage.Sets/src/mage/cards/d/DeathpactAngel.java
+++ b/Mage.Sets/src/mage/cards/d/DeathpactAngel.java
@@ -2,7 +2,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class DeathpactAngel extends CardImpl {
//Flying
this.addAbility(FlyingAbility.getInstance());
//When Deathpact Angel dies, create a 1/1 white and black Cleric creature token. It has "{3}{W}{B}{B}, {T}, Sacrifice this creature: Return a card named Deathpact Angel from your graveyard to the battlefield."
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new DeathpactAngelToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new DeathpactAngelToken())));
}
public DeathpactAngel(final DeathpactAngel card) {
diff --git a/Mage.Sets/src/mage/cards/d/DeathsHeadBuzzard.java b/Mage.Sets/src/mage/cards/d/DeathsHeadBuzzard.java
index 91f87019c4b..93d6785fece 100644
--- a/Mage.Sets/src/mage/cards/d/DeathsHeadBuzzard.java
+++ b/Mage.Sets/src/mage/cards/d/DeathsHeadBuzzard.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class DeathsHeadBuzzard extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Death's-Head Buzzard dies, all creatures get -1/-1 until end of turn.
- this.addAbility(new DiesTriggeredAbility(new BoostAllEffect(-1, -1, Duration.EndOfTurn)));
+ this.addAbility(new DiesSourceTriggeredAbility(new BoostAllEffect(-1, -1, Duration.EndOfTurn)));
}
public DeathsHeadBuzzard(final DeathsHeadBuzzard card) {
diff --git a/Mage.Sets/src/mage/cards/d/DeclarationInStone.java b/Mage.Sets/src/mage/cards/d/DeclarationInStone.java
index 45cfb5b117f..c7edeb0cca7 100644
--- a/Mage.Sets/src/mage/cards/d/DeclarationInStone.java
+++ b/Mage.Sets/src/mage/cards/d/DeclarationInStone.java
@@ -88,7 +88,7 @@ class DeclarationInStoneEffect extends OneShotEffect {
}
}
controller.moveCards(cardsToExile, Zone.EXILED, source, game);
- game.applyEffects();
+ game.getState().processAction(game);
if (nonTokenCount > 0) {
new ClueArtifactToken().putOntoBattlefield(nonTokenCount, game, source.getSourceId(), targetPermanent.getControllerId(), false, false);
}
diff --git a/Mage.Sets/src/mage/cards/d/Decompose.java b/Mage.Sets/src/mage/cards/d/Decompose.java
index c3cf1b5d0cb..4989f1075ae 100644
--- a/Mage.Sets/src/mage/cards/d/Decompose.java
+++ b/Mage.Sets/src/mage/cards/d/Decompose.java
@@ -1,26 +1,25 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInASingleGraveyard;
+import java.util.UUID;
+
/**
- *
* @author ilcartographer
*/
public final class Decompose extends CardImpl {
public Decompose(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
// Exile up to three target cards from a single graveyard.
this.getSpellAbility().addEffect(new ExileTargetEffect());
- this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("cards from a single graveyard")));
+ this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, StaticFilters.FILTER_CARD_CARDS));
}
public Decompose(final Decompose card) {
diff --git a/Mage.Sets/src/mage/cards/d/DecoyGambit.java b/Mage.Sets/src/mage/cards/d/DecoyGambit.java
index 99c29db62cd..d2385583793 100644
--- a/Mage.Sets/src/mage/cards/d/DecoyGambit.java
+++ b/Mage.Sets/src/mage/cards/d/DecoyGambit.java
@@ -6,7 +6,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
@@ -16,12 +15,14 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.targetadjustment.TargetAdjuster;
-
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
+import mage.abilities.condition.Condition;
+import mage.constants.Zone;
/**
* @author TheElk801
@@ -31,7 +32,8 @@ public final class DecoyGambit extends CardImpl {
public DecoyGambit(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
- // For each opponent, choose up to one target creature that player controls, then return that creature to its owner's hand unless its controller has you draw a card.
+ // For each opponent, choose up to one target creature that player controls,
+ // then return that creature to its owner's hand unless its controller has you draw a card.
this.getSpellAbility().addEffect(new DecoyGambitEffect());
this.getSpellAbility().setTargetAdjuster(DecoyGambitAdjuster.instance);
}
@@ -70,8 +72,8 @@ class DecoyGambitEffect extends OneShotEffect {
DecoyGambitEffect() {
super(Outcome.Benefit);
- staticText = "For each opponent, choose up to one target creature that player controls, " +
- "then return that creature to its owner's hand unless its controller has you draw a card.";
+ staticText = "For each opponent, choose up to one target creature that player controls, "
+ + "then return that creature to its owner's hand unless its controller has you draw a card.";
}
private DecoyGambitEffect(final DecoyGambitEffect effect) {
@@ -86,6 +88,8 @@ class DecoyGambitEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
+ HashSet permanentToHand = new HashSet();
+ int numberOfCardsToDraw = 0;
if (controller == null) {
return false;
}
@@ -98,16 +102,54 @@ class DecoyGambitEffect extends OneShotEffect {
.filter(Objects::nonNull)
.collect(Collectors.toList());
for (Permanent permanent : permanents) {
+ // If a creature targeted by Decoy Gambit changes controller, it’s no longer a legal target.
+ new DecoyGambitCondition(permanent).apply(game, source); // save current controller
Player player = game.getPlayer(permanent.getControllerId());
if (player == null) {
continue;
}
- if (player.chooseUse(outcome, "Have " + controller.getName() + " draw a card? If you don't, " +
- permanent.getName() + " will be returned to its owner's hand.", source, game)
- && controller.drawCards(1, source.getSourceId(), game) > 0) {
- player.moveCards(permanent, Zone.HAND, source, game);
+ if (player.chooseUse(outcome, "Have " + controller.getName() + " draw a card? If you don't, "
+ + permanent.getName() + " will be returned to its owner's hand.", source, game)) {
+ game.informPlayers(player.getName() + " chose to have " + controller.getName() + " draw a card.");
+ numberOfCardsToDraw += 1;
+ } else {
+ game.informPlayers(player.getName() + " chose to have their creature returned to their hand.");
+ permanentToHand.add(permanent);
+ }
+ }
+ /*
+ As the Decoy Gambit resolves, first the next opponent in turn order (or, if it’s an opponent’s
+ turn, the opponent whose turn it is) chooses whether you’ll draw a card or return their creature
+ that was targeted to its owner’s hand, then each other opponent in turn order does so knowing
+ the choices made before them. After all choices are made, you draw the appropriate number of
+ cards. After you’ve drawn, the appropriate creatures are all simultaneously returned to their owners’ hands.
+ */
+ controller.drawCards(numberOfCardsToDraw, source.getSourceId(), game);
+ for (Permanent creature : permanentToHand) {
+ if (creature != null
+ && new DecoyGambitCondition(creature).apply(game, source)) { // same controller required
+ creature.moveToZone(Zone.HAND, source.getSourceId(), game, false);
}
}
return true;
}
}
+
+class DecoyGambitCondition implements Condition {
+
+ private UUID controllerId;
+ private final Permanent permanent;
+
+ DecoyGambitCondition(Permanent permanent) {
+ this.permanent = permanent;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ if (controllerId == null) { // is the original controller set
+ controllerId = permanent.getControllerId(); // original controller set
+ }
+ return (permanent != null
+ && Objects.equals(controllerId, permanent.getControllerId()));
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/d/DeepSpawn.java b/Mage.Sets/src/mage/cards/d/DeepSpawn.java
index 1c54645f9c6..3a78baa9fb0 100644
--- a/Mage.Sets/src/mage/cards/d/DeepSpawn.java
+++ b/Mage.Sets/src/mage/cards/d/DeepSpawn.java
@@ -39,7 +39,7 @@ public final class DeepSpawn extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// At the beginning of your upkeep, sacrifice Deep Spawn unless you put the top two cards of your library into your graveyard.
Effect effect = new SacrificeSourceUnlessPaysEffect(new PutTopCardOfYourLibraryToGraveyardCost(2));
- effect.setText("sacrifice {this} unless you put the top two cards of your library into your graveyard");
+ effect.setText("sacrifice {this} unless you mill two cards");
this.addAbility(new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, false));
// {U}: Deep Spawn gains shroud until end of turn and doesn't untap during your next untap step. Tap Deep Spawn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(
diff --git a/Mage.Sets/src/mage/cards/d/DeeprootWarrior.java b/Mage.Sets/src/mage/cards/d/DeeprootWarrior.java
index 42fea81ea0b..e55b432804d 100644
--- a/Mage.Sets/src/mage/cards/d/DeeprootWarrior.java
+++ b/Mage.Sets/src/mage/cards/d/DeeprootWarrior.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
@@ -29,7 +29,7 @@ public final class DeeprootWarrior extends CardImpl {
// Whenever Deeproot Warrior becomes blocked, it gets +1/+1 until end of turn.
Effect effect = new BoostSourceEffect(1, 1, Duration.EndOfTurn);
effect.setText("it gets +1/+1 until end of turn");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public DeeprootWarrior(final DeeprootWarrior card) {
diff --git a/Mage.Sets/src/mage/cards/d/DeepwoodTantiv.java b/Mage.Sets/src/mage/cards/d/DeepwoodTantiv.java
index b8f265102f7..a1e0b9d32a7 100644
--- a/Mage.Sets/src/mage/cards/d/DeepwoodTantiv.java
+++ b/Mage.Sets/src/mage/cards/d/DeepwoodTantiv.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class DeepwoodTantiv extends CardImpl {
this.toughness = new MageInt(4);
// Whenever Deepwood Tantiv becomes blocked, you gain 2 life.
- this.addAbility(new BecomesBlockedTriggeredAbility(new GainLifeEffect(2), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new GainLifeEffect(2), false));
}
public DeepwoodTantiv(final DeepwoodTantiv card) {
diff --git a/Mage.Sets/src/mage/cards/d/DeepwoodWolverine.java b/Mage.Sets/src/mage/cards/d/DeepwoodWolverine.java
index f7e364dcff7..7ed887cf9da 100644
--- a/Mage.Sets/src/mage/cards/d/DeepwoodWolverine.java
+++ b/Mage.Sets/src/mage/cards/d/DeepwoodWolverine.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class DeepwoodWolverine extends CardImpl {
// Whenever Deepwood Wolverine becomes blocked, it gets +2/+0 until end of turn.
Effect effect = new BoostSourceEffect(2, 0, Duration.EndOfTurn);
effect.setText("it gets +2/+0 until end of turn");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public DeepwoodWolverine(final DeepwoodWolverine card) {
diff --git a/Mage.Sets/src/mage/cards/d/DefyDeath.java b/Mage.Sets/src/mage/cards/d/DefyDeath.java
index 3a2f5783d2f..92fa3bbd0ca 100644
--- a/Mage.Sets/src/mage/cards/d/DefyDeath.java
+++ b/Mage.Sets/src/mage/cards/d/DefyDeath.java
@@ -1,7 +1,5 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
@@ -16,8 +14,9 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInYourGraveyard;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class DefyDeath extends CardImpl {
@@ -26,7 +25,7 @@ public final class DefyDeath extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}{W}");
// Return target creature card from your graveyard to the battlefield. If it's an Angel, put two +1/+1 counters on it.
- this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect());
+ this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect(false, false));
this.getSpellAbility().addEffect(new DefyDeathEffect());
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD));
}
diff --git a/Mage.Sets/src/mage/cards/d/DementiaSliver.java b/Mage.Sets/src/mage/cards/d/DementiaSliver.java
index 686a33a1ce4..1610c825ae9 100644
--- a/Mage.Sets/src/mage/cards/d/DementiaSliver.java
+++ b/Mage.Sets/src/mage/cards/d/DementiaSliver.java
@@ -86,7 +86,7 @@ class DementiaSliverEffect extends OneShotEffect {
if (card != null) {
revealed.add(card);
opponent.revealCards(sourceObject.getName(), revealed, game);
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
opponent.discard(card, source, game);
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DemonicEmbrace.java b/Mage.Sets/src/mage/cards/d/DemonicEmbrace.java
new file mode 100644
index 00000000000..a206bc9f767
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/d/DemonicEmbrace.java
@@ -0,0 +1,108 @@
+package mage.cards.d;
+
+import java.util.UUID;
+
+import mage.abilities.costs.Cost;
+import mage.abilities.costs.Costs;
+import mage.abilities.costs.CostsImpl;
+import mage.abilities.costs.common.DiscardCardCost;
+import mage.abilities.costs.common.PayLifeCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.AsThoughEffectImpl;
+import mage.constants.*;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetCreaturePermanent;
+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.continuous.AddCardSubtypeAttachedEffect;
+import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
+import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
+import mage.target.TargetPermanent;
+import mage.abilities.keyword.EnchantAbility;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+
+/**
+ * @author arcox
+ */
+public final class DemonicEmbrace extends CardImpl {
+
+ public DemonicEmbrace(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{B}");
+
+ this.subtype.add(SubType.AURA);
+
+ // Enchant creature
+ TargetPermanent auraTarget = new TargetCreaturePermanent();
+ this.getSpellAbility().addTarget(auraTarget);
+ this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
+ Ability ability = new EnchantAbility(auraTarget.getTargetName());
+ this.addAbility(ability);
+
+ // Enchanted creature gets +3/+1, has flying, and is a Demon in addition to its other types.
+ ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 1, Duration.WhileOnBattlefield));
+ Effect effect = new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA);
+ effect.setText(", has flying");
+ ability.addEffect(effect);
+ effect = new AddCardSubtypeAttachedEffect(SubType.DEMON, Duration.WhileOnBattlefield, AttachmentType.AURA);
+ effect.setText(", and is a Demon in addition to its other types");
+ ability.addEffect(effect);
+ this.addAbility(ability);
+
+ // You may cast Demonic Embrace from your graveyard by paying 3 life and discarding a card in addition to paying its other costs.
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new DemonicEmbracePlayEffect()));
+ }
+
+ public DemonicEmbrace(final DemonicEmbrace card) {
+ super(card);
+ }
+
+ @Override
+ public DemonicEmbrace copy() {
+ return new DemonicEmbrace(this);
+ }
+}
+
+
+class DemonicEmbracePlayEffect extends AsThoughEffectImpl {
+
+ public DemonicEmbracePlayEffect() {
+ super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit);
+ staticText = "You may cast {this} from your graveyard by paying 3 life and discarding a card in addition to paying its other costs";
+ }
+
+ public DemonicEmbracePlayEffect(final DemonicEmbracePlayEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public DemonicEmbracePlayEffect copy() {
+ return new DemonicEmbracePlayEffect(this);
+ }
+
+ @Override
+ public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
+ if (sourceId.equals(source.getSourceId()) && source.isControlledBy(affectedControllerId)) {
+ if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
+ Player player = game.getPlayer(affectedControllerId);
+ if (player != null) {
+ Costs costs = new CostsImpl<>();
+ costs.add(new PayLifeCost(3));
+ costs.add(new DiscardCardCost());
+ player.setCastSourceIdWithAlternateMana(sourceId, new ManaCostsImpl<>("{1}{B}{B}"), costs);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/d/Denied.java b/Mage.Sets/src/mage/cards/d/Denied.java
index b5825c8b1ea..b8d60aec7af 100644
--- a/Mage.Sets/src/mage/cards/d/Denied.java
+++ b/Mage.Sets/src/mage/cards/d/Denied.java
@@ -58,12 +58,11 @@ class DeniedEffect extends OneShotEffect {
return true;
}
Player player = game.getPlayer(targetSpell.getControllerId());
- Object object = game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (player != null && object instanceof String) {
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ if (player != null && cardName != null) {
player.revealCards("Denied!", player.getHand(), game, true);
- String namedCard = (String) object;
for (Card card : player.getHand().getCards(game)) {
- if (card != null && CardUtil.haveSameNames(card.getName(), namedCard)) {
+ if (card != null && CardUtil.haveSameNames(card, cardName, game)) {
game.getStack().counter(targetSpell.getId(), source.getSourceId(), game);
break;
}
diff --git a/Mage.Sets/src/mage/cards/d/DenseCanopy.java b/Mage.Sets/src/mage/cards/d/DenseCanopy.java
index 9a43da5da03..3226e49efaf 100644
--- a/Mage.Sets/src/mage/cards/d/DenseCanopy.java
+++ b/Mage.Sets/src/mage/cards/d/DenseCanopy.java
@@ -66,7 +66,7 @@ class DenseCanopyCantBlockEffect extends RestrictionEffect {
if (attacker == null) {
return true;
}
- return attacker.hasAbility(FlyingAbility.getInstance().getId(), game);
+ return attacker.hasAbility(FlyingAbility.getInstance(), game);
}
@Override
diff --git a/Mage.Sets/src/mage/cards/d/Derelor.java b/Mage.Sets/src/mage/cards/d/Derelor.java
index 6d1ddddc001..e6984a51e64 100644
--- a/Mage.Sets/src/mage/cards/d/Derelor.java
+++ b/Mage.Sets/src/mage/cards/d/Derelor.java
@@ -1,41 +1,41 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementControllerEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author Quercitron
*/
public final class Derelor extends CardImpl {
private static final FilterCard filter = new FilterCard("Black spells");
-
+
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
}
-
+
public Derelor(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.THRULL);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Black spells you cast cost {B} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasementControllerEffect(filter, new ManaCostsImpl<>("{B}"))));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(new ManaCostsImpl<>("{B}"), filter, TargetController.YOU)));
}
public Derelor(final Derelor card) {
diff --git a/Mage.Sets/src/mage/cards/d/DesecratedTomb.java b/Mage.Sets/src/mage/cards/d/DesecratedTomb.java
index b597b3e36d2..0ca91ef33b1 100644
--- a/Mage.Sets/src/mage/cards/d/DesecratedTomb.java
+++ b/Mage.Sets/src/mage/cards/d/DesecratedTomb.java
@@ -1,6 +1,5 @@
package mage.cards.d;
-import java.util.Set;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -60,13 +59,9 @@ class DesecratedTombTriggeredAbility extends TriggeredAbilityImpl {
&& zEvent.getCards() != null) {
for (Card card : zEvent.getCards()) {
if (card != null) {
-
UUID cardOwnerId = card.getOwnerId();
- Set cardType = card.getCardType();
-
if (cardOwnerId != null
&& card.isOwnedBy(getControllerId())
- && cardType != null
&& card.isCreature()) {
return true;
}
diff --git a/Mage.Sets/src/mage/cards/d/Desertion.java b/Mage.Sets/src/mage/cards/d/Desertion.java
index e7ef89c2a14..5758bc61f3a 100644
--- a/Mage.Sets/src/mage/cards/d/Desertion.java
+++ b/Mage.Sets/src/mage/cards/d/Desertion.java
@@ -2,17 +2,20 @@
package mage.cards.d;
import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.effects.common.CounterTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
-import mage.game.stack.Spell;
-import mage.players.Player;
+import mage.game.events.GameEvent;
+import mage.game.events.ZoneChangeEvent;
import mage.target.TargetSpell;
/**
@@ -24,9 +27,12 @@ public final class Desertion extends CardImpl {
public Desertion(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}");
- // Counter target spell. If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard.
- this.getSpellAbility().addEffect(new DesertionEffect());
+ // Counter target spell.
+ this.getSpellAbility().addEffect(new CounterTargetEffect());
this.getSpellAbility().addTarget(new TargetSpell());
+
+ // If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard.
+ this.addAbility(new SimpleStaticAbility(Zone.STACK, new DesertionReplacementEffect()));
}
public Desertion(final Desertion card) {
@@ -39,38 +45,48 @@ public final class Desertion extends CardImpl {
}
}
-class DesertionEffect extends OneShotEffect {
+class DesertionReplacementEffect extends ReplacementEffectImpl {
- public DesertionEffect() {
- super(Outcome.Detriment);
- this.staticText = "Counter target spell. If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard";
+ DesertionReplacementEffect() {
+ super(Duration.WhileOnStack, Outcome.PutCardInPlay);
+ staticText = "If an artifact or creature spell is countered this way, put that card onto the battlefield under your control instead of into its owner's graveyard";
}
- public DesertionEffect(final DesertionEffect effect) {
+ private DesertionReplacementEffect(final DesertionReplacementEffect effect) {
super(effect);
}
@Override
- public DesertionEffect copy() {
- return new DesertionEffect(this);
+ public DesertionReplacementEffect copy() {
+ return new DesertionReplacementEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Spell targetSpell = game.getStack().getSpell(getTargetPointer().getFirst(game, source));
- if (targetSpell != null) {
- if (game.getStack().counter(targetSpell.getId(), source.getSourceId(), game)) {
- game.applyEffects();
- if (targetSpell.isArtifact() || targetSpell.isCreature()) {
- Card card = game.getCard(targetSpell.getSourceId());
- controller.moveCards(card, Zone.BATTLEFIELD, source, game);
- }
- }
- }
- return true;
- }
+ return true;
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ ZoneChangeEvent zce = (ZoneChangeEvent) event;
+ zce.setToZone(Zone.BATTLEFIELD);
+ zce.setPlayerId(source.getControllerId());
return false;
}
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ZONE_CHANGE;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (!event.getSourceId().equals(source.getSourceId())
+ || !(((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD)) {
+ return false;
+ }
+ MageObject mageObject = game.getObject(event.getTargetId());
+ return mageObject != null
+ && (mageObject.isArtifact() || mageObject.isCreature());
+ }
}
diff --git a/Mage.Sets/src/mage/cards/d/DesiccatedNaga.java b/Mage.Sets/src/mage/cards/d/DesiccatedNaga.java
index a9fbe8b25fb..b15a00889d4 100644
--- a/Mage.Sets/src/mage/cards/d/DesiccatedNaga.java
+++ b/Mage.Sets/src/mage/cards/d/DesiccatedNaga.java
@@ -1,4 +1,3 @@
-
package mage.cards.d;
import mage.MageInt;
@@ -6,7 +5,6 @@ import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
@@ -20,7 +18,6 @@ import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
- *
* @author fireshoes
*/
public final class DesiccatedNaga extends CardImpl {
@@ -44,10 +41,8 @@ public final class DesiccatedNaga extends CardImpl {
new LoseLifeTargetEffect(2),
new ManaCostsImpl("{3}{B}"),
new PermanentsOnTheBattlefieldCondition(filter));
+ ability.addEffect(new GainLifeEffect(2).concatBy("and"));
ability.addTarget(new TargetOpponent());
- Effect effect = new GainLifeEffect(2);
- effect.setText("and you gain 2 life");
- ability.addEffect(effect);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/d/DesperateSentry.java b/Mage.Sets/src/mage/cards/d/DesperateSentry.java
index 28dc4fe5c5b..0cb69932d46 100644
--- a/Mage.Sets/src/mage/cards/d/DesperateSentry.java
+++ b/Mage.Sets/src/mage/cards/d/DesperateSentry.java
@@ -4,7 +4,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.DeliriumCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
@@ -32,7 +32,7 @@ public final class DesperateSentry extends CardImpl {
this.toughness = new MageInt(2);
// When Desperate Sentry dies, create a 3/2 colorless Eldrazi Horror creature token.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new EldraziHorrorToken()), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new EldraziHorrorToken()), false));
// Delirium — Desperate Sentry gets +3/+0 as long as there are four or more card types among cards in your graveyard.
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(
diff --git a/Mage.Sets/src/mage/cards/d/DestructorDragon.java b/Mage.Sets/src/mage/cards/d/DestructorDragon.java
index cb37ba3c4b0..94a3ca7b085 100644
--- a/Mage.Sets/src/mage/cards/d/DestructorDragon.java
+++ b/Mage.Sets/src/mage/cards/d/DestructorDragon.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -35,7 +35,7 @@ public final class DestructorDragon extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Destructor Dragon dies, destroy target noncreature permanent.
- Ability ability = new DiesTriggeredAbility(new DestroyTargetEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DestroyTargetEffect(), false);
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/d/DetentionSphere.java b/Mage.Sets/src/mage/cards/d/DetentionSphere.java
index 64943101ae9..c7a99d41a55 100644
--- a/Mage.Sets/src/mage/cards/d/DetentionSphere.java
+++ b/Mage.Sets/src/mage/cards/d/DetentionSphere.java
@@ -85,7 +85,7 @@ class DetentionSphereEntersEffect extends OneShotEffect {
} else {
String name = targetPermanent.getName();
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
- if (permanent != null && CardUtil.haveSameNames(permanent.getName(), name)) {
+ if (permanent != null && CardUtil.haveSameNames(permanent, name, game)) {
controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true);
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DevourFlesh.java b/Mage.Sets/src/mage/cards/d/DevourFlesh.java
index 985f35f554c..c8b64b60045 100644
--- a/Mage.Sets/src/mage/cards/d/DevourFlesh.java
+++ b/Mage.Sets/src/mage/cards/d/DevourFlesh.java
@@ -73,7 +73,7 @@ class DevourFleshSacrificeEffect extends OneShotEffect {
if (permanent != null) {
int gainLife = permanent.getToughness().getValue();
permanent.sacrifice(source.getSourceId(), game);
- game.applyEffects();
+ game.getState().processAction(game);
player.gainLife(gainLife, game, source);
} else {
return false;
diff --git a/Mage.Sets/src/mage/cards/d/DidntSayPlease.java b/Mage.Sets/src/mage/cards/d/DidntSayPlease.java
index f4e6a186b51..96f5edc3635 100644
--- a/Mage.Sets/src/mage/cards/d/DidntSayPlease.java
+++ b/Mage.Sets/src/mage/cards/d/DidntSayPlease.java
@@ -8,7 +8,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetSpell;
@@ -44,8 +43,7 @@ class DidntSayPleaseEffect extends OneShotEffect {
DidntSayPleaseEffect() {
super(Outcome.Benefit);
- staticText = "Counter target spell. Its controller puts " +
- "the top three cards of their library into their graveyard.";
+ staticText = "Counter target spell. Its controller mills three cards.";
}
private DidntSayPleaseEffect(final DidntSayPleaseEffect effect) {
@@ -63,7 +61,7 @@ class DidntSayPleaseEffect extends OneShotEffect {
if (player == null) {
return false;
}
- player.moveCards(player.getLibrary().getTopCards(game, 3), Zone.GRAVEYARD, source, game);
+ player.millCards(3, source, game);
return effect.apply(game, source);
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DigThroughTime.java b/Mage.Sets/src/mage/cards/d/DigThroughTime.java
index fbc8168103a..5a652e5ceba 100644
--- a/Mage.Sets/src/mage/cards/d/DigThroughTime.java
+++ b/Mage.Sets/src/mage/cards/d/DigThroughTime.java
@@ -1,7 +1,5 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.abilities.keyword.DelveAbility;
@@ -11,19 +9,19 @@ import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.FilterCard;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class DigThroughTime extends CardImpl {
public DigThroughTime(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{6}{U}{U}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{6}{U}{U}");
// Delve
this.addAbility(new DelveAbility());
-
+
// Look at the top seven cards of your library. Put two of them into your hand and the rest on the bottom of your library in any order.
this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect(StaticValue.get(7), false, StaticValue.get(2), new FilterCard(), Zone.LIBRARY, false, false));
}
diff --git a/Mage.Sets/src/mage/cards/d/DiminishingReturns.java b/Mage.Sets/src/mage/cards/d/DiminishingReturns.java
index cee47ba7676..f1c69c6f8ca 100644
--- a/Mage.Sets/src/mage/cards/d/DiminishingReturns.java
+++ b/Mage.Sets/src/mage/cards/d/DiminishingReturns.java
@@ -4,7 +4,8 @@ package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
+import mage.abilities.effects.common.DrawCardAllEffect;
+import mage.abilities.effects.common.ShuffleHandGraveyardAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -23,7 +24,8 @@ public final class DiminishingReturns extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{U}{U}");
// Each player shuffles their hand and graveyard into their library. You exile the top ten cards of your library. Then each player draws up to seven cards.
- this.getSpellAbility().addEffect(new DiminishingReturnsEffect());
+ this.getSpellAbility().addEffect(new ShuffleHandGraveyardAllEffect());
+ this.getSpellAbility().addEffect(new DiminishingReturnsEffect());
}
public DiminishingReturns(final DiminishingReturns card) {
@@ -40,7 +42,7 @@ class DiminishingReturnsEffect extends OneShotEffect {
public DiminishingReturnsEffect() {
super(Outcome.Neutral);
- staticText = "Each player shuffles their hand and graveyard into their library. You exile the top ten cards of your library. Then each player draws up to seven cards.";
+ staticText = "You exile the top ten cards of your library. Then each player draws up to seven cards.";
}
public DiminishingReturnsEffect(final DiminishingReturnsEffect effect) {
@@ -51,28 +53,13 @@ class DiminishingReturnsEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
+ controller.moveCards(controller.getLibrary().getTopCards(game, 10), Zone.EXILED, source, game);
+ game.getState().processAction(game);
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
- for (Card card: player.getHand().getCards(game)) {
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- for (Card card: player.getGraveyard().getCards(game)) {
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- player.shuffleLibrary(source, game);
- }
- }
-
- for (Card card: controller.getLibrary().getTopCards(game, 10)) {
- controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.LIBRARY, true);
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int cardsToDrawCount = player.getAmount(0, 7, "How many cards to draw (up to 7)?", game);
- player.drawCards(cardsToDrawCount, source.getSourceId(), game);
+ player.drawCards(player.getAmount(0, 7, "How many cards to draw (up to 7)?", game),
+ source.getSourceId(), game);
}
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java b/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java
index eee9cd1434d..664420628b1 100644
--- a/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java
+++ b/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java
@@ -49,7 +49,9 @@ public final class DireFleetDaredevil extends CardImpl {
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
- // When this enters the battlefield, exile target instant or sorcery card from an opponent's graveyard. You may cast that card this turn and you may spend mana as though it were mana of any color. If that card would be put into a graveyard this turn, exile it instead.
+ // When Dire Fleet Daredevil enters the battlefield, exile target instant or sorcery card from an opponent's graveyard.
+ // You may cast it this turn, and you may spend mana as though it were mana of any type to cast that spell.
+ // If that spell would be put into a graveyard this turn, exile it instead.
Ability ability = new EntersBattlefieldTriggeredAbility(new DireFleetDaredevilEffect());
ability.addTarget(new TargetCardInOpponentsGraveyard(filter));
this.addAbility(ability);
@@ -167,8 +169,9 @@ class DireFleetDaredevilReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Card card = game.getCard(event.getTargetId());
- if (card != null) {
- return card.moveToZone(Zone.EXILED, source.getSourceId(), game, false);
+ Player controller = game.getPlayer(source.getControllerId());
+ if (card != null && controller != null) {
+ return controller.moveCards(card, Zone.EXILED, source, game);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/d/DireFleetHoarder.java b/Mage.Sets/src/mage/cards/d/DireFleetHoarder.java
index b23b13831b6..1c40d691392 100644
--- a/Mage.Sets/src/mage/cards/d/DireFleetHoarder.java
+++ b/Mage.Sets/src/mage/cards/d/DireFleetHoarder.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
@@ -26,7 +26,7 @@ public final class DireFleetHoarder extends CardImpl {
this.toughness = new MageInt(1);
// When Dire Fleet Hoarder dies, create a colorless Treasure artifact token with "{t}, Sacrifice this artifact: Add one mana of any color."
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new TreasureToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new TreasureToken())));
}
public DireFleetHoarder(final DireFleetHoarder card) {
diff --git a/Mage.Sets/src/mage/cards/d/DireFleetWarmonger.java b/Mage.Sets/src/mage/cards/d/DireFleetWarmonger.java
new file mode 100644
index 00000000000..b43fafe14e9
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/d/DireFleetWarmonger.java
@@ -0,0 +1,53 @@
+package mage.cards.d;
+
+import mage.MageInt;
+import mage.abilities.common.BeginningOfCombatTriggeredAbility;
+import mage.abilities.costs.common.SacrificeTargetCost;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.filter.StaticFilters;
+import mage.target.common.TargetControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class DireFleetWarmonger extends CardImpl {
+
+ public DireFleetWarmonger(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}");
+
+ this.subtype.add(SubType.ORC);
+ this.subtype.add(SubType.PIRATE);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // At the beginning of combat on your turn, you may sacrifice another creature. If you do, Dire Fleet Warmonger gets +2/+2 and gains trample until end of turn.
+ this.addAbility(new BeginningOfCombatTriggeredAbility(new DoIfCostPaid(
+ new BoostSourceEffect(2, 2, Duration.EndOfTurn),
+ new SacrificeTargetCost(new TargetControlledPermanent(
+ StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE
+ ))
+ ).addEffect(new GainAbilitySourceEffect(
+ TrampleAbility.getInstance(), Duration.EndOfTurn
+ )), TargetController.YOU, false));
+ }
+
+ private DireFleetWarmonger(final DireFleetWarmonger card) {
+ super(card);
+ }
+
+ @Override
+ public DireFleetWarmonger copy() {
+ return new DireFleetWarmonger(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/d/DiregrafCaptain.java b/Mage.Sets/src/mage/cards/d/DiregrafCaptain.java
index 845221f6d8a..52ee1b1f960 100644
--- a/Mage.Sets/src/mage/cards/d/DiregrafCaptain.java
+++ b/Mage.Sets/src/mage/cards/d/DiregrafCaptain.java
@@ -1,7 +1,5 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
@@ -22,8 +20,9 @@ import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class DiregrafCaptain extends CardImpl {
@@ -35,16 +34,18 @@ public final class DiregrafCaptain extends CardImpl {
}
public DiregrafCaptain(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}");
this.subtype.add(SubType.ZOMBIE);
this.subtype.add(SubType.SOLDIER);
-
this.power = new MageInt(2);
this.toughness = new MageInt(2);
+ // Deathtouch
this.addAbility(DeathtouchAbility.getInstance());
+
// Other Zombie creatures you control get +1/+1.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter, true)));
+
// Whenever another Zombie you control dies, target opponent loses 1 life.
this.addAbility(new DiregrafCaptainTriggeredAbility());
}
@@ -84,12 +85,10 @@ class DiregrafCaptainTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!event.getTargetId().equals(this.getSourceId())) {
- ZoneChangeEvent zEvent = (ZoneChangeEvent)event;
+ ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent()) {
Permanent p = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
- if (p != null && p.isControlledBy(this.controllerId) && filter.match(p, game)) {
- return true;
- }
+ return p != null && p.isControlledBy(this.controllerId) && filter.match(p, game);
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/d/Discontinuity.java b/Mage.Sets/src/mage/cards/d/Discontinuity.java
new file mode 100644
index 00000000000..87f82cc923a
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/d/Discontinuity.java
@@ -0,0 +1,42 @@
+package mage.cards.d;
+
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.MyTurnCondition;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.EndTurnEffect;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.common.MyTurnHint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Zone;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class Discontinuity extends CardImpl {
+
+ public Discontinuity(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}{U}{U}");
+
+ // As long as it's your turn, this spell costs {2}{U}{U} less to cast.
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(
+ new ManaCostsImpl("{2}{U}{U}"), MyTurnCondition.instance
+ ).setText("as long as it's your turn, this spell costs {2}{U}{U} less to cast"))
+ .addHint(MyTurnHint.instance));
+
+ // End the turn.
+ this.getSpellAbility().addEffect(new EndTurnEffect());
+ }
+
+ private Discontinuity(final Discontinuity card) {
+ super(card);
+ }
+
+ @Override
+ public Discontinuity copy() {
+ return new Discontinuity(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/d/DiscordantDirge.java b/Mage.Sets/src/mage/cards/d/DiscordantDirge.java
index 4d2c5f94052..f81f8fa141b 100644
--- a/Mage.Sets/src/mage/cards/d/DiscordantDirge.java
+++ b/Mage.Sets/src/mage/cards/d/DiscordantDirge.java
@@ -9,6 +9,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
@@ -21,7 +22,6 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetOpponent;
-import java.util.Objects;
import java.util.UUID;
/**
@@ -29,8 +29,6 @@ import java.util.UUID;
*/
public final class DiscordantDirge extends CardImpl {
- private static final String rule = "Look at target opponent's hand and choose up to X cards from it, where X is the number of verse counters on {this}. That player discards those cards..";
-
public DiscordantDirge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}");
@@ -47,7 +45,7 @@ public final class DiscordantDirge extends CardImpl {
this.addAbility(ability);
}
- public DiscordantDirge(final DiscordantDirge card) {
+ private DiscordantDirge(final DiscordantDirge card) {
super(card);
}
@@ -59,37 +57,37 @@ public final class DiscordantDirge extends CardImpl {
class DiscordantDirgeEffect extends OneShotEffect {
- public DiscordantDirgeEffect() {
+ DiscordantDirgeEffect() {
super(Outcome.Benefit);
- staticText = "Look at target opponent's hand and choose up to X cards from it, where X is the number of verse counters on {this}. That player discards those card.";
+ staticText = "Look at target opponent's hand and choose up to X cards from it, " +
+ "where X is the number of verse counters on {this}. That player discards those cards";
}
- public DiscordantDirgeEffect(final DiscordantDirgeEffect effect) {
+ private DiscordantDirgeEffect(final DiscordantDirgeEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent discordantDirge = game.getPermanentOrLKIBattlefield(source.getSourceId());
- if (discordantDirge != null) {
- int verseCounters = discordantDirge.getCounters(game).getCount(CounterType.VERSE);
- Player targetOpponent = game.getPlayer(source.getFirstTarget());
- Player controller = game.getPlayer(source.getControllerId());
- if (targetOpponent != null
- && controller != null) {
- controller.lookAtCards(targetOpponent.getName() + " hand", targetOpponent.getHand(), game);
- TargetCard target = new TargetCard(0, verseCounters, Zone.HAND, new FilterCard());
- target.setNotTarget(true);
- if (controller.choose(Outcome.Benefit, targetOpponent.getHand(), target, game)) {
- target.getTargets().stream().map(game::getCard).filter(Objects::nonNull).filter((card) -> (card != null
- && targetOpponent.getHand().contains(card.getId()))).forEachOrdered((card) -> {
- targetOpponent.discard(card, source, game);
- });
- return true;
- }
- }
+ if (discordantDirge == null) {
+ return false;
}
- return false;
+ int verseCounters = discordantDirge.getCounters(game).getCount(CounterType.VERSE);
+ Player targetOpponent = game.getPlayer(source.getFirstTarget());
+ Player controller = game.getPlayer(source.getControllerId());
+ if (targetOpponent == null
+ || controller == null) {
+ return false;
+ }
+ controller.lookAtCards(targetOpponent.getName() + " hand", targetOpponent.getHand(), game);
+ TargetCard target = new TargetCard(0, verseCounters, Zone.HAND, new FilterCard());
+ target.setNotTarget(true);
+ if (!controller.choose(Outcome.Benefit, targetOpponent.getHand(), target, game)) {
+ return false;
+ }
+ targetOpponent.discard(new CardsImpl(target.getTargets()), source, game);
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/d/DiscordantPiper.java b/Mage.Sets/src/mage/cards/d/DiscordantPiper.java
index 2e1a8797da8..ce3d17a0927 100644
--- a/Mage.Sets/src/mage/cards/d/DiscordantPiper.java
+++ b/Mage.Sets/src/mage/cards/d/DiscordantPiper.java
@@ -1,7 +1,7 @@
package mage.cards.d;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class DiscordantPiper extends CardImpl {
this.toughness = new MageInt(1);
// When Discordant Piper dies, create a 0/1 white Goat creature token.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new GoatToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new GoatToken())));
}
private DiscordantPiper(final DiscordantPiper card) {
diff --git a/Mage.Sets/src/mage/cards/d/DiseaseCarriers.java b/Mage.Sets/src/mage/cards/d/DiseaseCarriers.java
index 1c94958523a..0e926a6ad84 100644
--- a/Mage.Sets/src/mage/cards/d/DiseaseCarriers.java
+++ b/Mage.Sets/src/mage/cards/d/DiseaseCarriers.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class DiseaseCarriers extends CardImpl {
this.toughness = new MageInt(2);
// When Disease Carriers dies, target creature gets -2/-2 until end of turn.
- Ability ability = new DiesTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn), false);
+ Ability ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn), false);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/d/DismissIntoDream.java b/Mage.Sets/src/mage/cards/d/DismissIntoDream.java
index 16a2addbe15..2c2a2fcd09f 100644
--- a/Mage.Sets/src/mage/cards/d/DismissIntoDream.java
+++ b/Mage.Sets/src/mage/cards/d/DismissIntoDream.java
@@ -3,13 +3,15 @@ package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
+import mage.abilities.Mode;
import mage.abilities.common.BecomesTargetTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.SacrificeSourceEffect;
+import mage.abilities.effects.common.continuous.CreaturesBecomeOtherTypeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
+import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
@@ -20,13 +22,18 @@ import mage.game.permanent.Permanent;
*/
public final class DismissIntoDream extends CardImpl {
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Each creature your opponents control");
+ static {
+ filter.add(TargetController.OPPONENT.getControllerPredicate());
+ }
+
public DismissIntoDream(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{6}{U}");
// Each creature your opponents control is an Illusion in addition to its other types
// and has "When this creature becomes the target of a spell or ability, sacrifice it."
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DismissIntoDreamEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DismissIntoDreamEffect(filter)));
}
public DismissIntoDream(final DismissIntoDream card) {
@@ -39,16 +46,11 @@ public final class DismissIntoDream extends CardImpl {
}
}
-class DismissIntoDreamEffect extends ContinuousEffectImpl {
+class DismissIntoDreamEffect extends CreaturesBecomeOtherTypeEffect {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
- static {
- filter.add(TargetController.OPPONENT.getControllerPredicate());
- }
-
- DismissIntoDreamEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Detriment);
- this.staticText = "Each creature your opponents control is an Illusion in addition to its other types and has \"When this creature becomes the target of a spell or ability, sacrifice it.\"";
+ DismissIntoDreamEffect(FilterPermanent filter) {
+ super(filter, SubType.ILLUSION, Duration.WhileOnBattlefield);
+ this.outcome = Outcome.Detriment;
}
DismissIntoDreamEffect(final DismissIntoDreamEffect effect) {
@@ -67,23 +69,24 @@ class DismissIntoDreamEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
- for (Permanent object: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
- switch (layer) {
- case AbilityAddingRemovingEffects_6:
- object.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), source.getSourceId(), game);
- break;
- case TypeChangingEffects_4:
- if (!object.hasSubtype(SubType.ILLUSION, game)) {
- object.getSubtype(game).add(SubType.ILLUSION);
- }
- break;
+ super.apply(layer, sublayer, source, game);
+
+ if (layer == Layer.AbilityAddingRemovingEffects_6) {
+ for (Permanent object: game.getBattlefield().getActivePermanents(this.filter, source.getControllerId(), game)) {
+ object.addAbility(new BecomesTargetTriggeredAbility(new SacrificeSourceEffect()), source.getSourceId(), game);
}
}
+
return true;
}
@Override
public boolean hasLayer(Layer layer) {
- return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4;
+ return super.hasLayer(layer) || layer == Layer.AbilityAddingRemovingEffects_6;
+ }
+
+ @Override
+ public String getText(Mode mode) {
+ return super.getText(mode) + " and has \"When this creature becomes the target of a spell or ability, sacrifice it.\"";
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DistantMemories.java b/Mage.Sets/src/mage/cards/d/DistantMemories.java
index 1869d6ba375..3833a540a9d 100644
--- a/Mage.Sets/src/mage/cards/d/DistantMemories.java
+++ b/Mage.Sets/src/mage/cards/d/DistantMemories.java
@@ -65,7 +65,7 @@ class DistantMemoriesEffect extends OneShotEffect {
if (controller.searchLibrary(target, source, game)) {
Card card = controller.getLibrary().remove(target.getFirstTarget(), game);
if (card != null) {
- card.moveToZone(Zone.EXILED, source.getSourceId(), game, false);
+ controller.moveCards(card, Zone.EXILED, source, game);
controller.shuffleLibrary(source, game);
StringBuilder sb = new StringBuilder();
@@ -76,9 +76,13 @@ class DistantMemoriesEffect extends OneShotEffect {
Set opponents = game.getOpponents(source.getControllerId());
for (UUID opponentUuid : opponents) {
Player opponent = game.getPlayer(opponentUuid);
- if (opponent != null
- && opponent.chooseUse(Outcome.Detriment, sb.toString(), source, game)) {
- putInHand = true;
+ if (opponent != null) {
+ if (opponent.chooseUse(Outcome.Detriment, sb.toString(), source, game)) {
+ putInHand = true;
+ game.informPlayers(opponent.getName() + " decides to put the selected card into the player's hand.");
+ } else {
+ game.informPlayers(opponent.getName() + " decides to leave the card in exile.");
+ }
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DistendedMindbender.java b/Mage.Sets/src/mage/cards/d/DistendedMindbender.java
index 13500ac1449..8b6c5813b8b 100644
--- a/Mage.Sets/src/mage/cards/d/DistendedMindbender.java
+++ b/Mage.Sets/src/mage/cards/d/DistendedMindbender.java
@@ -1,38 +1,38 @@
-
package mage.cards.d;
-import java.util.List;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CastSourceTriggeredAbility;
import mage.abilities.keyword.EmergeAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
+import mage.target.common.TargetCardInHand;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+import mage.constants.Zone;
+
/**
- *
* @author fireshoes
*/
public final class DistendedMindbender extends CardImpl {
public DistendedMindbender(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{8}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{8}");
this.subtype.add(SubType.ELDRAZI);
this.subtype.add(SubType.INSECT);
this.power = new MageInt(5);
@@ -88,30 +88,20 @@ class DistendedMindbenderEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player opponent = game.getPlayer(source.getFirstTarget());
Player controller = game.getPlayer(source.getControllerId());
- if (opponent != null && controller != null) {
- opponent.revealCards("Distended Mindbender", opponent.getHand(), game);
- TargetCard targetThreeOrLess = new TargetCard(1, Zone.HAND, filterThreeOrLess);
- TargetCard targetFourOrGreater = new TargetCard(1, Zone.HAND, filterFourOrGreater);
- if (controller.choose(Outcome.Benefit, opponent.getHand(), targetThreeOrLess, game)) {
- List targets = targetThreeOrLess.getTargets();
- for (UUID targetId : targets) {
- Card card = opponent.getHand().get(targetId, game);
- if (card != null) {
- opponent.discard(card, source, game);
- }
- }
- }
- if (controller.choose(Outcome.Benefit, opponent.getHand(), targetFourOrGreater, game)) {
- List targets = targetFourOrGreater.getTargets();
- for (UUID targetId : targets) {
- Card card = opponent.getHand().get(targetId, game);
- if (card != null) {
- opponent.discard(card, source, game);
- }
- }
- }
- return true;
+ if (opponent == null || controller == null) {
+ return false;
}
- return false;
+ opponent.revealCards(source, opponent.getHand(), game);
+ TargetCard targetThreeOrLess = new TargetCard(1, Zone.HAND, filterThreeOrLess);
+ TargetCard targetFourOrGreater = new TargetCard(1, Zone.HAND, filterFourOrGreater);
+ Cards toDiscard = new CardsImpl();
+ if (controller.chooseTarget(Outcome.Benefit, opponent.getHand(), targetThreeOrLess, source, game)) {
+ toDiscard.addAll(targetThreeOrLess.getTargets());
+ }
+ if (controller.chooseTarget(Outcome.Benefit, opponent.getHand(), targetFourOrGreater, source, game)) {
+ toDiscard.addAll(targetFourOrGreater.getTargets());
+ }
+ opponent.discard(toDiscard, source, game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DiviningWitch.java b/Mage.Sets/src/mage/cards/d/DiviningWitch.java
index 39e231aa203..a1a2f862bb3 100644
--- a/Mage.Sets/src/mage/cards/d/DiviningWitch.java
+++ b/Mage.Sets/src/mage/cards/d/DiviningWitch.java
@@ -92,7 +92,7 @@ public final class DiviningWitch extends CardImpl {
if (card != null) {
cardsToReaveal.add(card);
// Put that card into your hand
- if (CardUtil.haveSameNames(card.getName(), name)) {
+ if (CardUtil.haveSameNames(card, name, game)) {
cardToHand = card;
break;
}
diff --git a/Mage.Sets/src/mage/cards/d/DomrisAmbush.java b/Mage.Sets/src/mage/cards/d/DomrisAmbush.java
index f1c177cb97d..99eeb781a0c 100644
--- a/Mage.Sets/src/mage/cards/d/DomrisAmbush.java
+++ b/Mage.Sets/src/mage/cards/d/DomrisAmbush.java
@@ -1,19 +1,14 @@
package mage.cards.d;
-import mage.abilities.Ability;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
@@ -52,33 +47,3 @@ public final class DomrisAmbush extends CardImpl {
return new DomrisAmbush(this);
}
}
-
-class DomrisAmbushEffect extends OneShotEffect {
-
- DomrisAmbushEffect() {
- super(Outcome.Benefit);
- staticText = "Put a +1/+1 counter on target creature you control. " +
- "Then that creature deals damage equal to its power " +
- "to target creature or planeswalker you don't control.";
- }
-
- private DomrisAmbushEffect(final DomrisAmbushEffect effect) {
- super(effect);
- }
-
- @Override
- public DomrisAmbushEffect copy() {
- return new DomrisAmbushEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Permanent permanent = game.getPermanent(source.getFirstTarget());
- if (permanent == null) {
- return false;
- }
- permanent.addCounters(CounterType.P1P1.createInstance(), source, game);
- game.applyEffects();
- return new DamageWithPowerFromOneToAnotherTargetEffect().apply(game, source);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/d/DoomedDissenter.java b/Mage.Sets/src/mage/cards/d/DoomedDissenter.java
index 04e3dd2ccef..08c87cbdc90 100644
--- a/Mage.Sets/src/mage/cards/d/DoomedDissenter.java
+++ b/Mage.Sets/src/mage/cards/d/DoomedDissenter.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class DoomedDissenter extends CardImpl {
this.toughness = new MageInt(1);
// When Doomed Dissenter dies, create a 2/2 black Zombie creature token.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ZombieToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new ZombieToken())));
}
public DoomedDissenter(final DoomedDissenter card) {
diff --git a/Mage.Sets/src/mage/cards/d/DoomedTraveler.java b/Mage.Sets/src/mage/cards/d/DoomedTraveler.java
index d1d89ccfa3f..cbdbfefeafb 100644
--- a/Mage.Sets/src/mage/cards/d/DoomedTraveler.java
+++ b/Mage.Sets/src/mage/cards/d/DoomedTraveler.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class DoomedTraveler extends CardImpl {
this.toughness = new MageInt(1);
// When Doomed Traveler dies, create a 1/1 white Spirit creature token with flying.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken())));
}
public DoomedTraveler(final DoomedTraveler card) {
diff --git a/Mage.Sets/src/mage/cards/d/Doomsday.java b/Mage.Sets/src/mage/cards/d/Doomsday.java
index 59f04c1df2d..15ed6ab58a3 100644
--- a/Mage.Sets/src/mage/cards/d/Doomsday.java
+++ b/Mage.Sets/src/mage/cards/d/Doomsday.java
@@ -58,47 +58,24 @@ class DoomsdayEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getControllerId());
+ Player controller = game.getPlayer(source.getControllerId());
- if (player != null) {
+ if (controller != null) {
//Search your library and graveyard for five cards
Cards allCards = new CardsImpl();
- Cards cards = new CardsImpl();
- allCards.addAll(player.getLibrary().getCardList());
- allCards.addAll(player.getGraveyard());
+ allCards.addAll(controller.getLibrary().getCardList());
+ allCards.addAll(controller.getGraveyard());
int number = Math.min(5, allCards.size());
TargetCard target = new TargetCard(number, number, Zone.ALL, new FilterCard());
- if (player.choose(Outcome.Benefit, allCards, target, game)) {
- // exile the rest
- for (UUID uuid : allCards) {
- if (!target.getTargets().contains(uuid)) {
- Card card = game.getCard(uuid);
- if (card != null) {
- card.moveToExile(null, "Doomsday", source.getSourceId(), game);
- }
- } else {
- cards.add(uuid);
- }
-
- }
+ if (controller.choose(Outcome.Benefit, allCards, target, game)) {
+ Cards toLibrary = new CardsImpl(target.getTargets());
+ allCards.removeAll(toLibrary);
+ // Exile the rest
+ controller.moveCards(allCards, Zone.EXILED, source, game);
//Put the chosen cards on top of your library in any order
- target = new TargetCard(Zone.ALL, new FilterCard("Card to put on top"));
- while (cards.size() > 1 && player.canRespond()) {
- player.choose(Outcome.Neutral, cards, target, game);
- Card card = cards.get(target.getFirstTarget(), game);
- if (card != null) {
- cards.remove(card);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- target.clearChosen();
- }
- if (cards.size() == 1) {
- Card card = cards.get(cards.iterator().next(), game);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
+ controller.putCardsOnTopOfLibrary(toLibrary, game, source, true);
}
-
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/d/DoubleVision.java b/Mage.Sets/src/mage/cards/d/DoubleVision.java
new file mode 100644
index 00000000000..f71749174e4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/d/DoubleVision.java
@@ -0,0 +1,86 @@
+package mage.cards.d;
+
+import mage.abilities.common.SpellCastControllerTriggeredAbility;
+import mage.abilities.effects.common.CopyTargetSpellEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.filter.common.FilterInstantOrSorcerySpell;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.stack.Spell;
+import mage.target.targetpointer.FixedTarget;
+import mage.watchers.common.SpellsCastWatcher;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+/**
+ * @author htrajan
+ */
+public final class DoubleVision extends CardImpl {
+
+ public DoubleVision(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}");
+
+ // Whenever you cast your first instant or sorcery spell each turn, copy that spell. You may choose new targets for the copy.
+ this.addAbility(new DoubleVisionCopyTriggeredAbility(), new SpellsCastWatcher());
+ }
+
+ private DoubleVision(final DoubleVision card) {
+ super(card);
+ }
+
+ @Override
+ public DoubleVision copy() {
+ return new DoubleVision(this);
+ }
+}
+
+class DoubleVisionCopyTriggeredAbility extends SpellCastControllerTriggeredAbility {
+
+ DoubleVisionCopyTriggeredAbility() {
+ super(new CopyTargetSpellEffect(true), new FilterInstantOrSorcerySpell(), false);
+ }
+
+ DoubleVisionCopyTriggeredAbility(DoubleVisionCopyTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public DoubleVisionCopyTriggeredAbility copy() {
+ return new DoubleVisionCopyTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (super.checkTrigger(event, game)) {
+ Spell spell = game.getStack().getSpell(event.getTargetId());
+ if (isFirstInstantOrSorceryCastByPlayerOnTurn(spell, game)) {
+ this.getEffects().get(0).setTargetPointer(new FixedTarget(spell.getId()));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isFirstInstantOrSorceryCastByPlayerOnTurn(Spell spell, Game game) {
+ if (spell != null) {
+ SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
+ if (watcher != null) {
+ List eligibleSpells = watcher.getSpellsCastThisTurn(this.getControllerId())
+ .stream()
+ .filter(s -> s.isInstant() || s.isSorcery())
+ .collect(Collectors.toList());
+ return eligibleSpells.size() == 1 && eligibleSpells.get(0).getId().equals(spell.getId());
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever you cast your first instant or sorcery spell each turn, copy that spell. You may choose new targets for the copy.";
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/d/DovinHandOfControl.java b/Mage.Sets/src/mage/cards/d/DovinHandOfControl.java
index 34eaf023bcc..dc14c627a52 100644
--- a/Mage.Sets/src/mage/cards/d/DovinHandOfControl.java
+++ b/Mage.Sets/src/mage/cards/d/DovinHandOfControl.java
@@ -2,30 +2,35 @@ package mage.cards.d;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
-import mage.abilities.SpellAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.PreventDamageByTargetEffect;
import mage.abilities.effects.common.PreventDamageToTargetEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
-import mage.cards.Card;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
+import mage.filter.FilterCard;
import mage.filter.StaticFilters;
-import mage.game.Game;
+import mage.filter.predicate.Predicates;
import mage.target.TargetPermanent;
-import mage.util.CardUtil;
import java.util.UUID;
-import mage.abilities.mana.ManaAbility;
-import mage.game.stack.Spell;
/**
* @author TheElk801
*/
public final class DovinHandOfControl extends CardImpl {
+ private static final FilterCard filter = new FilterCard("Artifact, instant, and sorcery spells");
+
+ static {
+ filter.add(Predicates.or(
+ CardType.ARTIFACT.getPredicate(),
+ CardType.INSTANT.getPredicate(),
+ CardType.SORCERY.getPredicate()));
+ }
+
public DovinHandOfControl(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{W/U}");
@@ -34,7 +39,7 @@ public final class DovinHandOfControl extends CardImpl {
this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
// Artifact, instant, and sorcery spells your opponents cast cost {1} more to cast.
- this.addAbility(new SimpleStaticAbility(new DovinHandOfControlEffect()));
+ this.addAbility(new SimpleStaticAbility(new SpellsCostIncreasingAllEffect(1, filter, TargetController.OPPONENT)));
// -1: Until your next turn, prevent all damage that would be dealt to and dealt by target permanent an opponent controls.
Ability ability = new LoyaltyAbility(new PreventDamageToTargetEffect(
@@ -55,40 +60,4 @@ public final class DovinHandOfControl extends CardImpl {
public DovinHandOfControl copy() {
return new DovinHandOfControl(this);
}
-}
-
-class DovinHandOfControlEffect extends CostModificationEffectImpl {
-
- DovinHandOfControlEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Artifact, instant, and sorcery spells your opponents cast cost {1} more to cast";
- }
-
- private DovinHandOfControlEffect(DovinHandOfControlEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -1);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- Card card = game.getCard(abilityToModify.getSourceId());
- if (!(abilityToModify instanceof SpellAbility)) {
- return false;
- }
- return card != null
- && (card.isInstantOrSorcery()
- || card.isArtifact())
- && game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId());
- }
-
- @Override
- public DovinHandOfControlEffect copy() {
- return new DovinHandOfControlEffect(this);
- }
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/d/Draco.java b/Mage.Sets/src/mage/cards/d/Draco.java
index 973d2433ef2..736a234e7ab 100644
--- a/Mage.Sets/src/mage/cards/d/Draco.java
+++ b/Mage.Sets/src/mage/cards/d/Draco.java
@@ -35,7 +35,7 @@ public final class Draco extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Domain - Draco costs {2} less to cast for each basic land type among lands you control.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new DracoCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new DracoCostReductionEffect()));
// Domain - At the beginning of your upkeep, sacrifice Draco unless you pay {10}. This cost is reduced by {2} for each basic land type among lands you control.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DracoSacrificeUnlessPaysEffect(), TargetController.YOU, false));
diff --git a/Mage.Sets/src/mage/cards/d/DragToTheUnderworld.java b/Mage.Sets/src/mage/cards/d/DragToTheUnderworld.java
index e8c6687c808..bc91ad64c37 100644
--- a/Mage.Sets/src/mage/cards/d/DragToTheUnderworld.java
+++ b/Mage.Sets/src/mage/cards/d/DragToTheUnderworld.java
@@ -1,16 +1,13 @@
package mage.cards.d;
-import mage.Mana;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.DevotionCount;
import mage.abilities.effects.common.DestroyTargetEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
+import mage.constants.CardType;
+import mage.constants.Zone;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
@@ -24,7 +21,7 @@ public final class DragToTheUnderworld extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}{B}");
// This spell costs {X} less to cast, where X is your devotion to black.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new DragToTheUnderworldEffect())
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(DevotionCount.B))
.addHint(DevotionCount.B.getHint())
.setRuleAtTheTop(true));
@@ -41,41 +38,4 @@ public final class DragToTheUnderworld extends CardImpl {
public DragToTheUnderworld copy() {
return new DragToTheUnderworld(this);
}
-}
-
-class DragToTheUnderworldEffect extends CostModificationEffectImpl {
-
- DragToTheUnderworldEffect() {
- super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {X} less to cast, where X is your devotion to black. " +
- "(Each {B} in the mana costs of permanents you control counts toward your devotion to black.) ";
- }
-
- private DragToTheUnderworldEffect(final DragToTheUnderworldEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- Mana mana = spellAbility.getManaCostsToPay().getMana();
- if (mana.getGeneric() == 0) {
- return false;
- }
- int count = DevotionCount.B.calculate(game, source, this);
- mana.setGeneric(Math.max(mana.getGeneric() - count, 0));
- spellAbility.getManaCostsToPay().load(mana.toString());
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- return abilityToModify instanceof SpellAbility
- && abilityToModify.getSourceId().equals(source.getSourceId());
- }
-
- @Override
- public DragToTheUnderworldEffect copy() {
- return new DragToTheUnderworldEffect(this);
- }
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/d/DragonEgg.java b/Mage.Sets/src/mage/cards/d/DragonEgg.java
index 7758179a672..defc2e95f8a 100644
--- a/Mage.Sets/src/mage/cards/d/DragonEgg.java
+++ b/Mage.Sets/src/mage/cards/d/DragonEgg.java
@@ -2,7 +2,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class DragonEgg extends CardImpl {
this.addAbility(DefenderAbility.getInstance());
// When Dragon Egg dies, create a 2/2 red Dragon creature token with flying. It has "{R}: This creature gets +1/+0 until end of turn".
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new DragonEggDragonToken()), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new DragonEggDragonToken()), false));
}
diff --git a/Mage.Sets/src/mage/cards/d/DragonGrip.java b/Mage.Sets/src/mage/cards/d/DragonGrip.java
index 9280f0c4a26..6637c97a21b 100644
--- a/Mage.Sets/src/mage/cards/d/DragonGrip.java
+++ b/Mage.Sets/src/mage/cards/d/DragonGrip.java
@@ -32,9 +32,9 @@ public final class DragonGrip extends CardImpl {
// Ferocious - If you control a creature with power 4 or greater, you may cast Dragon Grip as though it had flash.
AsThoughEffect effect = new CastAsThoughItHadFlashSourceEffect(Duration.EndOfGame);
- effect.setText("Ferocious — If you control a creature with power 4 or greater, you may cast Dragon Grip as though it had flash");
this.addAbility(new SimpleStaticAbility(Zone.ALL, new ConditionalAsThoughEffect(effect,
- FerociousCondition.instance))
+ FerociousCondition.instance).setText("Ferocious — If you control a creature with power 4 or greater, "
+ + "you may cast Dragon Grip as though it had flash"))
.addHint(FerociousHint.instance));
// Enchant creature
diff --git a/Mage.Sets/src/mage/cards/d/DragonlordDromoka.java b/Mage.Sets/src/mage/cards/d/DragonlordDromoka.java
index c24d6985bce..36d69f9f500 100644
--- a/Mage.Sets/src/mage/cards/d/DragonlordDromoka.java
+++ b/Mage.Sets/src/mage/cards/d/DragonlordDromoka.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.keyword.FlyingAbility;
@@ -30,7 +30,7 @@ public final class DragonlordDromoka extends CardImpl {
this.toughness = new MageInt(7);
// Dragonlord Dromoka can't be countered
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Flying
this.addAbility(FlyingAbility.getInstance());
// Lifelink
diff --git a/Mage.Sets/src/mage/cards/d/DragonlordSilumgar.java b/Mage.Sets/src/mage/cards/d/DragonlordSilumgar.java
index e4b4464ed33..ccf9f829139 100644
--- a/Mage.Sets/src/mage/cards/d/DragonlordSilumgar.java
+++ b/Mage.Sets/src/mage/cards/d/DragonlordSilumgar.java
@@ -1,4 +1,3 @@
-
package mage.cards.d;
import java.util.UUID;
@@ -16,9 +15,9 @@ import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.SuperType;
import mage.game.Game;
import mage.game.permanent.Permanent;
@@ -26,6 +25,7 @@ import mage.players.Player;
import mage.target.common.TargetCreatureOrPlaneswalker;
import mage.util.CardUtil;
import mage.util.GameLog;
+import mage.watchers.common.LostControlWatcher;
/**
*
@@ -50,6 +50,7 @@ public final class DragonlordSilumgar extends CardImpl {
// When Dragonlord Silumgar enters the battlefield, gain control of target creature or planeswalker for as long as you control Dragonlord Silumgar.
Ability ability = new EntersBattlefieldTriggeredAbility(new DragonlordSilumgarEffect(), false);
ability.addTarget(new TargetCreatureOrPlaneswalker());
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/d/DrainpipeVermin.java b/Mage.Sets/src/mage/cards/d/DrainpipeVermin.java
index 65991fd0e47..23be4152f1e 100644
--- a/Mage.Sets/src/mage/cards/d/DrainpipeVermin.java
+++ b/Mage.Sets/src/mage/cards/d/DrainpipeVermin.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
@@ -29,7 +29,7 @@ public final class DrainpipeVermin extends CardImpl {
this.toughness = new MageInt(1);
// When Drainpipe Vermin dies, you may pay {B}. If you do, target player discards a card.
- Ability ability = new DiesTriggeredAbility(new DoIfCostPaid(new DiscardTargetEffect(1), new ColoredManaCost(ColoredManaSymbol.B)), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DoIfCostPaid(new DiscardTargetEffect(1), new ColoredManaCost(ColoredManaSymbol.B)), false);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/d/DrasticRevelation.java b/Mage.Sets/src/mage/cards/d/DrasticRevelation.java
index d6391c7de8e..df6a334e9ae 100644
--- a/Mage.Sets/src/mage/cards/d/DrasticRevelation.java
+++ b/Mage.Sets/src/mage/cards/d/DrasticRevelation.java
@@ -2,10 +2,8 @@ package mage.cards.d;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
@@ -25,7 +23,7 @@ public final class DrasticRevelation extends CardImpl {
this.getSpellAbility().addEffect(new DrasticRevelationEffect());
}
- public DrasticRevelation(final DrasticRevelation card) {
+ private DrasticRevelation(final DrasticRevelation card) {
super(card);
}
@@ -42,24 +40,19 @@ class DrasticRevelationEffect extends OneShotEffect {
staticText = "Discard your hand. Draw seven cards, then discard three cards at random";
}
- DrasticRevelationEffect(final DrasticRevelationEffect effect) {
+ private DrasticRevelationEffect(final DrasticRevelationEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player you = game.getPlayer(source.getControllerId());
- if (you != null) {
- you.discard(you.getHand().size(), false, source, game);
- you.drawCards(7, source.getSourceId(), game);
- Cards hand = you.getHand();
- for (int i = 0; i < 3; i++) {
- Card card = hand.getRandom(game);
- if (card != null) {
- you.discard(card, source, game);
- }
- }
+ if (you == null) {
+ return false;
}
+ you.discard(you.getHand(), source, game);
+ you.drawCards(7, source.getSourceId(), game);
+ you.discard(3, true, source, game);
return false;
}
@@ -67,4 +60,4 @@ class DrasticRevelationEffect extends OneShotEffect {
public DrasticRevelationEffect copy() {
return new DrasticRevelationEffect(this);
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/d/DreadCacodemon.java b/Mage.Sets/src/mage/cards/d/DreadCacodemon.java
index cb2b37606c2..ab005dde426 100644
--- a/Mage.Sets/src/mage/cards/d/DreadCacodemon.java
+++ b/Mage.Sets/src/mage/cards/d/DreadCacodemon.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.effects.common.TapAllEffect;
@@ -44,7 +44,7 @@ public final class DreadCacodemon extends CardImpl {
// if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control.
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(opponentsCreatures, false));
ability.addEffect(new TapAllEffect(otherCreaturesYouControl));
- this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourceCondition.instance,
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourcePermanentCondition.instance,
"When {this} enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."), new CastFromHandWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/d/DreadSpecter.java b/Mage.Sets/src/mage/cards/d/DreadSpecter.java
index c3cb1d8e77d..50e5aca6756 100644
--- a/Mage.Sets/src/mage/cards/d/DreadSpecter.java
+++ b/Mage.Sets/src/mage/cards/d/DreadSpecter.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -38,7 +38,7 @@ public final class DreadSpecter extends CardImpl {
// Whenever Dread Specter blocks or becomes blocked by a nonblack creature, destroy that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true);
effect.setText("destroy that creature at end of combat");
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, filter, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, filter, false));
}
public DreadSpecter(final DreadSpecter card) {
diff --git a/Mage.Sets/src/mage/cards/d/DreadSummons.java b/Mage.Sets/src/mage/cards/d/DreadSummons.java
index 0367d259c09..8a2812efbfa 100644
--- a/Mage.Sets/src/mage/cards/d/DreadSummons.java
+++ b/Mage.Sets/src/mage/cards/d/DreadSummons.java
@@ -1,23 +1,22 @@
-
package mage.cards.d;
-import java.util.Set;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.CreateTokenEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
+import mage.game.permanent.token.Token;
import mage.game.permanent.token.ZombieToken;
import mage.players.Player;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class DreadSummons extends CardImpl {
@@ -26,10 +25,10 @@ public final class DreadSummons extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}");
// Each player puts the top X cards of their library into their graveyard. For each creature card put into a graveyard this way, you create a tapped 2/2 black Zombie creature token.
- getSpellAbility().addEffect(new DreadSummonsEffect());
+ this.getSpellAbility().addEffect(new DreadSummonsEffect());
}
- public DreadSummons(final DreadSummons card) {
+ private DreadSummons(final DreadSummons card) {
super(card);
}
@@ -41,12 +40,15 @@ public final class DreadSummons extends CardImpl {
class DreadSummonsEffect extends OneShotEffect {
- public DreadSummonsEffect() {
+ private static final Token token = new ZombieToken();
+
+ DreadSummonsEffect() {
super(Outcome.PutCreatureInPlay);
- this.staticText = "Each player puts the top X cards of their library into their graveyard. For each creature card put into a graveyard this way, you create a tapped 2/2 black Zombie creature token";
+ this.staticText = "each player mills X cards. For each creature card put into a graveyard this way, " +
+ "you create a tapped 2/2 black Zombie creature token";
}
- public DreadSummonsEffect(final DreadSummonsEffect effect) {
+ private DreadSummonsEffect(final DreadSummonsEffect effect) {
super(effect);
}
@@ -57,28 +59,24 @@ class DreadSummonsEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- int numberOfCards = source.getManaCostsToPay().getX();
- if (numberOfCards > 0) {
- int numberOfCreatureCards = 0;
- for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Set movedCards = player.moveCardsToGraveyardWithInfo(player.getLibrary().getTopCards(game, numberOfCards), source, game, Zone.LIBRARY);
- for (Card card : movedCards) {
- if (card.isCreature()) {
- numberOfCreatureCards++;
- }
- }
- }
- }
- if (numberOfCreatureCards > 0) {
- return new CreateTokenEffect(new ZombieToken(), numberOfCreatureCards, true, false).apply(game, source);
- }
+ int creatureCount = 0;
+ for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
}
- return true;
+ creatureCount += player
+ .millCards(source.getManaCostsToPay().getX(), source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(card -> game.getState().getZone(card.getId()) == Zone.GRAVEYARD)
+ .filter(MageObject::isCreature)
+ .count();
}
- return false;
+ if (creatureCount > 0) {
+ token.putOntoBattlefield(creatureCount, game, source.getSourceId(), source.getControllerId());
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DreadhordeButcher.java b/Mage.Sets/src/mage/cards/d/DreadhordeButcher.java
index 6e99a3b55f8..bd8699396c0 100644
--- a/Mage.Sets/src/mage/cards/d/DreadhordeButcher.java
+++ b/Mage.Sets/src/mage/cards/d/DreadhordeButcher.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@@ -39,7 +39,7 @@ public final class DreadhordeButcher extends CardImpl {
), false).setOrPlaneswalker(true));
// When Dreadhorde Butcher dies, it deals damage equal to its power to any target.
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(
new SourcePermanentPowerCount()
).setText("it deals damage equal to its power to any target"));
ability.addTarget(new TargetAnyTarget());
diff --git a/Mage.Sets/src/mage/cards/d/DreamEater.java b/Mage.Sets/src/mage/cards/d/DreamEater.java
index de2fe374169..5c728566480 100644
--- a/Mage.Sets/src/mage/cards/d/DreamEater.java
+++ b/Mage.Sets/src/mage/cards/d/DreamEater.java
@@ -1,30 +1,28 @@
package mage.cards.d;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.abilities.effects.keyword.SurveilEffect;
-import mage.constants.SubType;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterNonlandPermanent;
import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.target.TargetPermanent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class DreamEater extends CardImpl {
@@ -44,14 +42,12 @@ public final class DreamEater extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Dream Eater enters the battlefield, surveil 4. When you do, you may return target nonland permanent an opponent controls to its owner's hand.
- Ability ability = new EntersBattlefieldTriggeredAbility(
- new SurveilEffect(4)
- );
- ability.addEffect(new DreamEaterCreateReflexiveTriggerEffect());
+ Ability ability = new EntersBattlefieldTriggeredAbility(new SurveilEffect(4));
+ ability.addEffect(new DreamEaterEffect());
this.addAbility(ability);
}
- public DreamEater(final DreamEater card) {
+ private DreamEater(final DreamEater card) {
super(card);
}
@@ -61,31 +57,7 @@ public final class DreamEater extends CardImpl {
}
}
-class DreamEaterCreateReflexiveTriggerEffect extends OneShotEffect {
-
- public DreamEaterCreateReflexiveTriggerEffect() {
- super(Outcome.Benefit);
- this.staticText = "When you do, you may return target "
- + "nonland permanent an opponent controls to its owner's hand.";
- }
-
- public DreamEaterCreateReflexiveTriggerEffect(final DreamEaterCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public DreamEaterCreateReflexiveTriggerEffect copy() {
- return new DreamEaterCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new DreamEaterReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class DreamEaterReflexiveTriggeredAbility extends DelayedTriggeredAbility {
+class DreamEaterEffect extends OneShotEffect {
private static final FilterPermanent filter
= new FilterNonlandPermanent("nonland permanent an opponent controls");
@@ -94,35 +66,29 @@ class DreamEaterReflexiveTriggeredAbility extends DelayedTriggeredAbility {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
- public DreamEaterReflexiveTriggeredAbility() {
- super(new ReturnToHandTargetEffect());
- this.addTarget(new TargetPermanent(filter));
- this.optional = true;
+ DreamEaterEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "When you do, you may return target "
+ + "nonland permanent an opponent controls to its owner's hand.";
}
- public DreamEaterReflexiveTriggeredAbility(final DreamEaterReflexiveTriggeredAbility ability) {
- super(ability);
+ private DreamEaterEffect(final DreamEaterEffect effect) {
+ super(effect);
}
@Override
- public DreamEaterReflexiveTriggeredAbility copy() {
- return new DreamEaterReflexiveTriggeredAbility(this);
+ public DreamEaterEffect copy() {
+ return new DreamEaterEffect(this);
}
@Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When you surveil 4, you may return target nonland permanent "
- + "an opponent controls to its owner's hand.";
+ public boolean apply(Game game, Ability source) {
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new ReturnToHandTargetEffect(), true,
+ "you may return target nonland permanent an opponent controls to its owner's hand"
+ );
+ ability.addTarget(new TargetPermanent(filter));
+ game.fireReflexiveTriggeredAbility(ability, source);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/d/DreamLeash.java b/Mage.Sets/src/mage/cards/d/DreamLeash.java
index bccc18cffd5..a68a361904d 100644
--- a/Mage.Sets/src/mage/cards/d/DreamLeash.java
+++ b/Mage.Sets/src/mage/cards/d/DreamLeash.java
@@ -1,7 +1,6 @@
package mage.cards.d;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AttachEffect;
@@ -10,13 +9,16 @@ import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
+import java.util.UUID;
+
/**
*
* @author maxlebedev
@@ -52,14 +54,30 @@ public final class DreamLeash extends CardImpl {
class DreamLeashTarget extends TargetPermanent {
+ DreamLeashTarget() {}
+
+ private DreamLeashTarget(DreamLeashTarget target) {
+ super(target);
+ }
+
+ @Override
+ public DreamLeashTarget copy() {
+ return new DreamLeashTarget(this);
+ }
+
@Override
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
-
- if(super.canTarget(controllerId, id, source, game)){
+ if (super.canTarget(controllerId, id, source, game)) {
Permanent permanent = game.getPermanent(id);
return permanent.isTapped();
}
return false;
}
+ // See ruling: https://www.mtgsalvation.com/forums/magic-fundamentals/magic-rulings/magic-rulings-archives/253345-dream-leash
+ @Override
+ public boolean stillLegalTarget(UUID id, Ability source, Game game) {
+ Permanent permanent = game.getPermanent(id);
+ return permanent != null && StaticFilters.FILTER_PERMANENT.match(permanent, game);
+ }
}
diff --git a/Mage.Sets/src/mage/cards/d/DreambornMuse.java b/Mage.Sets/src/mage/cards/d/DreambornMuse.java
index 169107a55c2..1ea48de2e1e 100644
--- a/Mage.Sets/src/mage/cards/d/DreambornMuse.java
+++ b/Mage.Sets/src/mage/cards/d/DreambornMuse.java
@@ -1,7 +1,5 @@
-
package mage.cards.d;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.dynamicvalue.common.CardsInTargetPlayerHandCount;
@@ -12,26 +10,26 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
+import java.util.UUID;
+
/**
- *
* @author cbrianhill
*/
public final class DreambornMuse extends CardImpl {
public DreambornMuse(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}");
this.subtype.add(SubType.SPIRIT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
-
+
// At the beginning of each player's upkeep, that player puts the top X cards of their library into their graveyard, where X is the number of cards in their hand.
PutLibraryIntoGraveTargetEffect effect = new PutLibraryIntoGraveTargetEffect(CardsInTargetPlayerHandCount.instance);
- effect.setText("that player puts the top X cards of their library into their graveyard, where X is the number of cards in their hand.");
+ effect.setText("that player mills X cards, where X is the number of cards in their hand");
this.addAbility(new BeginningOfUpkeepTriggeredAbility(effect, TargetController.ANY, false));
-
}
- public DreambornMuse(final DreambornMuse card) {
+ private DreambornMuse(final DreambornMuse card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/d/Drelnoch.java b/Mage.Sets/src/mage/cards/d/Drelnoch.java
index 21b7ae3e2d9..c82c191d869 100644
--- a/Mage.Sets/src/mage/cards/d/Drelnoch.java
+++ b/Mage.Sets/src/mage/cards/d/Drelnoch.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class Drelnoch extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Drelnoch becomes blocked, you may draw two cards.
- this.addAbility(new BecomesBlockedTriggeredAbility(new DrawCardSourceControllerEffect(2), true));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new DrawCardSourceControllerEffect(2), true));
}
public Drelnoch(final Drelnoch card) {
diff --git a/Mage.Sets/src/mage/cards/d/DrippingTongueZubera.java b/Mage.Sets/src/mage/cards/d/DrippingTongueZubera.java
index ed36a32932b..ba93772a8b8 100644
--- a/Mage.Sets/src/mage/cards/d/DrippingTongueZubera.java
+++ b/Mage.Sets/src/mage/cards/d/DrippingTongueZubera.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.ZuberasDiedDynamicValue;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class DrippingTongueZubera extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(2);
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SpiritToken(), ZuberasDiedDynamicValue.instance), false), new ZuberasDiedWatcher());
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new SpiritToken(), ZuberasDiedDynamicValue.instance), false), new ZuberasDiedWatcher());
}
public DrippingTongueZubera (final DrippingTongueZubera card) {
diff --git a/Mage.Sets/src/mage/cards/d/DriverOfTheDead.java b/Mage.Sets/src/mage/cards/d/DriverOfTheDead.java
index 67b28222df7..debff34c885 100644
--- a/Mage.Sets/src/mage/cards/d/DriverOfTheDead.java
+++ b/Mage.Sets/src/mage/cards/d/DriverOfTheDead.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -21,7 +21,7 @@ import mage.target.common.TargetCardInYourGraveyard;
*/
public final class DriverOfTheDead extends CardImpl {
- private static final FilterCreatureCard filter = new FilterCreatureCard("creature card with converted mana cost 2 or less from your graveyard to the battlefield");
+ private static final FilterCreatureCard filter = new FilterCreatureCard("creature card with converted mana cost 2 or less from your graveyard");
static {
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 3));
@@ -35,7 +35,7 @@ public final class DriverOfTheDead extends CardImpl {
this.toughness = new MageInt(2);
// When Driver of the Dead dies, return target creature card with converted mana cost 2 or less from your graveyard to the battlefield.
- Ability ability = new DiesTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false);
Target target = new TargetCardInYourGraveyard(filter);
ability.addTarget(target);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/d/DroidCommando.java b/Mage.Sets/src/mage/cards/d/DroidCommando.java
index 981a61d28a1..2c86fd7f721 100644
--- a/Mage.Sets/src/mage/cards/d/DroidCommando.java
+++ b/Mage.Sets/src/mage/cards/d/DroidCommando.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.keyword.RepairAbility;
@@ -27,7 +27,7 @@ public final class DroidCommando extends CardImpl {
this.toughness = new MageInt(2);
// When Droid Commando dies, target player loses 2 life and you gain 2 life.
- Ability ability = new DiesTriggeredAbility(new LoseLifeTargetEffect(2));
+ Ability ability = new DiesSourceTriggeredAbility(new LoseLifeTargetEffect(2));
ability.addEffect(new GainLifeEffect(2));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/d/Dromosaur.java b/Mage.Sets/src/mage/cards/d/Dromosaur.java
index edc3d676905..99cac6e8ce5 100644
--- a/Mage.Sets/src/mage/cards/d/Dromosaur.java
+++ b/Mage.Sets/src/mage/cards/d/Dromosaur.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class Dromosaur extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Dromosaur blocks or becomes blocked by a creature, it gets +2/-2 until end of turn.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(2, -2, Duration.EndOfTurn), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(2, -2, Duration.EndOfTurn), false));
}
public Dromosaur(final Dromosaur card) {
diff --git a/Mage.Sets/src/mage/cards/d/DrossRipper.java b/Mage.Sets/src/mage/cards/d/DrossRipper.java
index d9867e585fc..836f431631d 100644
--- a/Mage.Sets/src/mage/cards/d/DrossRipper.java
+++ b/Mage.Sets/src/mage/cards/d/DrossRipper.java
@@ -22,7 +22,7 @@ public final class DrossRipper extends CardImpl {
public DrossRipper (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{2}{B}")));
diff --git a/Mage.Sets/src/mage/cards/d/DrownInFilth.java b/Mage.Sets/src/mage/cards/d/DrownInFilth.java
index c9befad3dd2..55138284192 100644
--- a/Mage.Sets/src/mage/cards/d/DrownInFilth.java
+++ b/Mage.Sets/src/mage/cards/d/DrownInFilth.java
@@ -28,7 +28,7 @@ public final class DrownInFilth extends CardImpl {
// Choose target creature. Put the top four cards of your library into your graveyard, then that creature gets -1/-1 until end of turn for each land card in your graveyard.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
Effect effect = new PutTopCardOfLibraryIntoGraveControllerEffect(4);
- effect.setText("Choose target creature. Put the top four cards of your library into your graveyard");
+ effect.setText("Choose target creature. Mill four cards");
this.getSpellAbility().addEffect(effect);
DynamicValue landCards = new SignInversionDynamicValue(new CardsInControllerGraveyardCount(new FilterLandCard()));
this.getSpellAbility().addEffect(new BoostTargetEffect(landCards, landCards, Duration.EndOfTurn));
diff --git a/Mage.Sets/src/mage/cards/d/DrowsingTyrannodon.java b/Mage.Sets/src/mage/cards/d/DrowsingTyrannodon.java
new file mode 100644
index 00000000000..0635f947dd8
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/d/DrowsingTyrannodon.java
@@ -0,0 +1,49 @@
+package mage.cards.d;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.FerociousCondition;
+import mage.abilities.decorator.ConditionalAsThoughEffect;
+import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect;
+import mage.abilities.keyword.DefenderAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class DrowsingTyrannodon extends CardImpl {
+
+ public DrowsingTyrannodon(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
+
+ this.subtype.add(SubType.DINOSAUR);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Defender
+ this.addAbility(DefenderAbility.getInstance());
+
+ // As long as you control a creature with power 4 or greater, Drowsing Tyrannodon can attack as though it didn't have defender.
+ this.addAbility(new SimpleStaticAbility(new ConditionalAsThoughEffect(
+ new CanAttackAsThoughItDidntHaveDefenderSourceEffect(
+ Duration.WhileOnBattlefield
+ ), FerociousCondition.instance
+ ).setText("as long as you control a creature with power 4 or greater, " +
+ "{this} can attack as though it didn't have defender")));
+ }
+
+ private DrowsingTyrannodon(final DrowsingTyrannodon card) {
+ super(card);
+ }
+
+ @Override
+ public DrowsingTyrannodon copy() {
+ return new DrowsingTyrannodon(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/d/DuskFeaster.java b/Mage.Sets/src/mage/cards/d/DuskFeaster.java
index 96c7fbaea3c..40750273978 100644
--- a/Mage.Sets/src/mage/cards/d/DuskFeaster.java
+++ b/Mage.Sets/src/mage/cards/d/DuskFeaster.java
@@ -1,36 +1,38 @@
-
package mage.cards.d;
-import java.util.EnumSet;
-import java.util.UUID;
import mage.MageInt;
-import mage.Mana;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.condition.common.DeliriumCondition;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.common.DeliriumHint;
import mage.abilities.keyword.FlyingAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.players.Player;
+import mage.constants.AbilityWord;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
+
+import java.util.UUID;
/**
- *
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public final class DuskFeaster extends CardImpl {
public DuskFeaster(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}");
this.subtype.add(SubType.VAMPIRE);
this.power = new MageInt(4);
this.toughness = new MageInt(5);
- // Delirium — Dusk Feaster costs {2} less to cast if there are four or more card types among cards in your graveyard.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new DuskFeasterCostReductionEffect()));
+ // Delirium — This spell costs {2} less to cast if there are four or more card types among cards in your graveyard.
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(2, DeliriumCondition.instance));
+ ability.setRuleAtTheTop(true);
+ ability.setAbilityWord(AbilityWord.DELIRIUM);
+ ability.addHint(DeliriumHint.instance);
+ this.addAbility(ability);
// Flying
this.addAbility(FlyingAbility.getInstance());
@@ -44,56 +46,4 @@ public final class DuskFeaster extends CardImpl {
public DuskFeaster copy() {
return new DuskFeaster(this);
}
-}
-
-class DuskFeasterCostReductionEffect extends CostModificationEffectImpl {
-
- DuskFeasterCostReductionEffect() {
- super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "Delirium — {this} costs {2} less to cast if there are four or more card types among cards in your graveyard";
- }
-
- DuskFeasterCostReductionEffect(final DuskFeasterCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- Mana mana = spellAbility.getManaCostsToPay().getMana();
- if (mana.getGeneric() > 0) {
- int newCount = mana.getGeneric() - 2;
- if (newCount < 0) {
- newCount = 0;
- }
- mana.setGeneric(newCount);
- spellAbility.getManaCostsToPay().load(mana.toString());
- return true;
- }
- return false;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
-
- boolean hasDelirium = false;
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- EnumSet foundCardTypes = EnumSet.noneOf(CardType.class);
- for (Card card : controller.getGraveyard().getCards(game)) {
- foundCardTypes.addAll(card.getCardType());
- }
- int number = foundCardTypes.size();
- hasDelirium = number > 3;
- }
-
- return abilityToModify.getSourceId().equals(source.getSourceId())
- && (abilityToModify instanceof SpellAbility)
- && hasDelirium;
- }
-
- @Override
- public DuskFeasterCostReductionEffect copy() {
- return new DuskFeasterCostReductionEffect(this);
- }
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/d/DuskUrchins.java b/Mage.Sets/src/mage/cards/d/DuskUrchins.java
index 81047b88e24..728636cabf8 100644
--- a/Mage.Sets/src/mage/cards/d/DuskUrchins.java
+++ b/Mage.Sets/src/mage/cards/d/DuskUrchins.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.AttacksOrBlocksTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@@ -31,7 +31,7 @@ public final class DuskUrchins extends CardImpl {
this.addAbility(new AttacksOrBlocksTriggeredAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance()), false));
// When Dusk Urchins dies, draw a card for each -1/-1 counter on it.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.M1M1))));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.M1M1))));
}
diff --git a/Mage.Sets/src/mage/cards/d/Duskworker.java b/Mage.Sets/src/mage/cards/d/Duskworker.java
index 4dbd6d67139..dade86eb09c 100644
--- a/Mage.Sets/src/mage/cards/d/Duskworker.java
+++ b/Mage.Sets/src/mage/cards/d/Duskworker.java
@@ -3,7 +3,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.RegenerateSourceEffect;
@@ -26,7 +26,7 @@ public final class Duskworker extends CardImpl {
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
- this.addAbility(new BecomesBlockedTriggeredAbility(new RegenerateSourceEffect(), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new RegenerateSourceEffect(), false));
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new GenericManaCost(3)));
}
diff --git a/Mage.Sets/src/mage/cards/d/DutifulAttendant.java b/Mage.Sets/src/mage/cards/d/DutifulAttendant.java
index 8262b7050cc..46d73e16dcc 100644
--- a/Mage.Sets/src/mage/cards/d/DutifulAttendant.java
+++ b/Mage.Sets/src/mage/cards/d/DutifulAttendant.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -34,7 +34,7 @@ public final class DutifulAttendant extends CardImpl {
this.toughness = new MageInt(2);
// When Dutiful Ateendant dies, return another target creature card from your graveyard to your hand.
- Ability ability = new DiesTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), false);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/d/DwarvenBerserker.java b/Mage.Sets/src/mage/cards/d/DwarvenBerserker.java
index 998ff1a5093..21fe183f8cc 100644
--- a/Mage.Sets/src/mage/cards/d/DwarvenBerserker.java
+++ b/Mage.Sets/src/mage/cards/d/DwarvenBerserker.java
@@ -4,7 +4,7 @@ package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
@@ -31,7 +31,7 @@ public final class DwarvenBerserker extends CardImpl {
// Whenever Dwarven Berserker becomes blocked, it gets +3/+0 and gains trample until end of turn.
Effect effect = new BoostSourceEffect(3, 0, Duration.EndOfTurn);
effect.setText("it gets +3/+0");
- Ability ability = new BecomesBlockedTriggeredAbility(effect, false);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(effect, false);
effect = new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn);
effect.setText("and gains trample until end of turn");
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/d/DwellOnThePast.java b/Mage.Sets/src/mage/cards/d/DwellOnThePast.java
index efa62fddb7e..f57594e87ae 100644
--- a/Mage.Sets/src/mage/cards/d/DwellOnThePast.java
+++ b/Mage.Sets/src/mage/cards/d/DwellOnThePast.java
@@ -8,6 +8,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -61,24 +62,9 @@ class DwellOnThePastEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getFirstTarget());
- if (player != null) {
- List targets = source.getTargets().get(1).getTargets();
- boolean shuffle = false;
- for (UUID targetId : targets) {
- Card card = game.getCard(targetId);
- if (card != null) {
- if (player.getGraveyard().contains(card.getId())) {
- player.getGraveyard().remove(card);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- shuffle = true;
- }
- }
- }
- if (shuffle) {
- player.shuffleLibrary(source, game);
- }
- return true;
+ Player controller = game.getPlayer(source.getFirstTarget());
+ if (controller != null) {
+ return controller.shuffleCardsToLibrary(new CardsImpl(source.getTargets().get(1).getTargets()), game, source);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/e/EbonyCharm.java b/Mage.Sets/src/mage/cards/e/EbonyCharm.java
index f3ed1de7c0b..b6f92454712 100644
--- a/Mage.Sets/src/mage/cards/e/EbonyCharm.java
+++ b/Mage.Sets/src/mage/cards/e/EbonyCharm.java
@@ -1,26 +1,23 @@
package mage.cards.e;
-import java.util.UUID;
-import mage.abilities.Ability;
import mage.abilities.Mode;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.ExileTargetEffect;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.FearAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.filter.FilterCard;
-import mage.game.Game;
-import mage.players.Player;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInASingleGraveyard;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class EbonyCharm extends CardImpl {
@@ -29,13 +26,14 @@ public final class EbonyCharm extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
// Choose one - Target opponent loses 1 life and you gain 1 life;
- this.getSpellAbility().addEffect(new EbonyCharmDrainEffect());
+ this.getSpellAbility().addEffect(new LoseLifeTargetEffect(1));
+ this.getSpellAbility().addEffect(new GainLifeEffect(1).concatBy("and"));
this.getSpellAbility().addTarget(new TargetOpponent());
// or exile up to three target cards from a single graveyard;
Mode mode = new Mode();
- mode.addEffect(new EbonyCharmExileEffect());
- mode.addTarget((new TargetCardInASingleGraveyard(0, 3, new FilterCard("up to three target cards from a single graveyard"))));
+ mode.addEffect(new ExileTargetEffect());
+ mode.addTarget((new TargetCardInASingleGraveyard(0, 3, StaticFilters.FILTER_CARD_CARDS)));
this.getSpellAbility().addMode(mode);
// or target creature gains fear until end of turn.
@@ -54,62 +52,3 @@ public final class EbonyCharm extends CardImpl {
return new EbonyCharm(this);
}
}
-
-class EbonyCharmDrainEffect extends OneShotEffect {
-
- EbonyCharmDrainEffect() {
- super(Outcome.Damage);
- staticText = "target opponent loses 1 life and you gain 1 life";
- }
-
- EbonyCharmDrainEffect(final EbonyCharmDrainEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player targetOpponent = game.getPlayer(source.getFirstTarget());
- Player controller = game.getPlayer(source.getControllerId());
- if (targetOpponent != null
- && controller != null) {
- targetOpponent.loseLife(1, game, false);
- controller.gainLife(1, game, source);
- return true;
- }
- return false;
- }
-
- @Override
- public EbonyCharmDrainEffect copy() {
- return new EbonyCharmDrainEffect(this);
- }
-
-}
-
-class EbonyCharmExileEffect extends OneShotEffect {
-
- public EbonyCharmExileEffect() {
- super(Outcome.Exile);
- this.staticText = "Exile up to three target cards from a single graveyard";
- }
-
- public EbonyCharmExileEffect(final EbonyCharmExileEffect effect) {
- super(effect);
- }
-
- @Override
- public EbonyCharmExileEffect copy() {
- return new EbonyCharmExileEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (UUID targetID : source.getTargets().get(0).getTargets()) {
- Card card = game.getCard(targetID);
- if (card != null) {
- card.moveToExile(null, "", source.getSourceId(), game);
- }
- }
- return true;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/e/ElderCathar.java b/Mage.Sets/src/mage/cards/e/ElderCathar.java
index 4a68c92c63b..e285ed05aa6 100644
--- a/Mage.Sets/src/mage/cards/e/ElderCathar.java
+++ b/Mage.Sets/src/mage/cards/e/ElderCathar.java
@@ -4,7 +4,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -31,7 +31,7 @@ public final class ElderCathar extends CardImpl {
this.toughness = new MageInt(2);
// When Elder Cathar dies, put a +1/+1 counter on target creature you control. If that creature is a Human, put two +1/+1 counters on it instead.
- Ability ability = new DiesTriggeredAbility(new ElderCatharAddCountersTargetEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new ElderCatharAddCountersTargetEffect(), false);
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/e/ElderGargaroth.java b/Mage.Sets/src/mage/cards/e/ElderGargaroth.java
new file mode 100644
index 00000000000..37221728463
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/e/ElderGargaroth.java
@@ -0,0 +1,62 @@
+package mage.cards.e;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.common.AttacksOrBlocksTriggeredAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.keyword.ReachAbility;
+import mage.abilities.keyword.TrampleAbility;
+import mage.abilities.keyword.VigilanceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.game.permanent.token.BeastToken;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ElderGargaroth extends CardImpl {
+
+ public ElderGargaroth(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
+
+ this.subtype.add(SubType.BEAST);
+ this.power = new MageInt(6);
+ this.toughness = new MageInt(6);
+
+ // Vigilance
+ this.addAbility(VigilanceAbility.getInstance());
+
+ // Reach
+ this.addAbility(ReachAbility.getInstance());
+
+ // Trample
+ this.addAbility(TrampleAbility.getInstance());
+
+ // Whenever Elder Gargaroth attacks or blocks, choose one —
+ // • Create a 3/3 green Beast creature token.
+ Ability ability = new AttacksOrBlocksTriggeredAbility(new CreateTokenEffect(new BeastToken()), false);
+
+ // • You gain 3 life.
+ ability.addMode(new Mode(new GainLifeEffect(3)));
+
+ // • Draw a card.
+ ability.addMode(new Mode(new DrawCardSourceControllerEffect(1)));
+ this.addAbility(ability);
+ }
+
+ private ElderGargaroth(final ElderGargaroth card) {
+ super(card);
+ }
+
+ @Override
+ public ElderGargaroth copy() {
+ return new ElderGargaroth(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/e/ElderwoodScion.java b/Mage.Sets/src/mage/cards/e/ElderwoodScion.java
index 778ffb55e52..eceff73b4f2 100644
--- a/Mage.Sets/src/mage/cards/e/ElderwoodScion.java
+++ b/Mage.Sets/src/mage/cards/e/ElderwoodScion.java
@@ -1,24 +1,21 @@
-
package mage.cards.e;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.target.Target;
-import mage.util.CardUtil;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class ElderwoodScion extends CardImpl {
@@ -32,12 +29,19 @@ public final class ElderwoodScion extends CardImpl {
// Trample
this.addAbility(TrampleAbility.getInstance());
+
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
+
// Spells you cast that target Elderwood Scion cost {2} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ElderwoodScionCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(-2, new FilterCard("Spells"), TargetController.YOU))
+ );
+
// Spells your opponents cast that target Elderwood Scion cost {2} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ElderwoodScionCostReductionEffect2()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(2, new FilterCard("Spells"), TargetController.OPPONENT))
+ );
}
public ElderwoodScion(final ElderwoodScion card) {
@@ -49,92 +53,3 @@ public final class ElderwoodScion extends CardImpl {
return new ElderwoodScion(this);
}
}
-
-class ElderwoodScionCostReductionEffect extends CostModificationEffectImpl {
-
- private static final String effectText = "Spells you cast that target {this} cost {2} less to cast";
-
- ElderwoodScionCostReductionEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = effectText;
- }
-
- ElderwoodScionCostReductionEffect(ElderwoodScionCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, 2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- if (abilityToModify.isControlledBy(source.getControllerId())) {
- for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
- Mode mode = abilityToModify.getModes().get(modeId);
- for (Target target : mode.getTargets()) {
- for (UUID targetUUID : target.getTargets()) {
- if (targetUUID.equals(source.getSourceId())) {
- return true;
- }
- }
- }
- }
- }
- }
- return false;
- }
-
- @Override
- public ElderwoodScionCostReductionEffect copy() {
- return new ElderwoodScionCostReductionEffect(this);
- }
-
-}
-
-class ElderwoodScionCostReductionEffect2 extends CostModificationEffectImpl {
-
- private static final String effectText = "Spells your opponents cast that target {this} cost {2} more to cast";
-
- ElderwoodScionCostReductionEffect2() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = effectText;
- }
-
- ElderwoodScionCostReductionEffect2(ElderwoodScionCostReductionEffect2 effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.increaseCost(spellAbility, 2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- for (Target target : abilityToModify.getTargets()) {
- for (UUID targetUUID : target.getTargets()) {
- if (targetUUID.equals(source.getSourceId())) {
- return true;
- }
- }
- }
- }
- }
- return false;
- }
-
- @Override
- public ElderwoodScionCostReductionEffect2 copy() {
- return new ElderwoodScionCostReductionEffect2(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/e/ElementalAppeal.java b/Mage.Sets/src/mage/cards/e/ElementalAppeal.java
index d7346d75ceb..bfffb2e6b21 100644
--- a/Mage.Sets/src/mage/cards/e/ElementalAppeal.java
+++ b/Mage.Sets/src/mage/cards/e/ElementalAppeal.java
@@ -1,9 +1,5 @@
-
package mage.cards.e;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.condition.common.KickedCondition;
@@ -21,10 +17,13 @@ import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.game.Game;
-import mage.game.permanent.token.ElementalAppealElementalToken;
+import mage.game.permanent.token.RedElementalWithTrampleAndHaste;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
/**
- *
* @author North
*/
public final class ElementalAppeal extends CardImpl {
@@ -69,7 +68,7 @@ class ElementalAppealEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- CreateTokenEffect effect = new CreateTokenEffect(new ElementalAppealElementalToken());
+ CreateTokenEffect effect = new CreateTokenEffect(new RedElementalWithTrampleAndHaste());
if (effect.apply(game, source)) {
effect.exileTokensCreatedAtNextEndStep(game, source);
if (KickedCondition.instance.apply(game, source)) {
diff --git a/Mage.Sets/src/mage/cards/e/ElendaTheDuskRose.java b/Mage.Sets/src/mage/cards/e/ElendaTheDuskRose.java
index f6caea4489d..69b841e09c2 100644
--- a/Mage.Sets/src/mage/cards/e/ElendaTheDuskRose.java
+++ b/Mage.Sets/src/mage/cards/e/ElendaTheDuskRose.java
@@ -4,7 +4,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DiesCreatureTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@@ -38,7 +38,7 @@ public final class ElendaTheDuskRose extends CardImpl {
this.addAbility(new DiesCreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false, true));
// When Elenda dies, create X 1/1 white Vampire creature tokens with lifelink, where X is Elenda's power.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new IxalanVampireToken(), new SourcePermanentPowerCount())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new IxalanVampireToken(), new SourcePermanentPowerCount())));
}
public ElendaTheDuskRose(final ElendaTheDuskRose card) {
diff --git a/Mage.Sets/src/mage/cards/e/ElgaudInquisitor.java b/Mage.Sets/src/mage/cards/e/ElgaudInquisitor.java
index 97f1e20c73c..dae094242e3 100644
--- a/Mage.Sets/src/mage/cards/e/ElgaudInquisitor.java
+++ b/Mage.Sets/src/mage/cards/e/ElgaudInquisitor.java
@@ -3,7 +3,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class ElgaudInquisitor extends CardImpl {
this.addAbility(LifelinkAbility.getInstance());
// When Elgaud Inquisitor dies, create a 1/1 white Spirit creature token with flying.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken())));
}
public ElgaudInquisitor(final ElgaudInquisitor card) {
diff --git a/Mage.Sets/src/mage/cards/e/Eliminate.java b/Mage.Sets/src/mage/cards/e/Eliminate.java
new file mode 100644
index 00000000000..39423122e38
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/e/Eliminate.java
@@ -0,0 +1,44 @@
+package mage.cards.e;
+
+import mage.abilities.effects.common.DestroyTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.ComparisonType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
+import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class Eliminate extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent(
+ "creature or planeswalker with converted mana cost 3 or less"
+ );
+
+ static {
+ filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4));
+ }
+
+ public Eliminate(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}");
+
+ // Destroy target creature or planeswalker with converted mana cost 3 or less.
+ this.getSpellAbility().addEffect(new DestroyTargetEffect());
+ this.getSpellAbility().addTarget(new TargetPermanent(filter));
+ }
+
+ private Eliminate(final Eliminate card) {
+ super(card);
+ }
+
+ @Override
+ public Eliminate copy() {
+ return new Eliminate(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/e/EliteScaleguard.java b/Mage.Sets/src/mage/cards/e/EliteScaleguard.java
index b2c5911d85b..02a7c48ef02 100644
--- a/Mage.Sets/src/mage/cards/e/EliteScaleguard.java
+++ b/Mage.Sets/src/mage/cards/e/EliteScaleguard.java
@@ -1,10 +1,11 @@
-
package mage.cards.e;
+import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.effects.keyword.BolsterEffect;
import mage.cards.CardImpl;
@@ -14,13 +15,12 @@ import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.filter.predicate.permanent.CounterPredicate;
-import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate;
import mage.game.Game;
-import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
-
-import java.util.UUID;
+import mage.target.targetadjustment.TargetAdjuster;
+import mage.target.targetpointer.FirstTargetPointer;
/**
* @author emerald000
@@ -28,11 +28,9 @@ import java.util.UUID;
public final class EliteScaleguard extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control with a +1/+1 counter on it");
- private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature defending player controls");
static {
filter.add(new CounterPredicate(CounterType.P1P1));
- filter2.add(DefendingPlayerControlsPredicate.instance);
}
public EliteScaleguard(UUID ownerId, CardSetInfo setInfo) {
@@ -46,8 +44,9 @@ public final class EliteScaleguard extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new BolsterEffect(2)));
// Whenever a creature you control with a +1/+1 counter on it attacks, tap target creature defending player controls.
- Ability ability = new AttacksCreatureYouControlTriggeredAbility(new EliteScaleguardTapEffect(), false, filter, true);
- ability.addTarget(new TargetCreaturePermanent(filter2));
+ Ability ability = new AttacksCreatureYouControlTriggeredAbility(new TapTargetEffect(), false, filter, true);
+ ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls")));
+ ability.setTargetAdjuster(EliteScaleguardTargetAdjuster.instance);
this.addAbility(ability);
}
@@ -61,28 +60,21 @@ public final class EliteScaleguard extends CardImpl {
}
}
-class EliteScaleguardTapEffect extends TapTargetEffect {
-
- EliteScaleguardTapEffect() {
- super();
- }
-
- EliteScaleguardTapEffect(final EliteScaleguardTapEffect effect) {
- super(effect);
- }
+enum EliteScaleguardTargetAdjuster implements TargetAdjuster {
+ instance;
@Override
- public EliteScaleguardTapEffect copy() {
- return new EliteScaleguardTapEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Permanent permanent = game.getPermanent(source.getFirstTarget());
- if (permanent != null) {
- permanent.tap(game);
- return true;
+ public void adjustTargets(Ability ability, Game game) {
+ FilterCreaturePermanent filterDefender = new FilterCreaturePermanent("creature defending player controls");
+ for (Effect effect : ability.getEffects()) {
+ if (effect instanceof TapTargetEffect) {
+ filterDefender.add(new ControllerIdPredicate(game.getCombat().getDefendingPlayerId(effect.getTargetPointer().getFirst(game, ability), game)));
+ effect.setTargetPointer(new FirstTargetPointer());// reset target pointer to first target to tap correct target
+ break;
+ }
}
- return false;
+ ability.getTargets().clear();
+ TargetCreaturePermanent target = new TargetCreaturePermanent(filterDefender);
+ ability.addTarget(target);
}
}
diff --git a/Mage.Sets/src/mage/cards/e/ElspethUndauntedHero.java b/Mage.Sets/src/mage/cards/e/ElspethUndauntedHero.java
index 445548bb214..d04129b3531 100644
--- a/Mage.Sets/src/mage/cards/e/ElspethUndauntedHero.java
+++ b/Mage.Sets/src/mage/cards/e/ElspethUndauntedHero.java
@@ -28,7 +28,7 @@ import java.util.UUID;
*/
public final class ElspethUndauntedHero extends CardImpl {
- private static final FilterCard filter = new FilterCard("Sunlit Hoplite");
+ private static final FilterCard filter = new FilterCard("card named Sunlit Hoplite");
static {
filter.add(new NamePredicate("Sunlit Hoplite"));
diff --git a/Mage.Sets/src/mage/cards/e/ElvenWarhounds.java b/Mage.Sets/src/mage/cards/e/ElvenWarhounds.java
index e34c1972140..6809e3f2321 100644
--- a/Mage.Sets/src/mage/cards/e/ElvenWarhounds.java
+++ b/Mage.Sets/src/mage/cards/e/ElvenWarhounds.java
@@ -19,7 +19,7 @@ public final class ElvenWarhounds extends CardImpl {
public ElvenWarhounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/e/ElvishBerserker.java b/Mage.Sets/src/mage/cards/e/ElvishBerserker.java
index 48aa62ef48a..a85d7e9e763 100644
--- a/Mage.Sets/src/mage/cards/e/ElvishBerserker.java
+++ b/Mage.Sets/src/mage/cards/e/ElvishBerserker.java
@@ -3,7 +3,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.BlockedCreatureCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
@@ -30,7 +30,7 @@ public final class ElvishBerserker extends CardImpl {
BlockedCreatureCount value = new BlockedCreatureCount();
Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn, true);
effect.setText("it gets +1/+1 until end of turn for each creature blocking it");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public ElvishBerserker(final ElvishBerserker card) {
diff --git a/Mage.Sets/src/mage/cards/e/ElvishSoultiller.java b/Mage.Sets/src/mage/cards/e/ElvishSoultiller.java
index a7153fbaa59..20cd16aa9c2 100644
--- a/Mage.Sets/src/mage/cards/e/ElvishSoultiller.java
+++ b/Mage.Sets/src/mage/cards/e/ElvishSoultiller.java
@@ -6,7 +6,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -34,7 +34,7 @@ public final class ElvishSoultiller extends CardImpl {
this.toughness = new MageInt(4);
// When Elvish Soultiller dies, choose a creature type. Shuffle all creature cards of that type from your graveyard into your library.
- addAbility(new DiesTriggeredAbility(new ElvishSoultillerEffect()));
+ addAbility(new DiesSourceTriggeredAbility(new ElvishSoultillerEffect()));
}
diff --git a/Mage.Sets/src/mage/cards/e/EmbalmersTools.java b/Mage.Sets/src/mage/cards/e/EmbalmersTools.java
index bb7c1284c11..59fa7e2e9a5 100644
--- a/Mage.Sets/src/mage/cards/e/EmbalmersTools.java
+++ b/Mage.Sets/src/mage/cards/e/EmbalmersTools.java
@@ -1,8 +1,5 @@
-
package mage.cards.e;
-import java.util.UUID;
-import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.common.SimpleActivatedAbility;
@@ -24,8 +21,9 @@ import mage.target.TargetPlayer;
import mage.target.common.TargetControlledPermanent;
import mage.util.CardUtil;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class EmbalmersTools extends CardImpl {
@@ -81,10 +79,7 @@ class EmbalmersToolsEffect extends CostModificationEffectImpl {
public boolean apply(Game game, Ability source, Ability abilityToModify) {
Player controller = game.getPlayer(abilityToModify.getControllerId());
if (controller != null) {
- Mana mana = abilityToModify.getManaCostsToPay().getMana();
- if (mana.count() > 1 && mana.getGeneric() > 0) {
- CardUtil.reduceCost(abilityToModify, 1);
- }
+ CardUtil.reduceCost(abilityToModify, 1);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/e/EmberFistZubera.java b/Mage.Sets/src/mage/cards/e/EmberFistZubera.java
index acfe8a486ca..921ad4e910e 100644
--- a/Mage.Sets/src/mage/cards/e/EmberFistZubera.java
+++ b/Mage.Sets/src/mage/cards/e/EmberFistZubera.java
@@ -5,7 +5,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.ZuberasDiedDynamicValue;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class EmberFistZubera extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(2);
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(ZuberasDiedDynamicValue.instance));
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(ZuberasDiedDynamicValue.instance));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability, new ZuberasDiedWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/e/Embercleave.java b/Mage.Sets/src/mage/cards/e/Embercleave.java
index 2c0d2baa7dd..35851640f03 100644
--- a/Mage.Sets/src/mage/cards/e/Embercleave.java
+++ b/Mage.Sets/src/mage/cards/e/Embercleave.java
@@ -1,13 +1,15 @@
package mage.cards.e;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.AttackingCreatureCount;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.DoubleStrikeAbility;
import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.FlashAbility;
@@ -15,12 +17,8 @@ import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
-import mage.filter.FilterPermanent;
-import mage.filter.common.FilterControlledCreaturePermanent;
-import mage.filter.predicate.permanent.AttackingPredicate;
-import mage.game.Game;
+import mage.filter.StaticFilters;
import mage.target.common.TargetControlledCreaturePermanent;
-import mage.util.CardUtil;
import java.util.UUID;
@@ -39,7 +37,10 @@ public final class Embercleave extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// This spell costs {1} less to cast for each attacking creature you control.
- this.addAbility(new SimpleStaticAbility(Zone.ALL, new EmbercleaveCostReductionEffect()));
+ DynamicValue xValue = new AttackingCreatureCount(StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED);
+ this.addAbility(new SimpleStaticAbility(Zone.ALL,
+ new SpellCostReductionForEachSourceEffect(1, xValue)
+ ).addHint(new ValueHint("Attacking creature you control", xValue)));
// When Embercleave enters the battlefield, attach it to target creature you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new AttachEffect(
@@ -71,41 +72,3 @@ public final class Embercleave extends CardImpl {
return new Embercleave(this);
}
}
-
-class EmbercleaveCostReductionEffect extends CostModificationEffectImpl {
-
- private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
-
- static {
- filter.add(AttackingPredicate.instance);
- }
-
- EmbercleaveCostReductionEffect() {
- super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {1} less to cast for each attacking creature you control";
- }
-
- private EmbercleaveCostReductionEffect(EmbercleaveCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- int reductionAmount = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
- CardUtil.reduceCost(abilityToModify, reductionAmount);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if ((abilityToModify instanceof SpellAbility) && abilityToModify.getSourceId().equals(source.getSourceId())) {
- return game.getCard(abilityToModify.getSourceId()) != null;
- }
- return false;
- }
-
- @Override
- public EmbercleaveCostReductionEffect copy() {
- return new EmbercleaveCostReductionEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/e/EmielTheBlessed.java b/Mage.Sets/src/mage/cards/e/EmielTheBlessed.java
new file mode 100644
index 00000000000..885180ceded
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/e/EmielTheBlessed.java
@@ -0,0 +1,98 @@
+package mage.cards.e;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.ExileTargetForSourceEffect;
+import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.counters.CounterType;
+import mage.filter.FilterPermanent;
+import mage.filter.StaticFilters;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.permanent.AnotherPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+import mage.abilities.effects.Effect;
+
+/**
+ * @author TheElk801
+ */
+public final class EmielTheBlessed extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterControlledCreaturePermanent("another target creature you control");
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ }
+
+ public EmielTheBlessed(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.UNICORN);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(4);
+
+ // {3}: Exile another target creature you control, then return it to the battlefield under its owner's control.
+ Ability ability = new SimpleActivatedAbility(new ExileTargetForSourceEffect(), new GenericManaCost(3));
+ ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect());
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(ability);
+
+ // Whenever another creature enters the battlefield under your control, you may pay {G/W}.
+ // If you do, put a +1/+1 counter on it. If it's a Unicorn, put two +1/+1 counters on it instead.
+ this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
+ Zone.BATTLEFIELD, new DoIfCostPaid(new EmielTheBlessedEffect(), new ManaCostsImpl<>("{G/W}")),
+ StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, false, SetTargetPointer.PERMANENT,
+ "Whenever another creature enters the battlefield under your control, you may pay {G/W}. "
+ + "If you do, put a +1/+1 counter on it. If it's a Unicorn, put two +1/+1 counters on it instead."
+ ));
+ }
+
+ private EmielTheBlessed(final EmielTheBlessed card) {
+ super(card);
+ }
+
+ @Override
+ public EmielTheBlessed copy() {
+ return new EmielTheBlessed(this);
+ }
+}
+
+class EmielTheBlessedEffect extends OneShotEffect {
+
+ EmielTheBlessedEffect() {
+ super(Outcome.Benefit);
+ }
+
+ private EmielTheBlessedEffect(final EmielTheBlessedEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public EmielTheBlessedEffect copy() {
+ return new EmielTheBlessedEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
+ if (permanent == null) {
+ return false;
+ }
+ int counters = permanent.hasSubtype(SubType.UNICORN, game) ? 2 : 1;
+ return permanent.addCounters(CounterType.P1P1.createInstance(counters), source, game);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/e/EmpoweredAutogenerator.java b/Mage.Sets/src/mage/cards/e/EmpoweredAutogenerator.java
index e8560d42708..a53fb3e2cab 100644
--- a/Mage.Sets/src/mage/cards/e/EmpoweredAutogenerator.java
+++ b/Mage.Sets/src/mage/cards/e/EmpoweredAutogenerator.java
@@ -88,7 +88,7 @@ class EmpoweredAutogeneratorManaEffect extends ManaEffect {
if (game == null) {
return mana;
}
- game.applyEffects();
+ game.getState().processAction(game);
Permanent sourcePermanent = game.getState().getPermanent(source.getSourceId());
if (sourcePermanent == null) {
return mana;
diff --git a/Mage.Sets/src/mage/cards/e/EmrakulTheAeonsTorn.java b/Mage.Sets/src/mage/cards/e/EmrakulTheAeonsTorn.java
index b08775abcbc..91caa63e32f 100644
--- a/Mage.Sets/src/mage/cards/e/EmrakulTheAeonsTorn.java
+++ b/Mage.Sets/src/mage/cards/e/EmrakulTheAeonsTorn.java
@@ -3,7 +3,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.PutIntoGraveFromAnywhereSourceTriggeredAbility;
import mage.abilities.effects.common.CastSourceTriggeredAbility;
import mage.abilities.effects.common.ShuffleIntoLibraryGraveOfSourceOwnerEffect;
@@ -39,7 +39,7 @@ public final class EmrakulTheAeonsTorn extends CardImpl {
this.toughness = new MageInt(15);
// Emrakul, the Aeons Torn can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// When you cast Emrakul, take an extra turn after this one.
this.addAbility(new CastSourceTriggeredAbility(new AddExtraTurnControllerEffect()));
diff --git a/Mage.Sets/src/mage/cards/e/EmryLurkerOfTheLoch.java b/Mage.Sets/src/mage/cards/e/EmryLurkerOfTheLoch.java
index d8338673a18..bebd901a619 100644
--- a/Mage.Sets/src/mage/cards/e/EmryLurkerOfTheLoch.java
+++ b/Mage.Sets/src/mage/cards/e/EmryLurkerOfTheLoch.java
@@ -2,21 +2,21 @@ package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.target.common.TargetCardInYourGraveyard;
-import mage.util.CardUtil;
import java.util.UUID;
@@ -35,7 +35,9 @@ public final class EmryLurkerOfTheLoch extends CardImpl {
this.toughness = new MageInt(2);
// This spell costs {1} less to cast for each artifact you control.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new EmryLurkerOfTheLochCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL,
+ new SpellCostReductionForEachSourceEffect(1, ArtifactYouControlCount.instance)
+ ).addHint(ArtifactYouControlHint.instance));
// When Emry, Lurker of the Loch enters the battlefield, put the top four cards of your library into your graveyard.
this.addAbility(new EntersBattlefieldTriggeredAbility(
@@ -58,40 +60,6 @@ public final class EmryLurkerOfTheLoch extends CardImpl {
}
}
-class EmryLurkerOfTheLochCostReductionEffect extends CostModificationEffectImpl {
-
- EmryLurkerOfTheLochCostReductionEffect() {
- super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {1} less to cast for each artifact you control";
- }
-
- private EmryLurkerOfTheLochCostReductionEffect(final EmryLurkerOfTheLochCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- int reductionAmount = game.getBattlefield().count(
- StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT,
- source.getSourceId(), source.getControllerId(), game
- );
- CardUtil.reduceCost(abilityToModify, reductionAmount);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- return abilityToModify instanceof SpellAbility
- && abilityToModify.getSourceId().equals(source.getSourceId())
- && game.getCard(abilityToModify.getSourceId()) != null;
- }
-
- @Override
- public EmryLurkerOfTheLochCostReductionEffect copy() {
- return new EmryLurkerOfTheLochCostReductionEffect(this);
- }
-}
-
class EmryLurkerOfTheLochPlayEffect extends AsThoughEffectImpl {
EmryLurkerOfTheLochPlayEffect() {
diff --git a/Mage.Sets/src/mage/cards/e/EnatuGolem.java b/Mage.Sets/src/mage/cards/e/EnatuGolem.java
index aba9da3ec17..b6f6f92caf8 100644
--- a/Mage.Sets/src/mage/cards/e/EnatuGolem.java
+++ b/Mage.Sets/src/mage/cards/e/EnatuGolem.java
@@ -3,7 +3,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class EnatuGolem extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(5);
- this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(4), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(4), false));
}
public EnatuGolem(final EnatuGolem card) {
diff --git a/Mage.Sets/src/mage/cards/e/EncampmentKeeper.java b/Mage.Sets/src/mage/cards/e/EncampmentKeeper.java
index 13fb82d3cb3..d2c401c54f9 100644
--- a/Mage.Sets/src/mage/cards/e/EncampmentKeeper.java
+++ b/Mage.Sets/src/mage/cards/e/EncampmentKeeper.java
@@ -26,7 +26,7 @@ public final class EncampmentKeeper extends CardImpl {
public EncampmentKeeper(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/e/EndlessCockroaches.java b/Mage.Sets/src/mage/cards/e/EndlessCockroaches.java
index ef402fd92dc..97b1e014e30 100644
--- a/Mage.Sets/src/mage/cards/e/EndlessCockroaches.java
+++ b/Mage.Sets/src/mage/cards/e/EndlessCockroaches.java
@@ -3,7 +3,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class EndlessCockroaches extends CardImpl {
this.toughness = new MageInt(1);
// When Endless Cockroaches dies, return it to its owner's hand.
- this.addAbility(new DiesTriggeredAbility(new ReturnToHandSourceEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new ReturnToHandSourceEffect()));
}
public EndlessCockroaches(final EndlessCockroaches card) {
diff --git a/Mage.Sets/src/mage/cards/e/EndlessWhispers.java b/Mage.Sets/src/mage/cards/e/EndlessWhispers.java
index 0eab041fecc..4cec197aea4 100644
--- a/Mage.Sets/src/mage/cards/e/EndlessWhispers.java
+++ b/Mage.Sets/src/mage/cards/e/EndlessWhispers.java
@@ -4,7 +4,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
@@ -36,7 +36,7 @@ public final class EndlessWhispers extends CardImpl {
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceToBattlefieldEffect());
Effect effect = new CreateDelayedTriggeredAbilityEffect(delayedAbility, true);
effect.setText("choose target opponent. That player puts this card from its owner's graveyard onto the battlefield under their control at the beginning of the next end step");
- Ability gainAbility = new DiesTriggeredAbility(effect);
+ Ability gainAbility = new DiesSourceTriggeredAbility(effect);
gainAbility.addTarget(new TargetOpponent());
effect = new GainAbilityAllEffect(gainAbility, Duration.WhileOnBattlefield, new FilterCreaturePermanent("Each creature"));
diff --git a/Mage.Sets/src/mage/cards/e/EngulfingSlagwurm.java b/Mage.Sets/src/mage/cards/e/EngulfingSlagwurm.java
index 7a9919f7c42..2ff0a9b403b 100644
--- a/Mage.Sets/src/mage/cards/e/EngulfingSlagwurm.java
+++ b/Mage.Sets/src/mage/cards/e/EngulfingSlagwurm.java
@@ -4,7 +4,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
@@ -30,7 +30,7 @@ public final class EngulfingSlagwurm extends CardImpl {
this.toughness = new MageInt(7);
// Whenever Engulfing Slagwurm blocks or becomes blocked by a creature, destroy that creature. You gain life equal to that creature's toughness.
- Ability ability = new BlocksOrBecomesBlockedTriggeredAbility(new DestroyTargetEffect(), false);
+ Ability ability = new BlocksOrBecomesBlockedSourceTriggeredAbility(new DestroyTargetEffect(), false);
ability.addEffect(new EngulfingSlagwurmEffect());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/e/EnterTheGodEternals.java b/Mage.Sets/src/mage/cards/e/EnterTheGodEternals.java
index fe6bdebf9b1..5db22b3b0bb 100644
--- a/Mage.Sets/src/mage/cards/e/EnterTheGodEternals.java
+++ b/Mage.Sets/src/mage/cards/e/EnterTheGodEternals.java
@@ -46,7 +46,7 @@ class EnterTheGodEternalsEffect extends OneShotEffect {
EnterTheGodEternalsEffect() {
super(Outcome.Benefit);
staticText = "{this} deals 4 damage to target creature and you gain life equal to the damage dealt this way. " +
- "Target player puts the top four cards of their library into their graveyard. Amass 4.";
+ "Target player mills four cards. Amass 4.";
}
private EnterTheGodEternalsEffect(final EnterTheGodEternalsEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/e/EnthrallingHold.java b/Mage.Sets/src/mage/cards/e/EnthrallingHold.java
new file mode 100644
index 00000000000..f1a53c0a3fa
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/e/EnthrallingHold.java
@@ -0,0 +1,87 @@
+package mage.cards.e;
+
+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.continuous.ControlEnchantedEffect;
+import mage.abilities.keyword.EnchantAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class EnthrallingHold extends CardImpl {
+
+ public EnthrallingHold(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}");
+
+ this.subtype.add(SubType.AURA);
+
+ // Enchant creature
+ TargetPermanent auraTarget = new EnthrallingHoldTarget();
+ this.getSpellAbility().addTarget(auraTarget);
+ this.getSpellAbility().addEffect(new AttachEffect(Outcome.GainControl));
+ Ability ability = new EnchantAbility(auraTarget.getTargetName());
+ this.addAbility(ability);
+
+ // You can't choose an untapped creature as this spell's target as you cast it.
+ Effect controlEnchantedEffect = new ControlEnchantedEffect();
+ controlEnchantedEffect.setText("You can't choose an untapped creature as this spell's target as you cast it.
" + controlEnchantedEffect.getText(null));
+
+ // You control enchanted creature.
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, controlEnchantedEffect));
+ }
+
+ private EnthrallingHold(final EnthrallingHold card) {
+ super(card);
+ }
+
+ @Override
+ public EnthrallingHold copy() {
+ return new EnthrallingHold(this);
+ }
+}
+
+class EnthrallingHoldTarget extends TargetCreaturePermanent {
+
+ EnthrallingHoldTarget() {}
+
+ private EnthrallingHoldTarget(EnthrallingHoldTarget target) {
+ super(target);
+ }
+
+ @Override
+ public EnthrallingHoldTarget copy() {
+ return new EnthrallingHoldTarget(this);
+ }
+
+ @Override
+ public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
+ if (super.canTarget(controllerId, id, source, game)) {
+ Permanent permanent = game.getPermanent(id);
+ return permanent.isTapped();
+ }
+ return false;
+ }
+
+ // See ruling: https://www.mtgsalvation.com/forums/magic-fundamentals/magic-rulings/magic-rulings-archives/253345-dream-leash
+ @Override
+ public boolean stillLegalTarget(UUID id, Ability source, Game game) {
+ Permanent permanent = game.getPermanent(id);
+ return permanent != null && StaticFilters.FILTER_PERMANENT_CREATURE.match(permanent, game);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/e/EpitaphGolem.java b/Mage.Sets/src/mage/cards/e/EpitaphGolem.java
index 9751cffa5b5..19b60d1e562 100644
--- a/Mage.Sets/src/mage/cards/e/EpitaphGolem.java
+++ b/Mage.Sets/src/mage/cards/e/EpitaphGolem.java
@@ -7,7 +7,7 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
+import mage.abilities.effects.common.PutOnLibraryTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -15,6 +15,7 @@ import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
+import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
/**
@@ -32,7 +33,7 @@ public final class EpitaphGolem extends CardImpl {
// {2}: Put target card from your graveyard on the bottom of your library.
Ability ability = new SimpleActivatedAbility(
Zone.BATTLEFIELD,
- new EpitaphGolemGraveyardToLibraryEffect(),
+ new PutOnLibraryTargetEffect(true),
new ManaCostsImpl("{2}"));
ability.addTarget(new TargetCardInYourGraveyard());
this.addAbility(ability);
@@ -66,9 +67,9 @@ class EpitaphGolemGraveyardToLibraryEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Card card = game.getCard(getTargetPointer().getFirst(game, source));
- if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) {
- return card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false);
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ return controller.putCardsOnBottomOfLibrary(game.getCard(getTargetPointer().getFirst(game, source)), game, source, true);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/e/Epochrasite.java b/Mage.Sets/src/mage/cards/e/Epochrasite.java
index 439e042ddf8..f0c0c3cdd09 100644
--- a/Mage.Sets/src/mage/cards/e/Epochrasite.java
+++ b/Mage.Sets/src/mage/cards/e/Epochrasite.java
@@ -5,10 +5,10 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.condition.InvertCondition;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainSuspendEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@@ -41,12 +41,12 @@ public final class Epochrasite extends CardImpl {
// Epochrasite enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)),
- new InvertCondition(CastFromHandSourceCondition.instance),
+ new InvertCondition(CastFromHandSourcePermanentCondition.instance),
"{this} enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand",""),
new CastFromHandWatcher());
// When Epochrasite dies, exile it with three time counters on it and it gains suspend.
- this.addAbility(new DiesTriggeredAbility(new EpochrasiteEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new EpochrasiteEffect()));
}
public Epochrasite(final Epochrasite card) {
diff --git a/Mage.Sets/src/mage/cards/e/EscapeProtocol.java b/Mage.Sets/src/mage/cards/e/EscapeProtocol.java
index 9d4ddeaa649..e7335c60f1f 100644
--- a/Mage.Sets/src/mage/cards/e/EscapeProtocol.java
+++ b/Mage.Sets/src/mage/cards/e/EscapeProtocol.java
@@ -1,24 +1,17 @@
package mage.cards.e;
-import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.CycleControllerTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
-import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.Predicates;
-import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.target.TargetPermanent;
import java.util.UUID;
@@ -28,50 +21,6 @@ import java.util.UUID;
*/
public final class EscapeProtocol extends CardImpl {
- public EscapeProtocol(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}");
-
- // Whenever you cycle a card, you may pay {1}. When you do, exile target artifact or creature you control, then return it to the battlefield under its owner's control.
- this.addAbility(new CycleControllerTriggeredAbility(new DoIfCostPaid(
- new EscapeProtocolEffect(), new GenericManaCost(1)
- ).setText("you may pay {1}. When you do, exile target artifact or creature you control, " +
- "then return it to the battlefield under its owner's control.")));
- }
-
- private EscapeProtocol(final EscapeProtocol card) {
- super(card);
- }
-
- @Override
- public EscapeProtocol copy() {
- return new EscapeProtocol(this);
- }
-}
-
-class EscapeProtocolEffect extends OneShotEffect {
-
- EscapeProtocolEffect() {
- super(Outcome.Benefit);
- }
-
- private EscapeProtocolEffect(final EscapeProtocolEffect effect) {
- super(effect);
- }
-
- @Override
- public EscapeProtocolEffect copy() {
- return new EscapeProtocolEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new EscapeProtocolReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class EscapeProtocolReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
private static final FilterPermanent filter
= new FilterControlledPermanent("artifact or creature you control");
@@ -82,35 +31,28 @@ class EscapeProtocolReflexiveTriggeredAbility extends DelayedTriggeredAbility {
));
}
- EscapeProtocolReflexiveTriggeredAbility() {
- super(new ExileTargetForSourceEffect(), Duration.OneUse, true);
- this.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect());
- this.addTarget(new TargetPermanent(filter));
+ public EscapeProtocol(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}");
+
+ // Whenever you cycle a card, you may pay {1}. When you do, exile target artifact or creature you control, then return it to the battlefield under its owner's control.
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new ExileTargetForSourceEffect(), false,
+ "exile target artifact or creature you control, " +
+ "then return it to the battlefield under its owner's control."
+ );
+ ability.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect());
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(new CycleControllerTriggeredAbility(new DoWhenCostPaid(
+ ability, new GenericManaCost(1), "Pay {1}?"
+ )));
}
- private EscapeProtocolReflexiveTriggeredAbility(final EscapeProtocolReflexiveTriggeredAbility ability) {
- super(ability);
+ private EscapeProtocol(final EscapeProtocol card) {
+ super(card);
}
@Override
- public EscapeProtocolReflexiveTriggeredAbility copy() {
- return new EscapeProtocolReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "Exile target artifact or creature you control, " +
- "then return it to the battlefield under its owner's control.";
+ public EscapeProtocol copy() {
+ return new EscapeProtocol(this);
}
}
diff --git a/Mage.Sets/src/mage/cards/e/EscapedNull.java b/Mage.Sets/src/mage/cards/e/EscapedNull.java
index fdfcb2db58b..2a72bd2b0fe 100644
--- a/Mage.Sets/src/mage/cards/e/EscapedNull.java
+++ b/Mage.Sets/src/mage/cards/e/EscapedNull.java
@@ -3,7 +3,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class EscapedNull extends CardImpl {
this.toughness = new MageInt(2);
this.addAbility(LifelinkAbility.getInstance());
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(5, 0, Duration.EndOfTurn), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(5, 0, Duration.EndOfTurn), false));
}
public EscapedNull(final EscapedNull card) {
diff --git a/Mage.Sets/src/mage/cards/e/EsperSojourners.java b/Mage.Sets/src/mage/cards/e/EsperSojourners.java
index ebbaca1dcbc..46f72cfd8f0 100644
--- a/Mage.Sets/src/mage/cards/e/EsperSojourners.java
+++ b/Mage.Sets/src/mage/cards/e/EsperSojourners.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.CycleTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.MayTapOrUntapTargetEffect;
import mage.abilities.keyword.CyclingAbility;
@@ -34,7 +34,7 @@ public final class EsperSojourners extends CardImpl {
// When you cycle Esper Sojourners or it dies, you may tap or untap target permanent.
Ability ability1 = new CycleTriggeredAbility(new MayTapOrUntapTargetEffect());
- Ability ability2 = new DiesTriggeredAbility(new MayTapOrUntapTargetEffect());
+ Ability ability2 = new DiesSourceTriggeredAbility(new MayTapOrUntapTargetEffect());
ability1.addTarget(new TargetPermanent());
ability2.addTarget(new TargetPermanent());
this.addAbility(ability1);
diff --git a/Mage.Sets/src/mage/cards/e/EssenceBacklash.java b/Mage.Sets/src/mage/cards/e/EssenceBacklash.java
index 0fcc6e2e702..50410118aa6 100644
--- a/Mage.Sets/src/mage/cards/e/EssenceBacklash.java
+++ b/Mage.Sets/src/mage/cards/e/EssenceBacklash.java
@@ -41,7 +41,7 @@ class EssenceBacklashEffect extends OneShotEffect {
public EssenceBacklashEffect() {
super(Outcome.Damage);
- staticText = "Counter target creature spell. Essence Backlash deals damage equal to that spell's power to its controller";
+ staticText = "Counter target creature spell. {this} deals damage equal to that spell's power to its controller";
}
public EssenceBacklashEffect(final EssenceBacklashEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/e/EssenceDepleter.java b/Mage.Sets/src/mage/cards/e/EssenceDepleter.java
index 6f54e14200f..185570dfd42 100644
--- a/Mage.Sets/src/mage/cards/e/EssenceDepleter.java
+++ b/Mage.Sets/src/mage/cards/e/EssenceDepleter.java
@@ -1,12 +1,9 @@
-
package mage.cards.e;
-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.Effect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.keyword.DevoidAbility;
@@ -17,14 +14,15 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class EssenceDepleter extends CardImpl {
public EssenceDepleter(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.ELDRAZI);
this.subtype.add(SubType.DRONE);
this.power = new MageInt(2);
@@ -35,9 +33,7 @@ public final class EssenceDepleter extends CardImpl {
// {1}{C}: Target opponent loses 1 life and you gain 1 life.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseLifeTargetEffect(1), new ManaCostsImpl("{1}{C}"));
- Effect effect = new GainLifeEffect(1);
- effect.setText("and you gain 1 life");
- ability.addEffect(effect);
+ ability.addEffect(new GainLifeEffect(1).concatBy("and"));
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/e/EvilTwin.java b/Mage.Sets/src/mage/cards/e/EvilTwin.java
index cda27f37ff9..f08e6c3402b 100644
--- a/Mage.Sets/src/mage/cards/e/EvilTwin.java
+++ b/Mage.Sets/src/mage/cards/e/EvilTwin.java
@@ -69,7 +69,7 @@ class EvilTwinApplyToPermanent extends ApplyToPermanent {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{U}{B}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent(filter));
- permanent.addAbility(ability, game);
+ permanent.addAbility(ability, source.getSourceId(), game);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/e/Excavator.java b/Mage.Sets/src/mage/cards/e/Excavator.java
index 827f0d2c219..9516f6212c4 100644
--- a/Mage.Sets/src/mage/cards/e/Excavator.java
+++ b/Mage.Sets/src/mage/cards/e/Excavator.java
@@ -112,7 +112,7 @@ class ExcavatorEffect extends ContinuousEffectImpl implements SourceEffect {
if (permanent != null) {
for(Ability ability : abilities)
{
- permanent.addAbility(ability, source.getSourceId(), game, false);
+ permanent.addAbility(ability, source.getSourceId(), game);
}
}
}
diff --git a/Mage.Sets/src/mage/cards/e/ExiledBoggart.java b/Mage.Sets/src/mage/cards/e/ExiledBoggart.java
index 3d1703ba0d1..d78998ea279 100644
--- a/Mage.Sets/src/mage/cards/e/ExiledBoggart.java
+++ b/Mage.Sets/src/mage/cards/e/ExiledBoggart.java
@@ -3,7 +3,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.discard.DiscardControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class ExiledBoggart extends CardImpl {
this.toughness = new MageInt(2);
// When Exiled Boggart dies, discard a card.
- this.addAbility(new DiesTriggeredAbility(new DiscardControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DiscardControllerEffect(1), false));
}
public ExiledBoggart(final ExiledBoggart card) {
diff --git a/Mage.Sets/src/mage/cards/e/ExperimentalOverload.java b/Mage.Sets/src/mage/cards/e/ExperimentalOverload.java
new file mode 100644
index 00000000000..ae7d41f9079
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/e/ExperimentalOverload.java
@@ -0,0 +1,78 @@
+package mage.cards.e;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.ExileSpellEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.permanent.token.WeirdToken2;
+import mage.players.Player;
+import mage.target.TargetCard;
+import mage.target.common.TargetCardInYourGraveyard;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ExperimentalOverload extends CardImpl {
+
+ public ExperimentalOverload(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}{R}");
+
+ // Create an X/X blue and red Weird creature token, where X is the number of instant and sorcery cards in your graveyard. Then you may return an instant or sorcery card from your graveyard to your hand. Exile Experimental Overload.
+ this.getSpellAbility().addEffect(new ExperimentalOverloadEffect());
+ this.getSpellAbility().addEffect(ExileSpellEffect.getInstance());
+ }
+
+ private ExperimentalOverload(final ExperimentalOverload card) {
+ super(card);
+ }
+
+ @Override
+ public ExperimentalOverload copy() {
+ return new ExperimentalOverload(this);
+ }
+}
+
+class ExperimentalOverloadEffect extends OneShotEffect {
+
+ ExperimentalOverloadEffect() {
+ super(Outcome.Benefit);
+ staticText = "Create an X/X blue and red Weird creature token, " +
+ "where X is the number of instant and sorcery cards in your graveyard. " +
+ "Then you may return an instant or sorcery card from your graveyard to your hand.";
+ }
+
+ private ExperimentalOverloadEffect(final ExperimentalOverloadEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ExperimentalOverloadEffect copy() {
+ return new ExperimentalOverloadEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null) {
+ return false;
+ }
+ int spellCount = player.getGraveyard().count(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY, game);
+ new WeirdToken2(spellCount).putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
+ if (spellCount < 1) {
+ return true;
+ }
+ TargetCard target = new TargetCardInYourGraveyard(
+ 0, 1, StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY, true
+ );
+ player.choose(outcome, player.getGraveyard(), target, game);
+ return player.moveCards(game.getCard(target.getFirstTarget()), Zone.HAND, source, game);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/e/Extortion.java b/Mage.Sets/src/mage/cards/e/Extortion.java
index 46d5163ae06..86c210dc310 100644
--- a/Mage.Sets/src/mage/cards/e/Extortion.java
+++ b/Mage.Sets/src/mage/cards/e/Extortion.java
@@ -1,19 +1,18 @@
-
package mage.cards.e;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
+import mage.target.common.TargetCardInHand;
import java.util.UUID;
@@ -30,7 +29,7 @@ public final class Extortion extends CardImpl {
this.getSpellAbility().addTarget(new TargetPlayer());
}
- public Extortion(final Extortion card) {
+ private Extortion(final Extortion card) {
super(card);
}
@@ -42,12 +41,12 @@ public final class Extortion extends CardImpl {
class ExtortionEffect extends OneShotEffect {
- public ExtortionEffect() {
+ ExtortionEffect() {
super(Outcome.Discard);
- staticText = "Look at target player's hand and choose up to two cards from it. That player discards that card.";
+ staticText = "Look at target player's hand and choose up to two cards from it. That player discards those cards.";
}
- public ExtortionEffect(final ExtortionEffect effect) {
+ private ExtortionEffect(final ExtortionEffect effect) {
super(effect);
}
@@ -55,18 +54,15 @@ class ExtortionEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(source.getFirstTarget());
Player you = game.getPlayer(source.getControllerId());
- if (targetPlayer != null && you != null) {
- you.lookAtCards("Discard", targetPlayer.getHand(), game);
- TargetCard target = new TargetCard(0, 2, Zone.HAND, new FilterCard());
- target.setNotTarget(true);
- if (you.choose(Outcome.Benefit, targetPlayer.getHand(), target, game)) {
- Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
- return targetPlayer.discard(card, source, game);
-
- }
-
+ if (targetPlayer == null || you == null) {
+ return false;
}
- return false;
+ you.lookAtCards("Discard", targetPlayer.getHand(), game);
+ TargetCard target = new TargetCardInHand(0, 2, StaticFilters.FILTER_CARD_CARDS);
+ target.setNotTarget(true);
+ you.choose(Outcome.Discard, targetPlayer.getHand(), target, game);
+ targetPlayer.discard(new CardsImpl(target.getTargets()), source, game);
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/e/ExtractFromDarkness.java b/Mage.Sets/src/mage/cards/e/ExtractFromDarkness.java
index 60fa0cc6823..92e77183b56 100644
--- a/Mage.Sets/src/mage/cards/e/ExtractFromDarkness.java
+++ b/Mage.Sets/src/mage/cards/e/ExtractFromDarkness.java
@@ -1,12 +1,13 @@
package mage.cards.e;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
@@ -14,8 +15,9 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCardInGraveyard;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class ExtractFromDarkness extends CardImpl {
@@ -24,12 +26,13 @@ public final class ExtractFromDarkness extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{B}");
// Each player puts the top two cards of their library into their graveyard.
- this.getSpellAbility().addEffect(new ExtractFromDarknessMillEffect());
+ this.getSpellAbility().addEffect(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(2, TargetController.ANY));
+
// Then put a creature card from a graveyard onto the battlefield under your control.
- this.getSpellAbility().addEffect(new ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect());
+ this.getSpellAbility().addEffect(new ExtractFromDarknessEffect());
}
- public ExtractFromDarkness(final ExtractFromDarkness card) {
+ private ExtractFromDarkness(final ExtractFromDarkness card) {
super(card);
}
@@ -39,48 +42,20 @@ public final class ExtractFromDarkness extends CardImpl {
}
}
-class ExtractFromDarknessMillEffect extends OneShotEffect {
+class ExtractFromDarknessEffect extends OneShotEffect {
- ExtractFromDarknessMillEffect() {
- super(Outcome.Detriment);
- staticText = "Each player puts the top two cards of their library into their graveyard";
- }
-
- ExtractFromDarknessMillEffect(final ExtractFromDarknessMillEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, 2), Zone.GRAVEYARD, source, game);
- }
- }
- return true;
- }
-
- @Override
- public ExtractFromDarknessMillEffect copy() {
- return new ExtractFromDarknessMillEffect(this);
- }
-}
-
-class ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect extends OneShotEffect {
-
- public ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect() {
+ ExtractFromDarknessEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "Put a creature card from a graveyard onto the battlefield under your control";
}
- public ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect(final ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect effect) {
+ private ExtractFromDarknessEffect(final ExtractFromDarknessEffect effect) {
super(effect);
}
@Override
- public ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect copy() {
- return new ExtractFromDarknessReturnFromGraveyardToBattlefieldEffect(this);
+ public ExtractFromDarknessEffect copy() {
+ return new ExtractFromDarknessEffect(this);
}
@Override
diff --git a/Mage.Sets/src/mage/cards/e/ExultantCultist.java b/Mage.Sets/src/mage/cards/e/ExultantCultist.java
index 5011b0c40ed..babb9bf1969 100644
--- a/Mage.Sets/src/mage/cards/e/ExultantCultist.java
+++ b/Mage.Sets/src/mage/cards/e/ExultantCultist.java
@@ -3,7 +3,7 @@ package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class ExultantCultist extends CardImpl {
this.toughness = new MageInt(2);
// When Exultant Cultist dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public ExultantCultist(final ExultantCultist card) {
diff --git a/Mage.Sets/src/mage/cards/e/EyeCollector.java b/Mage.Sets/src/mage/cards/e/EyeCollector.java
index 708c9bec082..757aa987571 100644
--- a/Mage.Sets/src/mage/cards/e/EyeCollector.java
+++ b/Mage.Sets/src/mage/cards/e/EyeCollector.java
@@ -1,22 +1,16 @@
package mage.cards.e;
import mage.MageInt;
-import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.CardsImpl;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.players.Player;
+import mage.constants.TargetController;
import java.util.UUID;
-import java.util.stream.Collectors;
/**
* @author TheElk801
@@ -34,7 +28,7 @@ public final class EyeCollector extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever Eye Collector deals combat damage to a player, each player puts the top card of their library into their graveyard.
- this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new EyeCollectorEffect(), false));
+ this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.ANY), false));
}
private EyeCollector(final EyeCollector card) {
@@ -46,37 +40,3 @@ public final class EyeCollector extends CardImpl {
return new EyeCollector(this);
}
}
-
-class EyeCollectorEffect extends OneShotEffect {
-
- EyeCollectorEffect() {
- super(Outcome.Benefit);
- staticText = "each player puts the top card of their library into their graveyard";
- }
-
- private EyeCollectorEffect(final EyeCollectorEffect effect) {
- super(effect);
- }
-
- @Override
- public EyeCollectorEffect copy() {
- return new EyeCollectorEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller == null) {
- return false;
- }
- return controller.moveCards(new CardsImpl(game.getState()
- .getPlayersInRange(controller.getId(), game)
- .stream()
- .map(game::getPlayer)
- .filter(player -> player != null)
- .map(Player::getLibrary)
- .map(library -> library.getFromTop(game))
- .collect(Collectors.toSet())
- ), Zone.GRAVEYARD, source, game);
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/e/EyeOfUgin.java b/Mage.Sets/src/mage/cards/e/EyeOfUgin.java
index 5aa63ff887e..d2aec862fd1 100644
--- a/Mage.Sets/src/mage/cards/e/EyeOfUgin.java
+++ b/Mage.Sets/src/mage/cards/e/EyeOfUgin.java
@@ -1,8 +1,5 @@
-
-
package mage.cards.e;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
@@ -21,6 +18,8 @@ import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.ColorlessPredicate;
import mage.target.common.TargetCardInLibrary;
+import java.util.UUID;
+
/**
* @author maurer.it_at_gmail.com
*/
@@ -41,6 +40,7 @@ public final class EyeOfUgin extends CardImpl {
// Colorless Eldrazi spells you cast cost {2} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filterSpells, 2)));
+
// {7}, {tap}: Search your library for a colorless creature card, reveal it, and put it into your hand. Then shuffle your library.
Ability searchAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true),
diff --git a/Mage.Sets/src/mage/cards/e/EzurisPredation.java b/Mage.Sets/src/mage/cards/e/EzurisPredation.java
index ef1c18b4c17..12f004e6fa5 100644
--- a/Mage.Sets/src/mage/cards/e/EzurisPredation.java
+++ b/Mage.Sets/src/mage/cards/e/EzurisPredation.java
@@ -1,8 +1,7 @@
package mage.cards.e;
-import java.util.List;
-import java.util.UUID;
+import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -13,18 +12,23 @@ import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
+import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.BeastToken2;
import mage.players.Player;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class EzurisPredation extends CardImpl {
public EzurisPredation(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{5}{G}{G}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{G}{G}{G}");
// For each creature your opponents control, create a 4/4 green Beast creature token. Each of those Beasts fights a different one of those creatures.
this.getSpellAbility().addEffect(new EzurisPredationEffect());
@@ -75,6 +79,7 @@ class EzurisPredationEffect extends OneShotEffect {
FilterCreaturePermanent filterCreature = new FilterCreaturePermanent();
filterCreature.add(TargetController.OPPONENT.getControllerPredicate());
List creaturesOfOpponents = game.getBattlefield().getActivePermanents(filterCreature, source.getControllerId(), source.getSourceId(), game);
+ Set morSet = new HashSet<>();
if (!creaturesOfOpponents.isEmpty()) {
CreateTokenEffect effect = new CreateTokenEffect(new BeastToken2(), creaturesOfOpponents.size());
effect.apply(game, source);
@@ -86,10 +91,15 @@ class EzurisPredationEffect extends OneShotEffect {
}
Permanent opponentCreature = creaturesOfOpponents.iterator().next();
creaturesOfOpponents.remove(opponentCreature);
- token.fight(opponentCreature, source, game);
+ token.fight(opponentCreature, source, game, false);
+ morSet.add(new MageObjectReference(token, game));
+ morSet.add(new MageObjectReference(opponentCreature, game));
game.informPlayers(token.getLogName() + " fights " + opponentCreature.getLogName());
}
}
+ String data = UUID.randomUUID().toString();
+ game.getState().setValue("batchFight_" + data, morSet);
+ game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BATCH_FIGHT, getId(), getId(), source.getControllerId(), data, 0));
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/f/FalconerAdept.java b/Mage.Sets/src/mage/cards/f/FalconerAdept.java
new file mode 100644
index 00000000000..c9f342a0266
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/f/FalconerAdept.java
@@ -0,0 +1,41 @@
+package mage.cards.f;
+
+import mage.MageInt;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.game.permanent.token.BirdToken;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class FalconerAdept extends CardImpl {
+
+ public FalconerAdept(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.SOLDIER);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Whenever Falconer Adept attacks, create a 1/1 white Bird creature token with flying that's tapped and attacking.
+ this.addAbility(new AttacksTriggeredAbility(
+ new CreateTokenEffect(new BirdToken(), 1, true, true), false
+ ));
+ }
+
+ private FalconerAdept(final FalconerAdept card) {
+ super(card);
+ }
+
+ @Override
+ public FalconerAdept copy() {
+ return new FalconerAdept(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/f/FallenShinobi.java b/Mage.Sets/src/mage/cards/f/FallenShinobi.java
index bc6cf45403d..6405ab06868 100644
--- a/Mage.Sets/src/mage/cards/f/FallenShinobi.java
+++ b/Mage.Sets/src/mage/cards/f/FallenShinobi.java
@@ -4,7 +4,6 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.NinjutsuAbility;
@@ -12,9 +11,10 @@ import mage.cards.*;
import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
-import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
+import mage.target.targetpointer.FixedTargets;
/**
* @author TheElk801
@@ -52,8 +52,8 @@ class FallenShinobiEffect extends OneShotEffect {
FallenShinobiEffect() {
super(Outcome.Benefit);
- staticText = "that player exiles the top two cards of their library. " +
- "Until end of turn, you may play those cards without paying their mana cost.";
+ staticText = "that player exiles the top two cards of their library. "
+ + "Until end of turn, you may play those cards without paying their mana cost.";
}
private FallenShinobiEffect(final FallenShinobiEffect effect) {
@@ -71,53 +71,7 @@ class FallenShinobiEffect extends OneShotEffect {
if (player == null) {
return false;
}
- Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 2));
- player.moveCards(cards, Zone.EXILED, source, game);
- for (Card card : cards.getCards(game)) {
- ContinuousEffect effect = new UrzaLordHighArtificerFromExileEffect();
- effect.setTargetPointer(new FixedTarget(card, game));
- game.addEffect(effect, source);
- }
- return true;
- }
-}
-
-class UrzaLordHighArtificerFromExileEffect extends AsThoughEffectImpl {
-
- UrzaLordHighArtificerFromExileEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
- staticText = "you may play that card without paying its mana cost";
- }
-
- private UrzaLordHighArtificerFromExileEffect(final UrzaLordHighArtificerFromExileEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public UrzaLordHighArtificerFromExileEffect copy() {
- return new UrzaLordHighArtificerFromExileEffect(this);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- if (!affectedControllerId.equals(source.getControllerId())
- || !getTargetPointer().getTargets(game, source).contains(objectId)) {
- return false;
- }
- Card card = game.getCard(objectId);
- if (card == null || card.isLand() || card.getSpellAbility().getCosts() == null) {
- return true;
- }
- Player player = game.getPlayer(affectedControllerId);
- if (player == null) {
- return false;
- }
- player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
- return true;
+ return PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(game, source, player.getLibrary().getTopCards(game, 2),
+ TargetController.YOU, Duration.EndOfTurn, true);
}
}
diff --git a/Mage.Sets/src/mage/cards/f/FalseProphet.java b/Mage.Sets/src/mage/cards/f/FalseProphet.java
index 968b9c34550..6db36bfe8db 100644
--- a/Mage.Sets/src/mage/cards/f/FalseProphet.java
+++ b/Mage.Sets/src/mage/cards/f/FalseProphet.java
@@ -3,7 +3,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ExileAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class FalseProphet extends CardImpl {
this.toughness = new MageInt(2);
// When False Prophet dies, exile all creatures.
- this.addAbility(new DiesTriggeredAbility(new ExileAllEffect(new FilterCreaturePermanent())));
+ this.addAbility(new DiesSourceTriggeredAbility(new ExileAllEffect(new FilterCreaturePermanent())));
}
public FalseProphet(final FalseProphet card) {
diff --git a/Mage.Sets/src/mage/cards/f/FamishedGhoul.java b/Mage.Sets/src/mage/cards/f/FamishedGhoul.java
index 984bafd6106..83277c20645 100644
--- a/Mage.Sets/src/mage/cards/f/FamishedGhoul.java
+++ b/Mage.Sets/src/mage/cards/f/FamishedGhoul.java
@@ -1,7 +1,5 @@
-
package mage.cards.f;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -13,17 +11,18 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInASingleGraveyard;
+import java.util.UUID;
+
/**
- *
* @author cbt33
*/
public final class FamishedGhoul extends CardImpl {
public FamishedGhoul(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(3);
@@ -32,7 +31,7 @@ public final class FamishedGhoul extends CardImpl {
// {1}{B}, Sacrifice Famished Ghoul: Exile up to two target cards from a single graveyard.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new ManaCostsImpl("{1}{B}"));
ability.addCost(new SacrificeSourceCost());
- ability.addTarget(new TargetCardInASingleGraveyard(0, 2, new FilterCard("cards from a single graveyard")));
+ ability.addTarget(new TargetCardInASingleGraveyard(0, 2, StaticFilters.FILTER_CARD_CARDS));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/f/FatedConflagration.java b/Mage.Sets/src/mage/cards/f/FatedConflagration.java
index be6f34b0b6e..7c1b4b9a8d4 100644
--- a/Mage.Sets/src/mage/cards/f/FatedConflagration.java
+++ b/Mage.Sets/src/mage/cards/f/FatedConflagration.java
@@ -24,7 +24,7 @@ public final class FatedConflagration extends CardImpl {
// Fated Conflagration deals 5 damage to target creature or planewalker. If it's your turn, scry 2.
this.getSpellAbility().addEffect(new DamageTargetEffect(5));
this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker());
- this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ScryEffect(2), MyTurnCondition.instance, "If it's your turn, scry 2"));
+ this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ScryEffect(2, false), MyTurnCondition.instance, "If it's your turn, scry 2"));
this.getSpellAbility().addHint(MyTurnHint.instance);
}
diff --git a/Mage.Sets/src/mage/cards/f/FatedIntervention.java b/Mage.Sets/src/mage/cards/f/FatedIntervention.java
index 92d6442d137..2b1ea48ef08 100644
--- a/Mage.Sets/src/mage/cards/f/FatedIntervention.java
+++ b/Mage.Sets/src/mage/cards/f/FatedIntervention.java
@@ -20,10 +20,9 @@ public final class FatedIntervention extends CardImpl {
public FatedIntervention(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}{G}{G}");
-
// Create two 3/3 green Centaur enchantment creature tokens. If it's your turn, scry 2.
this.getSpellAbility().addEffect(new CreateTokenEffect(new CentaurEnchantmentCreatureToken(), 2));
- this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ScryEffect(2), MyTurnCondition.instance, "If it's your turn, scry 2"));
+ this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ScryEffect(2, false), MyTurnCondition.instance, "If it's your turn, scry 2"));
this.getSpellAbility().addHint(MyTurnHint.instance);
}
diff --git a/Mage.Sets/src/mage/cards/f/FatedRetribution.java b/Mage.Sets/src/mage/cards/f/FatedRetribution.java
index d0a35a9ed85..23654106e7a 100644
--- a/Mage.Sets/src/mage/cards/f/FatedRetribution.java
+++ b/Mage.Sets/src/mage/cards/f/FatedRetribution.java
@@ -32,7 +32,7 @@ public final class FatedRetribution extends CardImpl {
// Destroy all creatures and planeswalkers. If it's your turn, scry 2.
this.getSpellAbility().addEffect(new DestroyAllEffect(filter, false));
- this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ScryEffect(2), MyTurnCondition.instance, "If it's your turn, scry 2"));
+ this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new ScryEffect(2, false), MyTurnCondition.instance, "If it's your turn, scry 2"));
this.getSpellAbility().addHint(MyTurnHint.instance);
}
diff --git a/Mage.Sets/src/mage/cards/f/FeastingTrollKing.java b/Mage.Sets/src/mage/cards/f/FeastingTrollKing.java
index af752d5c849..5e021705bad 100644
--- a/Mage.Sets/src/mage/cards/f/FeastingTrollKing.java
+++ b/Mage.Sets/src/mage/cards/f/FeastingTrollKing.java
@@ -3,7 +3,7 @@ package mage.cards.f;
import mage.MageInt;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
@@ -48,7 +48,7 @@ public final class FeastingTrollKing extends CardImpl {
// When Feasting Troll King enters the battlefield, if you cast it from your hand, create three Food tokens.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new FoodToken(), 3)),
- CastFromHandSourceCondition.instance, "When {this} enters the battlefield, " +
+ CastFromHandSourcePermanentCondition.instance, "When {this} enters the battlefield, " +
"if you cast it from your hand, create three Food tokens."
), new CastFromHandWatcher());
diff --git a/Mage.Sets/src/mage/cards/f/FelineSovereign.java b/Mage.Sets/src/mage/cards/f/FelineSovereign.java
new file mode 100644
index 00000000000..7b84e45e8b4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/f/FelineSovereign.java
@@ -0,0 +1,131 @@
+package mage.cards.f;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.DestroyTargetEffect;
+import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
+import mage.abilities.keyword.ProtectionAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.FilterCard;
+import mage.filter.common.FilterArtifactOrEnchantmentPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+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.game.permanent.Permanent;
+import mage.target.TargetPermanent;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+public final class FelineSovereign extends CardImpl {
+
+ private static final FilterCreaturePermanent filterCat = new FilterCreaturePermanent("Cats");
+
+ static {
+ filterCat.add(SubType.CAT.getPredicate());
+ filterCat.add(TargetController.YOU.getControllerPredicate());
+ }
+
+ private static final FilterCard filterProtectionFromDogs = new FilterCard("Dogs");
+
+ static {
+ filterProtectionFromDogs.add(SubType.DOG.getPredicate());
+ }
+
+ public FelineSovereign(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
+ this.subtype.add(SubType.CAT);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Other Cats you control get +1/+1 and have protection from Dogs.
+ Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filterCat, true));
+ //
+ Effect effect = new GainAbilityAllEffect(new ProtectionAbility(filterProtectionFromDogs), Duration.WhileOnBattlefield, filterCat, true);
+ effect.setText("and have protection from Dogs");
+ ability.addEffect(effect);
+ this.addAbility(ability);
+
+ // Whenever one or more Cats you control deal combat damage to a player, destroy up to one target artifact or enchantment that player controls.
+ this.addAbility(new FelineSovereignTriggeredAbility());
+ }
+
+ public FelineSovereign(final FelineSovereign card) {
+ super(card);
+ }
+
+ @Override
+ public FelineSovereign copy() {
+ return new FelineSovereign(this);
+ }
+}
+
+class FelineSovereignTriggeredAbility extends TriggeredAbilityImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Cat you control");
+
+ static {
+ filter.add(TargetController.YOU.getControllerPredicate());
+ filter.add(SubType.CAT.getPredicate());
+ }
+
+ private final Set damagedPlayerIds = new HashSet<>();
+
+ public FelineSovereignTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new DestroyTargetEffect(), false);
+ }
+
+ public FelineSovereignTriggeredAbility(final FelineSovereignTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public FelineSovereignTriggeredAbility copy() {
+ return new FelineSovereignTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == EventType.DAMAGED_PLAYER
+ || event.getType() == EventType.COMBAT_DAMAGE_STEP_PRIORITY
+ || event.getType() == EventType.ZONE_CHANGE;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (event.getType() == EventType.DAMAGED_PLAYER) {
+ DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event;
+ Permanent p = game.getPermanent(event.getSourceId());
+ if (damageEvent.isCombatDamage() && p != null && p.isControlledBy(this.getControllerId()) &&
+ filter.match(p, getSourceId(), getControllerId(), game) &&
+ !damagedPlayerIds.contains(event.getPlayerId())) {
+ damagedPlayerIds.add(event.getPlayerId());
+ this.getTargets().clear();
+ FilterArtifactOrEnchantmentPermanent filter = new FilterArtifactOrEnchantmentPermanent();
+ filter.add(new ControllerIdPredicate(event.getPlayerId()));
+ this.addTarget(new TargetPermanent(0, 1, filter, false));
+ return true;
+ }
+ }
+ if (event.getType() == EventType.COMBAT_DAMAGE_STEP_PRIORITY ||
+ (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(getSourceId()))) {
+ damagedPlayerIds.clear();
+ }
+ return false;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever one or more Cats you control deal combat damage to a player, destroy up to one target artifact or enchantment that player controls";
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/f/FeralLightning.java b/Mage.Sets/src/mage/cards/f/FeralLightning.java
index e15766daf25..d87cf22bad3 100644
--- a/Mage.Sets/src/mage/cards/f/FeralLightning.java
+++ b/Mage.Sets/src/mage/cards/f/FeralLightning.java
@@ -1,7 +1,5 @@
-
package mage.cards.f;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -10,17 +8,18 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
-import mage.game.permanent.token.ElementalToken;
+import mage.game.permanent.token.ElementalTokenWithHaste;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class FeralLightning extends CardImpl {
public FeralLightning(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}{R}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}{R}{R}");
// Create three 3/1 red Elemental creature tokens with haste. Exile them at the beginning of the next end step.
this.getSpellAbility().addEffect(new FeralLightningEffect());
@@ -57,7 +56,7 @@ class FeralLightningEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- CreateTokenEffect effect = new CreateTokenEffect(new ElementalToken("CON", 1, true), 3);
+ CreateTokenEffect effect = new CreateTokenEffect(new ElementalTokenWithHaste(), 3);
effect.apply(game, source);
effect.exileTokensCreatedAtNextEndStep(game, source);
return true;
diff --git a/Mage.Sets/src/mage/cards/f/FeralProwler.java b/Mage.Sets/src/mage/cards/f/FeralProwler.java
index 35935d2fcbb..5636aa30e89 100644
--- a/Mage.Sets/src/mage/cards/f/FeralProwler.java
+++ b/Mage.Sets/src/mage/cards/f/FeralProwler.java
@@ -2,7 +2,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -18,7 +18,7 @@ public final class FeralProwler extends CardImpl {
power = new MageInt(1);
toughness = new MageInt(3);
- addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public FeralProwler(final FeralProwler feralProwler) {
diff --git a/Mage.Sets/src/mage/cards/f/FerozsBan.java b/Mage.Sets/src/mage/cards/f/FerozsBan.java
index bda78ea60a2..52a6ed49956 100644
--- a/Mage.Sets/src/mage/cards/f/FerozsBan.java
+++ b/Mage.Sets/src/mage/cards/f/FerozsBan.java
@@ -1,29 +1,29 @@
package mage.cards.f;
-import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.TargetController;
import mage.constants.Zone;
-import mage.filter.StaticFilters;
+import mage.filter.FilterCard;
+import mage.filter.common.FilterCreatureCard;
+
+import java.util.UUID;
/**
- *
* @author LoneFox
- *
*/
public final class FerozsBan extends CardImpl {
+ private static final FilterCard filter = new FilterCreatureCard("Creature spells");
+
public FerozsBan(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}");
// Creature spells cost {2} more to cast.
- Effect effect = new SpellsCostIncreasementAllEffect(StaticFilters.FILTER_CARD_CREATURE, 2);
- effect.setText("Creature spells cost {2} more to cast.");
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(2, filter, TargetController.ANY)));
}
public FerozsBan(final FerozsBan card) {
diff --git a/Mage.Sets/src/mage/cards/f/FesteringGoblin.java b/Mage.Sets/src/mage/cards/f/FesteringGoblin.java
index 846165c4b54..a5d737259b4 100644
--- a/Mage.Sets/src/mage/cards/f/FesteringGoblin.java
+++ b/Mage.Sets/src/mage/cards/f/FesteringGoblin.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class FesteringGoblin extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
- Ability ability = new DiesTriggeredAbility(new BoostTargetEffect(-1, -1, Duration.EndOfTurn), false);
+ Ability ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(-1, -1, Duration.EndOfTurn), false);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/f/FesteringMummy.java b/Mage.Sets/src/mage/cards/f/FesteringMummy.java
index ce2d4cc4baf..9278a6c6a99 100644
--- a/Mage.Sets/src/mage/cards/f/FesteringMummy.java
+++ b/Mage.Sets/src/mage/cards/f/FesteringMummy.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -27,7 +27,7 @@ public final class FesteringMummy extends CardImpl {
this.toughness = new MageInt(1);
// When Festering Mummy dies, you may put a -1/-1 counter on target creature.
- Ability ability = new DiesTriggeredAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()), true);
+ Ability ability = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()), true);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/f/FesteringNewt.java b/Mage.Sets/src/mage/cards/f/FesteringNewt.java
index d0219fe32cf..21b616b3b6c 100644
--- a/Mage.Sets/src/mage/cards/f/FesteringNewt.java
+++ b/Mage.Sets/src/mage/cards/f/FesteringNewt.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
@@ -45,7 +45,7 @@ public final class FesteringNewt extends CardImpl {
new BoostTargetEffect(-1,-1, Duration.EndOfTurn),
new LockedInCondition(new PermanentsOnTheBattlefieldCondition(filterBogbrewWitch)),
"target creature an opponent controls gets -1/-1 until end of turn. That creature gets -4/-4 instead if you control a creature named Bogbrew Witch");
- Ability ability = new DiesTriggeredAbility(effect);
+ Ability ability = new DiesSourceTriggeredAbility(effect);
ability.addTarget(new TargetCreaturePermanent(filterCreature));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java b/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java
index e4eca676bdb..f2241456540 100644
--- a/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java
+++ b/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java
@@ -1,8 +1,8 @@
package mage.cards.f;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTappedAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -33,8 +33,8 @@ public final class FieldOfTheDead extends CardImpl {
// Whenever Field of the Dead or another land enters the battlefield under your control, if you control seven or more lands with different names, create a 2/2 black Zombie creature token.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
- new EntersBattlefieldControlledTriggeredAbility(
- new CreateTokenEffect(new ZombieToken()), StaticFilters.FILTER_LAND
+ new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new CreateTokenEffect(new ZombieToken()), StaticFilters.FILTER_LAND, false, true
), FieldOfTheDeadCondition.instance, "Whenever {this} or another land " +
"enters the battlefield under your control, if you control seven or more lands with different names, " +
"create a 2/2 black Zombie creature token."
diff --git a/Mage.Sets/src/mage/cards/f/FieryEmancipation.java b/Mage.Sets/src/mage/cards/f/FieryEmancipation.java
new file mode 100644
index 00000000000..0c6009ef967
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/f/FieryEmancipation.java
@@ -0,0 +1,77 @@
+package mage.cards.f;
+
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.util.CardUtil;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class FieryEmancipation extends CardImpl {
+
+ public FieryEmancipation(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}{R}");
+
+ // If a source you control would deal damage to a permanent or player, it deals triple that damage to that permanent or player instead.
+ this.addAbility(new SimpleStaticAbility(new FieryEmancipationEffect()));
+ }
+
+ private FieryEmancipation(final FieryEmancipation card) {
+ super(card);
+ }
+
+ @Override
+ public FieryEmancipation copy() {
+ return new FieryEmancipation(this);
+ }
+}
+
+class FieryEmancipationEffect extends ReplacementEffectImpl {
+
+ FieryEmancipationEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.Damage);
+ staticText = "If a source you control would deal damage to a permanent or player, " +
+ "it deals triple that damage to that permanent or player instead";
+ }
+
+ private FieryEmancipationEffect(final FieryEmancipationEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public FieryEmancipationEffect copy() {
+ return new FieryEmancipationEffect(this);
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER)
+ || event.getType().equals(GameEvent.EventType.DAMAGE_CREATURE)
+ || event.getType().equals(GameEvent.EventType.DAMAGE_PLANESWALKER);
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ return game.getControllerId(event.getSourceId()).equals(source.getControllerId());
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ event.setAmount(CardUtil.addWithOverflowCheck(
+ CardUtil.addWithOverflowCheck(
+ event.getAmount(), event.getAmount()
+ ), event.getAmount()
+ ));
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/f/FieryHellhound.java b/Mage.Sets/src/mage/cards/f/FieryHellhound.java
index 62815a4ed5e..8381f487ef1 100644
--- a/Mage.Sets/src/mage/cards/f/FieryHellhound.java
+++ b/Mage.Sets/src/mage/cards/f/FieryHellhound.java
@@ -23,7 +23,7 @@ public final class FieryHellhound extends CardImpl {
public FieryHellhound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}");
this.subtype.add(SubType.ELEMENTAL);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/f/FiligreeAngel.java b/Mage.Sets/src/mage/cards/f/FiligreeAngel.java
index 638f78ff107..2f060359038 100644
--- a/Mage.Sets/src/mage/cards/f/FiligreeAngel.java
+++ b/Mage.Sets/src/mage/cards/f/FiligreeAngel.java
@@ -1,34 +1,30 @@
-
-
package mage.cards.f;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.effects.OneShotEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
-import mage.filter.FilterPermanent;
-import mage.filter.common.FilterControlledPermanent;
+import mage.constants.SubType;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class FiligreeAngel extends CardImpl {
- public FiligreeAngel (UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{5}{W}{W}{U}");
+ public FiligreeAngel(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}{W}{W}{U}");
this.subtype.add(SubType.ANGEL);
-
-
this.power = new MageInt(4);
this.toughness = new MageInt(4);
@@ -36,10 +32,10 @@ public final class FiligreeAngel extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Filigree Angel enters the battlefield, you gain 3 life for each artifact you control.
- this.addAbility(new EntersBattlefieldTriggeredAbility(new FiligreeAngelEffect()));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new FiligreeAngelEffect()).addHint(ArtifactYouControlHint.instance));
}
- public FiligreeAngel (final FiligreeAngel card) {
+ public FiligreeAngel(final FiligreeAngel card) {
super(card);
}
@@ -50,12 +46,6 @@ public final class FiligreeAngel extends CardImpl {
}
class FiligreeAngelEffect extends OneShotEffect {
-
- private static final FilterPermanent filter = new FilterControlledPermanent();
-
- static {
- filter.add(CardType.ARTIFACT.getPredicate());
- }
public FiligreeAngelEffect() {
super(Outcome.GainLife);
@@ -70,7 +60,7 @@ class FiligreeAngelEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
- int life = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) * 3;
+ int life = ArtifactYouControlCount.instance.calculate(game, source, this) * 3;
player.gainLife(life, game, source);
}
return true;
diff --git a/Mage.Sets/src/mage/cards/f/FiligreeCrawler.java b/Mage.Sets/src/mage/cards/f/FiligreeCrawler.java
index 3edcd09dfa2..c0ab6710dc4 100644
--- a/Mage.Sets/src/mage/cards/f/FiligreeCrawler.java
+++ b/Mage.Sets/src/mage/cards/f/FiligreeCrawler.java
@@ -3,7 +3,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class FiligreeCrawler extends CardImpl {
this.toughness = new MageInt(2);
// When Filigree Crawler dies, create a 1/1 colorless Thopter artifact creature token with flying.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken())));
}
public FiligreeCrawler(final FiligreeCrawler card) {
diff --git a/Mage.Sets/src/mage/cards/f/FiligreeFamiliar.java b/Mage.Sets/src/mage/cards/f/FiligreeFamiliar.java
index 854c79187c0..50a977f31ff 100644
--- a/Mage.Sets/src/mage/cards/f/FiligreeFamiliar.java
+++ b/Mage.Sets/src/mage/cards/f/FiligreeFamiliar.java
@@ -3,7 +3,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.GainLifeEffect;
@@ -28,7 +28,7 @@ public final class FiligreeFamiliar extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2), false));
// When Filigree Familiar dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public FiligreeFamiliar(final FiligreeFamiliar card) {
diff --git a/Mage.Sets/src/mage/cards/f/FiligreeFracture.java b/Mage.Sets/src/mage/cards/f/FiligreeFracture.java
index efcf412747f..98eb2eb6ed7 100644
--- a/Mage.Sets/src/mage/cards/f/FiligreeFracture.java
+++ b/Mage.Sets/src/mage/cards/f/FiligreeFracture.java
@@ -61,7 +61,7 @@ class FiligreeFractureEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (player != null && permanent != null) {
permanent.destroy(source.getSourceId(), game, true);
- game.applyEffects();
+ game.getState().processAction(game);
if (permanent.getColor(game).isBlack() || permanent.getColor(game).isBlue()) {
player.drawCards(1, source.getSourceId(), game);
}
diff --git a/Mage.Sets/src/mage/cards/f/FilthyCur.java b/Mage.Sets/src/mage/cards/f/FilthyCur.java
index 9864aec0122..e47525388a8 100644
--- a/Mage.Sets/src/mage/cards/f/FilthyCur.java
+++ b/Mage.Sets/src/mage/cards/f/FilthyCur.java
@@ -23,7 +23,7 @@ public final class FilthyCur extends CardImpl {
public FilthyCur(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/f/FinishingBlow.java b/Mage.Sets/src/mage/cards/f/FinishingBlow.java
new file mode 100644
index 00000000000..8376ef033d5
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/f/FinishingBlow.java
@@ -0,0 +1,32 @@
+package mage.cards.f;
+
+import mage.abilities.effects.common.DestroyTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.target.common.TargetCreatureOrPlaneswalker;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class FinishingBlow extends CardImpl {
+
+ public FinishingBlow(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{B}");
+
+ // Destroy target creature or planeswalker.
+ this.getSpellAbility().addEffect(new DestroyTargetEffect());
+ this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker());
+ }
+
+ private FinishingBlow(final FinishingBlow card) {
+ super(card);
+ }
+
+ @Override
+ public FinishingBlow copy() {
+ return new FinishingBlow(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/f/FireJuggler.java b/Mage.Sets/src/mage/cards/f/FireJuggler.java
index 87cd678002d..d2ede0bfae9 100644
--- a/Mage.Sets/src/mage/cards/f/FireJuggler.java
+++ b/Mage.Sets/src/mage/cards/f/FireJuggler.java
@@ -3,7 +3,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.DamageAllEffect;
import mage.abilities.effects.common.DoIfClashWonEffect;
import mage.cards.CardImpl;
@@ -30,7 +30,7 @@ public final class FireJuggler extends CardImpl {
// Whenever Fire Juggler becomes blocked, clash with an opponent. If you win, Fire Juggler deals 4 damage to each creature blocking it.
FilterPermanent filter = new FilterPermanent("each creature blocking it");
filter.add(new BlockingAttackerIdPredicate(this.getId()));
- this.addAbility(new BecomesBlockedTriggeredAbility(new DoIfClashWonEffect(new DamageAllEffect(4,filter)),false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new DoIfClashWonEffect(new DamageAllEffect(4,filter)),false));
}
public FireJuggler(final FireJuggler card) {
diff --git a/Mage.Sets/src/mage/cards/f/FireSnake.java b/Mage.Sets/src/mage/cards/f/FireSnake.java
index 2f6dca506d7..1a042533916 100644
--- a/Mage.Sets/src/mage/cards/f/FireSnake.java
+++ b/Mage.Sets/src/mage/cards/f/FireSnake.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class FireSnake extends CardImpl {
this.toughness = new MageInt(1);
// When Fire Snake dies, destroy target land.
- Ability ability = new DiesTriggeredAbility(new DestroyTargetEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DestroyTargetEffect(), false);
ability.addTarget(new TargetLandPermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/f/FirebladeArtist.java b/Mage.Sets/src/mage/cards/f/FirebladeArtist.java
index e11b412cc7b..5568d06ee3b 100644
--- a/Mage.Sets/src/mage/cards/f/FirebladeArtist.java
+++ b/Mage.Sets/src/mage/cards/f/FirebladeArtist.java
@@ -1,21 +1,18 @@
package mage.cards.f;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
-import mage.abilities.effects.common.DoIfCostPaid;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
+import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.filter.StaticFilters;
-import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetOpponentOrPlaneswalker;
@@ -38,15 +35,15 @@ public final class FirebladeArtist extends CardImpl {
this.addAbility(HasteAbility.getInstance());
// At the beginning of your upkeep, you may sacrifice a creature. When you do, Fireblade Artist deals 2 damage to target opponent or planeswalker.
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new DamageTargetEffect(2), false,
+ "{this} deals 2 damage to target opponent or planeswalker"
+ );
+ ability.addTarget(new TargetOpponentOrPlaneswalker());
this.addAbility(new BeginningOfUpkeepTriggeredAbility(
- new DoIfCostPaid(
- new FirebladeArtistCreateReflexiveTriggerEffect(),
- new SacrificeTargetCost(new TargetControlledPermanent(
- StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT
- )), "Sacrifice a creature to deal 2 damage to an opponent or planeswalker?"
- ).setText("you may sacrifice a creature. When you do, " +
- "{this} deals 2 damage to target opponent or planeswalker."),
- TargetController.YOU, false
+ new DoWhenCostPaid(ability, new SacrificeTargetCost(
+ new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT)
+ ), "Sacrifice a creature?"), TargetController.YOU, false
));
}
@@ -59,58 +56,3 @@ public final class FirebladeArtist extends CardImpl {
return new FirebladeArtist(this);
}
}
-
-class FirebladeArtistCreateReflexiveTriggerEffect extends OneShotEffect {
-
- FirebladeArtistCreateReflexiveTriggerEffect() {
- super(Outcome.Benefit);
- }
-
- private FirebladeArtistCreateReflexiveTriggerEffect(final FirebladeArtistCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public FirebladeArtistCreateReflexiveTriggerEffect copy() {
- return new FirebladeArtistCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new FirebladeArtistReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class FirebladeArtistReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- FirebladeArtistReflexiveTriggeredAbility() {
- super(new DamageTargetEffect(2), Duration.OneUse, true);
- this.addTarget(new TargetOpponentOrPlaneswalker());
- }
-
- private FirebladeArtistReflexiveTriggeredAbility(final FirebladeArtistReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public FirebladeArtistReflexiveTriggeredAbility copy() {
- return new FirebladeArtistReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "{this} deals 2 damage to target opponent or planeswalker.";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/f/FlailingDrake.java b/Mage.Sets/src/mage/cards/f/FlailingDrake.java
index 3083f1c918c..db8dd6a8555 100644
--- a/Mage.Sets/src/mage/cards/f/FlailingDrake.java
+++ b/Mage.Sets/src/mage/cards/f/FlailingDrake.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.keyword.FlyingAbility;
@@ -32,7 +32,7 @@ public final class FlailingDrake extends CardImpl {
// Whenever Flailing Drake blocks or becomes blocked by a creature, that creature gets +1/+1 until end of turn.
Effect effect = new BoostTargetEffect(+1, +1, Duration.EndOfTurn);
effect.setText("that creature gets +1/+1 until end of turn");
- Ability ability = new BlocksOrBecomesBlockedTriggeredAbility(effect, new FilterCreaturePermanent("a creature"), false, null, true);
+ Ability ability = new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, new FilterCreaturePermanent("a creature"), false, null, true);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/f/FlameSweep.java b/Mage.Sets/src/mage/cards/f/FlameSweep.java
index 5fb3d7b6c20..6b27948005b 100644
--- a/Mage.Sets/src/mage/cards/f/FlameSweep.java
+++ b/Mage.Sets/src/mage/cards/f/FlameSweep.java
@@ -51,8 +51,6 @@ enum FlameSweepPredicate implements ObjectPlayerPredicate ability.getClass().equals(FlyingAbility.class)
- ));
+ && object.getAbilities(game).containsClass(FlyingAbility.class));
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java b/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java
index e3a72038456..fda65cb18dc 100644
--- a/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java
+++ b/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.TributeNotPaidCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
@@ -39,7 +39,7 @@ public final class FlameWreathedPhoenix extends CardImpl {
this.addAbility(new TributeAbility(2));
// When Flame-Wreathed Phoenix enters the battlefield, if its tribute wasn't paid, it gains haste and "When this creature dies, return it to its owner's hand."
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield));
- Effect effect = new GainAbilitySourceEffect(new DiesTriggeredAbility(new ReturnToHandSourceEffect()));
+ Effect effect = new GainAbilitySourceEffect(new DiesSourceTriggeredAbility(new ReturnToHandSourceEffect()));
ability.addEffect(effect);
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance,
"When {this} enters the battlefield, if its tribute wasn't paid, it gains haste and \"When this creature dies, return it to its owner's hand.\""));
diff --git a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java
index 05ebb2bfe67..10fcf26864d 100644
--- a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java
+++ b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -36,7 +36,7 @@ public final class FlameheartWerewolf extends CardImpl {
this.transformable = true;
// Whenever Flameheart Werewolf blocks or becomes blocked by a creature, Flameheart Werewolf deals 2 damage to that creature.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new DamageTargetEffect(2, true, "that creature"),
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new DamageTargetEffect(2, true, "that creature"),
StaticFilters.FILTER_PERMANENT_CREATURE, false, null, true));
// At the beginning of each upkeep, if a player cast two or more spells last turn, transform Flameheart Werewolf.
diff --git a/Mage.Sets/src/mage/cards/f/FlaxenIntruder.java b/Mage.Sets/src/mage/cards/f/FlaxenIntruder.java
index 105e7d16c03..c64ba61968d 100644
--- a/Mage.Sets/src/mage/cards/f/FlaxenIntruder.java
+++ b/Mage.Sets/src/mage/cards/f/FlaxenIntruder.java
@@ -1,24 +1,17 @@
package mage.cards.f;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
-import mage.abilities.effects.common.DoIfCostPaid;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
+import mage.abilities.effects.common.DoWhenCostPaid;
import mage.cards.AdventureCard;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.StaticFilters;
-import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.game.permanent.token.BearToken;
import mage.target.TargetPermanent;
@@ -38,9 +31,13 @@ public final class FlaxenIntruder extends AdventureCard {
this.toughness = new MageInt(2);
// Whenever Flaxen Intruder deals combat damage to a player, you may sacrifice it. When you do, destroy target artifact or enchantment.
- this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DoIfCostPaid(
- new FlaxenIntruderCreateReflexiveTriggerEffect(), new SacrificeSourceCost()
- ).setText("you may sacrifice it. When you do, destroy target artifact or enchantment."), false));
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new DestroyTargetEffect(), false, "destroy target artifact or enchantment"
+ );
+ ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
+ this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DoWhenCostPaid(
+ ability, new SacrificeSourceCost(), "Sacrifice {this}?"
+ ), false));
// Welcome Home
// Create three 2/2 green Bear creature tokens.
@@ -56,58 +53,3 @@ public final class FlaxenIntruder extends AdventureCard {
return new FlaxenIntruder(this);
}
}
-
-class FlaxenIntruderCreateReflexiveTriggerEffect extends OneShotEffect {
-
- FlaxenIntruderCreateReflexiveTriggerEffect() {
- super(Outcome.Benefit);
- }
-
- private FlaxenIntruderCreateReflexiveTriggerEffect(final FlaxenIntruderCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public FlaxenIntruderCreateReflexiveTriggerEffect copy() {
- return new FlaxenIntruderCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new FlaxenIntruderReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class FlaxenIntruderReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- FlaxenIntruderReflexiveTriggeredAbility() {
- super(new DestroyTargetEffect(), Duration.OneUse, true);
- this.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
- }
-
- private FlaxenIntruderReflexiveTriggeredAbility(final FlaxenIntruderReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public FlaxenIntruderReflexiveTriggeredAbility copy() {
- return new FlaxenIntruderReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When you do, destroy target artifact or enchantment.";
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/f/FlayerOfTheHatebound.java b/Mage.Sets/src/mage/cards/f/FlayerOfTheHatebound.java
index b22d7cd6892..c25c1cc6fbf 100644
--- a/Mage.Sets/src/mage/cards/f/FlayerOfTheHatebound.java
+++ b/Mage.Sets/src/mage/cards/f/FlayerOfTheHatebound.java
@@ -73,7 +73,7 @@ class FlayerTriggeredAbility extends TriggeredAbilityImpl {
if (permanent != null
&& ((EntersTheBattlefieldEvent) event).getFromZone() == Zone.GRAVEYARD
&& permanent.isOwnedBy(controllerId)
- && permanent.isCreature()) {
+ && (permanent.isCreature() || permanent.getId().equals(getSourceId()))) {
Effect effect = this.getEffects().get(0);
effect.setValue("damageSource", event.getTargetId());
return true;
diff --git a/Mage.Sets/src/mage/cards/f/FleshCarver.java b/Mage.Sets/src/mage/cards/f/FleshCarver.java
index 96e7e22f3a4..1ef0f7f28a2 100644
--- a/Mage.Sets/src/mage/cards/f/FleshCarver.java
+++ b/Mage.Sets/src/mage/cards/f/FleshCarver.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -63,7 +63,7 @@ public final class FleshCarver extends CardImpl {
}
}
-class FleshCarverAbility extends DiesTriggeredAbility {
+class FleshCarverAbility extends DiesSourceTriggeredAbility {
public FleshCarverAbility() {
super(new FleshCarverEffect(), false);
diff --git a/Mage.Sets/src/mage/cards/f/FlightSpellbomb.java b/Mage.Sets/src/mage/cards/f/FlightSpellbomb.java
index 2d5368f786d..35162b4f3a0 100644
--- a/Mage.Sets/src/mage/cards/f/FlightSpellbomb.java
+++ b/Mage.Sets/src/mage/cards/f/FlightSpellbomb.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
@@ -32,7 +32,7 @@ public final class FlightSpellbomb extends CardImpl {
ability.addCost(new SacrificeSourceCost());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
- this.addAbility(new DiesTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{U}")), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{U}")), false));
}
public FlightSpellbomb (final FlightSpellbomb card) {
diff --git a/Mage.Sets/src/mage/cards/f/FlintGolem.java b/Mage.Sets/src/mage/cards/f/FlintGolem.java
index f78c9e2e67b..53fd61c3aed 100644
--- a/Mage.Sets/src/mage/cards/f/FlintGolem.java
+++ b/Mage.Sets/src/mage/cards/f/FlintGolem.java
@@ -46,7 +46,7 @@ class FlintGolemEffect extends OneShotEffect {
public FlintGolemEffect() {
super(Outcome.Detriment);
- this.staticText = "defending player puts the top three cards of their library into their graveyard";
+ this.staticText = "defending player mills three cards";
}
public FlintGolemEffect(final FlintGolemEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/f/FloatingDreamZubera.java b/Mage.Sets/src/mage/cards/f/FloatingDreamZubera.java
index f2e77e0b509..ad4c7fd2529 100644
--- a/Mage.Sets/src/mage/cards/f/FloatingDreamZubera.java
+++ b/Mage.Sets/src/mage/cards/f/FloatingDreamZubera.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.ZuberasDiedDynamicValue;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
@@ -25,7 +25,7 @@ public final class FloatingDreamZubera extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(2);
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(ZuberasDiedDynamicValue.instance)), new ZuberasDiedWatcher());
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(ZuberasDiedDynamicValue.instance)), new ZuberasDiedWatcher());
}
public FloatingDreamZubera(final FloatingDreamZubera card) {
diff --git a/Mage.Sets/src/mage/cards/f/Fluctuator.java b/Mage.Sets/src/mage/cards/f/Fluctuator.java
index c0a1e52d08d..29433b881df 100644
--- a/Mage.Sets/src/mage/cards/f/Fluctuator.java
+++ b/Mage.Sets/src/mage/cards/f/Fluctuator.java
@@ -1,8 +1,5 @@
package mage.cards.f;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
@@ -16,8 +13,11 @@ import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class Fluctuator extends CardImpl {
@@ -69,7 +69,7 @@ class FluctuatorEffect extends CostModificationEffectImpl {
}
if (reduceMax > 0) {
int reduce;
- if (game.inCheckPlayableState()) {
+ if (game.inCheckPlayableState() || !controller.isHuman()) {
reduce = reduceMax;
} else {
ChoiceImpl choice = new ChoiceImpl(true);
diff --git a/Mage.Sets/src/mage/cards/f/FogPatch.java b/Mage.Sets/src/mage/cards/f/FogPatch.java
index 7c62a881193..7e054f6c074 100644
--- a/Mage.Sets/src/mage/cards/f/FogPatch.java
+++ b/Mage.Sets/src/mage/cards/f/FogPatch.java
@@ -66,7 +66,7 @@ class FogPatchEffect extends OneShotEffect {
if (attacker != null) {
CombatGroup combatGroup = game.getCombat().findGroup(attacker.getId());
if (combatGroup != null) {
- combatGroup.setBlocked(true);
+ combatGroup.setBlocked(true, game);
}
}
}
diff --git a/Mage.Sets/src/mage/cards/f/FolioOfFancies.java b/Mage.Sets/src/mage/cards/f/FolioOfFancies.java
index 191fe2c06d0..1f81cc0be1c 100644
--- a/Mage.Sets/src/mage/cards/f/FolioOfFancies.java
+++ b/Mage.Sets/src/mage/cards/f/FolioOfFancies.java
@@ -9,18 +9,16 @@ import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.game.Game;
import mage.players.Player;
-import java.util.Collection;
-import java.util.Objects;
-import java.util.Set;
import java.util.UUID;
-import java.util.stream.Collectors;
/**
* @author TheElk801
@@ -63,8 +61,7 @@ class FolioOfFanciesEffect extends OneShotEffect {
FolioOfFanciesEffect() {
super(Outcome.Benefit);
- staticText = "Each opponent puts a number of cards equal to the number of cards in their hand " +
- "from the top of their library into their graveyard.";
+ staticText = "each opponent mills cards equal to the number of cards in their hand";
}
private FolioOfFanciesEffect(final FolioOfFanciesEffect effect) {
@@ -82,14 +79,13 @@ class FolioOfFanciesEffect extends OneShotEffect {
if (controller == null) {
return false;
}
- Set cards = game.getOpponents(source.getControllerId())
- .stream()
- .map(game::getPlayer)
- .filter(Objects::nonNull)
- .filter(player -> !player.getHand().isEmpty())
- .map(player -> player.getLibrary().getTopCards(game, player.getHand().size()))
- .flatMap(Collection::stream)
- .collect(Collectors.toSet());
- return controller.moveCards(cards, Zone.GRAVEYARD, source, game);
+ for (UUID playerId : game.getOpponents(source.getControllerId())) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
+ }
+ player.millCards(player.getHand().size(), source, game);
+ }
+ return true;
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/f/FootlightFiend.java b/Mage.Sets/src/mage/cards/f/FootlightFiend.java
index 6d7d41f9794..08d0071347f 100644
--- a/Mage.Sets/src/mage/cards/f/FootlightFiend.java
+++ b/Mage.Sets/src/mage/cards/f/FootlightFiend.java
@@ -2,7 +2,7 @@ package mage.cards.f;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class FootlightFiend extends CardImpl {
this.toughness = new MageInt(1);
// When Footlight Fiend dies, it deals 1 damage to any target.
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(1, "it"));
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(1, "it"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/f/Foresee.java b/Mage.Sets/src/mage/cards/f/Foresee.java
index 52b112e3a0c..d081d3acc76 100644
--- a/Mage.Sets/src/mage/cards/f/Foresee.java
+++ b/Mage.Sets/src/mage/cards/f/Foresee.java
@@ -16,8 +16,9 @@ public final class Foresee extends CardImpl {
public Foresee(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}");
- this.getSpellAbility().addEffect(new ScryEffect(4).setText("scry 4,"));
- this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2).setText("then draw two cards"));
+ // Scry 4, then draw two cards. (To scry 4, look at the top four cards of your library, then put any number of them on the bottom of your library and the rest on top in any order.)
+ this.getSpellAbility().addEffect(new ScryEffect(4, false));
+ this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2).concatBy(", then"));
}
public Foresee(final Foresee card) {
diff --git a/Mage.Sets/src/mage/cards/f/Foreshadow.java b/Mage.Sets/src/mage/cards/f/Foreshadow.java
index bfa869d0659..2ac311b6f3d 100644
--- a/Mage.Sets/src/mage/cards/f/Foreshadow.java
+++ b/Mage.Sets/src/mage/cards/f/Foreshadow.java
@@ -11,7 +11,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
@@ -49,12 +48,12 @@ public final class Foreshadow extends CardImpl {
class ForeshadowEffect extends OneShotEffect {
- public ForeshadowEffect() {
+ ForeshadowEffect() {
super(Outcome.DrawCard);
- this.staticText = "target opponent puts the top card of their library into their graveyard. If that card has the chosen name, you draw a card";
+ this.staticText = "target opponent mills a card. If that card has the chosen name, you draw a card";
}
- public ForeshadowEffect(final ForeshadowEffect effect) {
+ private ForeshadowEffect(final ForeshadowEffect effect) {
super(effect);
}
@@ -68,17 +67,16 @@ class ForeshadowEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) {
- Card card = targetPlayer.getLibrary().getFromTop(game);
- if (card != null) {
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
- controller.drawCards(1, source.getSourceId(), game);
- }
- }
- return true;
+ if (controller == null || targetPlayer == null || cardName == null || cardName.isEmpty()) {
+ return false;
}
- return false;
+ for (Card card : targetPlayer.millCards(1, source, game).getCards(game)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
+ controller.drawCards(1, source.getSourceId(), game);
+ break;
+ }
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/f/ForgottenSentinel.java b/Mage.Sets/src/mage/cards/f/ForgottenSentinel.java
new file mode 100644
index 00000000000..cfdcd623621
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/f/ForgottenSentinel.java
@@ -0,0 +1,36 @@
+package mage.cards.f;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTappedAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ForgottenSentinel extends CardImpl {
+
+ public ForgottenSentinel(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}");
+
+ this.subtype.add(SubType.GOLEM);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(3);
+
+ // Forgotten Sentinel enters the battlefield tapped.
+ this.addAbility(new EntersBattlefieldTappedAbility());
+ }
+
+ private ForgottenSentinel(final ForgottenSentinel card) {
+ super(card);
+ }
+
+ @Override
+ public ForgottenSentinel copy() {
+ return new ForgottenSentinel(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/f/ForkedBolt.java b/Mage.Sets/src/mage/cards/f/ForkedBolt.java
index cf57dc2b75c..83db5716c5b 100644
--- a/Mage.Sets/src/mage/cards/f/ForkedBolt.java
+++ b/Mage.Sets/src/mage/cards/f/ForkedBolt.java
@@ -1,7 +1,5 @@
-
package mage.cards.f;
-import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageMultiEffect;
import mage.cards.CardImpl;
@@ -9,22 +7,21 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetAnyTargetAmount;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
*/
public final class ForkedBolt extends CardImpl {
public ForkedBolt(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{R}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}");
// Forked Bolt deals 2 damage divided as you choose among one or two target creatures and/or players.
Effect effect = new DamageMultiEffect(2);
effect.setText("{this} deals 2 damage divided as you choose among one or two target creatures and/or players");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(2));
-
}
public ForkedBolt(final ForkedBolt card) {
diff --git a/Mage.Sets/src/mage/cards/f/ForsakenDrifters.java b/Mage.Sets/src/mage/cards/f/ForsakenDrifters.java
index cf624e8dce7..822954776da 100644
--- a/Mage.Sets/src/mage/cards/f/ForsakenDrifters.java
+++ b/Mage.Sets/src/mage/cards/f/ForsakenDrifters.java
@@ -3,7 +3,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class ForsakenDrifters extends CardImpl {
this.toughness = new MageInt(2);
// When Forsaken Drifters dies, put the top four cards of your library into your graveyard.
- this.addAbility(new DiesTriggeredAbility(new PutTopCardOfLibraryIntoGraveControllerEffect(4)));
+ this.addAbility(new DiesSourceTriggeredAbility(new PutTopCardOfLibraryIntoGraveControllerEffect(4)));
}
public ForsakenDrifters(final ForsakenDrifters card) {
diff --git a/Mage.Sets/src/mage/cards/f/FoulTongueShriek.java b/Mage.Sets/src/mage/cards/f/FoulTongueShriek.java
index fda28291705..725a760e578 100644
--- a/Mage.Sets/src/mage/cards/f/FoulTongueShriek.java
+++ b/Mage.Sets/src/mage/cards/f/FoulTongueShriek.java
@@ -1,28 +1,26 @@
-
package mage.cards.f;
-import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.dynamicvalue.common.AttackingFilterCreatureCount;
+import mage.abilities.dynamicvalue.common.AttackingCreatureCount;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.TargetController;
-import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class FoulTongueShriek extends CardImpl {
public FoulTongueShriek(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
// Target opponent loses 1 life for each attacking creature you control. You gain that much life.
this.getSpellAbility().addEffect(new FoulTongueShriekEffect());
@@ -41,12 +39,7 @@ public final class FoulTongueShriek extends CardImpl {
}
class FoulTongueShriekEffect extends OneShotEffect {
-
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
- static {
- filter.add(TargetController.YOU.getControllerPredicate());
- }
-
+
public FoulTongueShriekEffect() {
super(Outcome.Benefit);
this.staticText = "Target opponent loses 1 life for each attacking creature you control. You gain that much life";
@@ -66,7 +59,7 @@ class FoulTongueShriekEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player targetOpponent = game.getPlayer(getTargetPointer().getFirst(game, source));
if (controller != null && targetOpponent != null) {
- int amount = new AttackingFilterCreatureCount(filter).calculate(game, source, this);
+ int amount = new AttackingCreatureCount(StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED).calculate(game, source, this);
if (amount > 0) {
targetOpponent.loseLife(amount, game, false);
controller.gainLife(amount, game, source);
diff --git a/Mage.Sets/src/mage/cards/f/FracturingGust.java b/Mage.Sets/src/mage/cards/f/FracturingGust.java
index c54bb8b1f14..4da56870aef 100644
--- a/Mage.Sets/src/mage/cards/f/FracturingGust.java
+++ b/Mage.Sets/src/mage/cards/f/FracturingGust.java
@@ -67,7 +67,7 @@ class FracturingGustDestroyEffect extends OneShotEffect {
++destroyedPermanents;
}
}
- game.applyEffects(); // needed in case a destroyed permanent did prevent life gain
+ game.getState().processAction(game); // needed in case a destroyed permanent did prevent life gain
if (destroyedPermanents > 0) {
controller.gainLife(2 * destroyedPermanents, game, source);
}
diff --git a/Mage.Sets/src/mage/cards/f/FranticInventory.java b/Mage.Sets/src/mage/cards/f/FranticInventory.java
new file mode 100644
index 00000000000..7ab40c6030b
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/f/FranticInventory.java
@@ -0,0 +1,44 @@
+package mage.cards.f;
+
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.filter.FilterCard;
+import mage.filter.predicate.mageobject.NamePredicate;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class FranticInventory extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard();
+
+ static {
+ filter.add(new NamePredicate("Frantic Inventory"));
+ }
+
+ private static final DynamicValue xValue = new CardsInControllerGraveyardCount(filter);
+
+ public FranticInventory(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
+
+ // Draw a card, then draw cards equal to the number of cards named Frantic Inventory in your graveyard.
+ this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
+ this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(xValue)
+ .setText(", then draw cards equal to the number of cards named Frantic Inventory in your graveyard"));
+ }
+
+ private FranticInventory(final FranticInventory card) {
+ super(card);
+ }
+
+ @Override
+ public FranticInventory copy() {
+ return new FranticInventory(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/f/FrayingSanity.java b/Mage.Sets/src/mage/cards/f/FrayingSanity.java
index 56f444ed24d..92ea0d99339 100644
--- a/Mage.Sets/src/mage/cards/f/FrayingSanity.java
+++ b/Mage.Sets/src/mage/cards/f/FrayingSanity.java
@@ -83,7 +83,7 @@ class FrayingSanityTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "At the beginning of each end step, enchanted player puts the top X cards of their library into their graveyard, where X is the total number of cards put into their graveyard from anywhere this turn.";
+ return "At the beginning of each end step, enchanted player mills X cards, where X is the total number of cards put into their graveyard from anywhere this turn.";
}
}
@@ -117,8 +117,8 @@ class FrayingSanityEffect extends OneShotEffect {
if (watcher != null) {
xAmount = watcher.getAmountCardsPutToGraveyard(enchantedPlayer.getId());
}
- Set topXCardsFromLibrary = enchantedPlayer.getLibrary().getTopCards(game, xAmount);
- return enchantedPlayer.moveCards(topXCardsFromLibrary, Zone.GRAVEYARD, source, game, false, false, true, null);
+ enchantedPlayer.millCards(xAmount, source, game);
+ return true;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/f/FrogtosserBanneret.java b/Mage.Sets/src/mage/cards/f/FrogtosserBanneret.java
index 886577ba819..dd107b833f1 100644
--- a/Mage.Sets/src/mage/cards/f/FrogtosserBanneret.java
+++ b/Mage.Sets/src/mage/cards/f/FrogtosserBanneret.java
@@ -1,7 +1,5 @@
-
package mage.cards.f;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
@@ -14,8 +12,9 @@ import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class FrogtosserBanneret extends CardImpl {
@@ -29,7 +28,7 @@ public final class FrogtosserBanneret extends CardImpl {
}
public FrogtosserBanneret(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.GOBLIN);
this.subtype.add(SubType.ROGUE);
@@ -38,6 +37,7 @@ public final class FrogtosserBanneret extends CardImpl {
// Haste
this.addAbility(HasteAbility.getInstance());
+
// Goblin spells and Rogue spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
}
diff --git a/Mage.Sets/src/mage/cards/f/FromTheAshes.java b/Mage.Sets/src/mage/cards/f/FromTheAshes.java
index 77d8390df92..8dd0b42910b 100644
--- a/Mage.Sets/src/mage/cards/f/FromTheAshes.java
+++ b/Mage.Sets/src/mage/cards/f/FromTheAshes.java
@@ -76,7 +76,7 @@ class FromTheAshesEffect extends OneShotEffect {
playerAmount.put(playerId, amount);
}
}
- game.applyEffects();
+ game.getState().processAction(game);
for (Map.Entry entry : playerAmount.entrySet()) {
Player player = game.getPlayer(entry.getKey());
if (player != null && player.chooseUse(outcome, "Search your library for up to " + entry.getValue() + " basic land card(s) to put it onto the battlefield?", source, game)) {
@@ -90,7 +90,7 @@ class FromTheAshesEffect extends OneShotEffect {
entry.setValue(0); // no search no shuffling
}
}
- game.applyEffects();
+ game.getState().processAction(game);
for (Map.Entry entry : playerAmount.entrySet()) {
Player player = game.getPlayer(entry.getKey());
if (player != null && entry.getValue() > 0) {
diff --git a/Mage.Sets/src/mage/cards/f/Fry.java b/Mage.Sets/src/mage/cards/f/Fry.java
index c9c9f7eca34..faa409a226c 100644
--- a/Mage.Sets/src/mage/cards/f/Fry.java
+++ b/Mage.Sets/src/mage/cards/f/Fry.java
@@ -1,7 +1,7 @@
package mage.cards.f;
import mage.ObjectColor;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -33,7 +33,7 @@ public final class Fry extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}");
// This spell can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Fry deals 5 damage to target creature or planeswalker that's white or blue.
this.getSpellAbility().addEffect(new DamageTargetEffect(5));
diff --git a/Mage.Sets/src/mage/cards/f/Fumigate.java b/Mage.Sets/src/mage/cards/f/Fumigate.java
index 54a1d5cfee0..b74ef2339e4 100644
--- a/Mage.Sets/src/mage/cards/f/Fumigate.java
+++ b/Mage.Sets/src/mage/cards/f/Fumigate.java
@@ -62,7 +62,7 @@ class FumigateEffect extends OneShotEffect {
destroyedCreature++;
}
}
- game.applyEffects();
+ game.getState().processAction(game);
if (destroyedCreature > 0) {
controller.gainLife(destroyedCreature, game, source);
}
diff --git a/Mage.Sets/src/mage/cards/f/FungalRebirth.java b/Mage.Sets/src/mage/cards/f/FungalRebirth.java
new file mode 100644
index 00000000000..801d277449a
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/f/FungalRebirth.java
@@ -0,0 +1,46 @@
+package mage.cards.f;
+
+import mage.abilities.condition.common.MorbidCondition;
+import mage.abilities.decorator.ConditionalOneShotEffect;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.filter.StaticFilters;
+import mage.game.permanent.token.SaprolingToken;
+import mage.target.common.TargetCardInYourGraveyard;
+import mage.watchers.common.MorbidWatcher;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class FungalRebirth extends CardImpl {
+
+ public FungalRebirth(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}");
+
+ // Return target permanent card from your graveyard to your hand. If a creature died this turn, create two 1/1 green Saproling creature tokens.
+ getSpellAbility().addEffect(
+ new ReturnFromGraveyardToHandTargetEffect().setText("Return target permanent card from your graveyard to your hand")
+ );
+ getSpellAbility().addWatcher(new MorbidWatcher());
+ getSpellAbility().addEffect(new ConditionalOneShotEffect(
+ new CreateTokenEffect(new SaprolingToken(), 2),
+ MorbidCondition.instance,
+ "If a creature died this turn, create two 1/1 green Saproling creature tokens"));
+ getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_PERMANENT));
+ }
+
+ private FungalRebirth(final FungalRebirth card) {
+ super(card);
+ }
+
+ @Override
+ public FungalRebirth copy() {
+ return new FungalRebirth(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/f/FurnaceDragon.java b/Mage.Sets/src/mage/cards/f/FurnaceDragon.java
index 8f508a93bb4..92a267b0db1 100644
--- a/Mage.Sets/src/mage/cards/f/FurnaceDragon.java
+++ b/Mage.Sets/src/mage/cards/f/FurnaceDragon.java
@@ -4,7 +4,7 @@ package mage.cards.f;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.ExileAllEffect;
import mage.abilities.keyword.AffinityForArtifactsAbility;
@@ -43,7 +43,7 @@ public final class FurnaceDragon extends CardImpl {
// When Furnace Dragon enters the battlefield, if you cast it from your hand, exile all artifacts.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new ExileAllEffect(filter), false),
- CastFromHandSourceCondition.instance,
+ CastFromHandSourcePermanentCondition.instance,
"When {this} enters the battlefield, if you cast it from your hand, exile all artifacts."),
new CastFromHandWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/f/FyndhornDruid.java b/Mage.Sets/src/mage/cards/f/FyndhornDruid.java
index a1b1fb15afa..5c3f7b50cb3 100644
--- a/Mage.Sets/src/mage/cards/f/FyndhornDruid.java
+++ b/Mage.Sets/src/mage/cards/f/FyndhornDruid.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
@@ -31,7 +31,7 @@ public final class FyndhornDruid extends CardImpl {
this.toughness = new MageInt(2);
// When Fyndhorn Druid dies, if it was blocked this turn, you gain 4 life.
- this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesTriggeredAbility(new GainLifeEffect(4)), new SourceWasBlockedThisTurnCondition(),
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(4)), new SourceWasBlockedThisTurnCondition(),
"When {this} dies, if it was blocked this turn, you gain 4 life."), new WasBlockedThisTurnWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/g/GaddockTeeg.java b/Mage.Sets/src/mage/cards/g/GaddockTeeg.java
index a18c4d4bd6a..bc8b26b2fcf 100644
--- a/Mage.Sets/src/mage/cards/g/GaddockTeeg.java
+++ b/Mage.Sets/src/mage/cards/g/GaddockTeeg.java
@@ -48,7 +48,7 @@ class GaddockTeegReplacementEffect4 extends ContinuousRuleModifyingEffectImpl {
public GaddockTeegReplacementEffect4() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
- staticText = "Noncreature spells with converted mana cost 4 or greater can't be cast. Noncreature spells with {X} in their mana costs can't be cast.";
+ staticText = "Noncreature spells with converted mana cost 4 or greater can't be cast. Noncreature spells with {X} in their mana costs can't be cast";
}
public GaddockTeegReplacementEffect4(final GaddockTeegReplacementEffect4 effect) {
@@ -85,7 +85,7 @@ class GaddockTeegReplacementEffectX extends ContinuousRuleModifyingEffectImpl {
public GaddockTeegReplacementEffectX() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
- staticText = "Noncreature spells with {X} in their mana costs can't be cast.";
+ staticText = "Noncreature spells with {X} in their mana costs can't be cast";
}
public GaddockTeegReplacementEffectX(final GaddockTeegReplacementEffectX effect) {
diff --git a/Mage.Sets/src/mage/cards/g/GadrakTheCrownScourge.java b/Mage.Sets/src/mage/cards/g/GadrakTheCrownScourge.java
new file mode 100644
index 00000000000..2fd15a1465e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GadrakTheCrownScourge.java
@@ -0,0 +1,126 @@
+package mage.cards.g;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
+import mage.abilities.decorator.ConditionalRestrictionEffect;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.combat.CantAttackSourceEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.ZoneChangeEvent;
+import mage.game.permanent.PermanentToken;
+import mage.game.permanent.token.TreasureToken;
+import mage.watchers.Watcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class GadrakTheCrownScourge extends CardImpl {
+
+ private static final Condition condition = new PermanentsOnTheBattlefieldCondition(
+ StaticFilters.FILTER_PERMANENT_ARTIFACT, ComparisonType.FEWER_THAN, 4
+ );
+
+ public GadrakTheCrownScourge(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.DRAGON);
+ this.power = new MageInt(5);
+ this.toughness = new MageInt(4);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Gadrak, the Crown-Scourge can't attack unless you control four or more artifacts.
+ this.addAbility(new SimpleStaticAbility(new ConditionalRestrictionEffect(
+ new CantAttackSourceEffect(Duration.WhileOnBattlefield), condition,
+ "{this} can't attack unless you control four or more artifacts"
+ )));
+
+ // At the beginning of your end step, create a Treasure token for each nontoken creature that died this turn.
+ this.addAbility(new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(
+ new TreasureToken(), GadrakTheCrownScourgeValue.instance
+ ), TargetController.YOU, false), new GadrakTheCrownScourgeWatcher());
+ }
+
+ private GadrakTheCrownScourge(final GadrakTheCrownScourge card) {
+ super(card);
+ }
+
+ @Override
+ public GadrakTheCrownScourge copy() {
+ return new GadrakTheCrownScourge(this);
+ }
+}
+
+enum GadrakTheCrownScourgeValue implements DynamicValue {
+ instance;
+
+ @Override
+ public int calculate(Game game, Ability sourceAbility, Effect effect) {
+ GadrakTheCrownScourgeWatcher watcher = game.getState().getWatcher(GadrakTheCrownScourgeWatcher.class);
+ return watcher != null ? watcher.getDiedThisTurn() : 0;
+ }
+
+ @Override
+ public GadrakTheCrownScourgeValue copy() {
+ return instance;
+ }
+
+ @Override
+ public String getMessage() {
+ return "nontoken creature that died this turn";
+ }
+
+ @Override
+ public String toString() {
+ return "1";
+ }
+}
+
+class GadrakTheCrownScourgeWatcher extends Watcher {
+
+ private int diedThisTurn = 0;
+
+ GadrakTheCrownScourgeWatcher() {
+ super(WatcherScope.GAME);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() != GameEvent.EventType.ZONE_CHANGE) {
+ return;
+ }
+ ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
+ if (zEvent.isDiesEvent()
+ && zEvent.getTarget() != null
+ && zEvent.getTarget().isCreature()
+ && !(zEvent.getTarget() instanceof PermanentToken)) {
+ diedThisTurn++;
+ }
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ diedThisTurn = 0;
+ }
+
+ int getDiedThisTurn() {
+ return diedThisTurn;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GaeasBlessing.java b/Mage.Sets/src/mage/cards/g/GaeasBlessing.java
index 62b9516c83c..e3de06d4a51 100644
--- a/Mage.Sets/src/mage/cards/g/GaeasBlessing.java
+++ b/Mage.Sets/src/mage/cards/g/GaeasBlessing.java
@@ -1,7 +1,6 @@
package mage.cards.g;
-import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.ZoneChangeTriggeredAbility;
@@ -10,6 +9,7 @@ import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -68,24 +68,9 @@ class GaeasBlessingEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getFirstTarget());
- if (player != null) {
- List targets = source.getTargets().get(1).getTargets();
- boolean shuffle = false;
- for (UUID targetId : targets) {
- Card card = game.getCard(targetId);
- if (card != null) {
- if (player.getGraveyard().contains(card.getId())) {
- player.getGraveyard().remove(card);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- shuffle = true;
- }
- }
- }
- if (shuffle) {
- player.shuffleLibrary(source, game);
- }
- return true;
+ Player targetPlayer = game.getPlayer(source.getFirstTarget());
+ if (targetPlayer != null) {
+ return targetPlayer.shuffleCardsToLibrary(new CardsImpl(source.getTargets().get(1).getTargets()), game, source);
}
return false;
}
@@ -155,14 +140,7 @@ class GaeasBlessingGraveToLibraryEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- game.informPlayers(controller.getLogName() + " shuffle their graveyard into their library");
- for (Card card : controller.getGraveyard().getCards(game)) {
- controller.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.GRAVEYARD, true, true);
- }
- controller.getLibrary().addAll(controller.getGraveyard().getCards(game), game);
- controller.getGraveyard().clear();
- controller.shuffleLibrary(source, game);
- return true;
+ return controller.shuffleCardsToLibrary(controller.getGraveyard(), game, source);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/g/GaleSwooper.java b/Mage.Sets/src/mage/cards/g/GaleSwooper.java
new file mode 100644
index 00000000000..14130beddf2
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GaleSwooper.java
@@ -0,0 +1,48 @@
+package mage.cards.g;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class GaleSwooper extends CardImpl {
+
+ public GaleSwooper(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
+
+ this.subtype.add(SubType.GRIFFIN);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(2);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // When Gale Swooper enters the battlefield, target creature gains flying until end of turn.
+ Ability ability = new EntersBattlefieldTriggeredAbility(
+ new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn)
+ );
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ }
+
+ private GaleSwooper(final GaleSwooper card) {
+ super(card);
+ }
+
+ @Override
+ public GaleSwooper copy() {
+ return new GaleSwooper(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/Gamekeeper.java b/Mage.Sets/src/mage/cards/g/Gamekeeper.java
index d3e3ef3ab02..967860a4e2d 100644
--- a/Mage.Sets/src/mage/cards/g/Gamekeeper.java
+++ b/Mage.Sets/src/mage/cards/g/Gamekeeper.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.RevealCardsFromLibraryUntilEffect;
@@ -27,7 +27,7 @@ public final class Gamekeeper extends CardImpl {
this.toughness = new MageInt(2);
// When Gamekeeper dies, you may exile it. If you do, reveal cards from the top of your library until you reveal a creature card. Put that card onto the battlefield and put all other cards revealed this way into your graveyard.
- Ability ability = new DiesTriggeredAbility(new DoIfCostPaid(new RevealCardsFromLibraryUntilEffect(StaticFilters.FILTER_CARD_CREATURE, Zone.BATTLEFIELD, Zone.GRAVEYARD), new ExileSourceFromGraveCost(), "Exile to reveal cards from the top of your library until you reveal a creature card?"), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DoIfCostPaid(new RevealCardsFromLibraryUntilEffect(StaticFilters.FILTER_CARD_CREATURE, Zone.BATTLEFIELD, Zone.GRAVEYARD), new ExileSourceFromGraveCost(), "Exile to reveal cards from the top of your library until you reveal a creature card?"), false);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GangOfDevils.java b/Mage.Sets/src/mage/cards/g/GangOfDevils.java
index 551c096e7ac..db51d712d77 100644
--- a/Mage.Sets/src/mage/cards/g/GangOfDevils.java
+++ b/Mage.Sets/src/mage/cards/g/GangOfDevils.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageMultiEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -27,7 +27,7 @@ public final class GangOfDevils extends CardImpl {
this.toughness = new MageInt(3);
// When Gang of Devils dies, it deals 3 damage divided as you choose among one, two, or three target creatures and/or players.
- Ability ability = new DiesTriggeredAbility(new DamageMultiEffect(3, "it"));
+ Ability ability = new DiesSourceTriggeredAbility(new DamageMultiEffect(3, "it"));
ability.addTarget(new TargetAnyTargetAmount(3));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GangOfElk.java b/Mage.Sets/src/mage/cards/g/GangOfElk.java
index 3a9ce2c366c..5372dfaedc6 100644
--- a/Mage.Sets/src/mage/cards/g/GangOfElk.java
+++ b/Mage.Sets/src/mage/cards/g/GangOfElk.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.MultipliedValue;
import mage.abilities.dynamicvalue.common.BlockedCreatureCount;
@@ -33,7 +33,7 @@ public final class GangOfElk extends CardImpl {
DynamicValue value = new MultipliedValue(new BlockedCreatureCount(), 2);
Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn, true);
effect.setText("it gets +2/+2 until end of turn for each creature blocking it");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public GangOfElk(final GangOfElk card) {
diff --git a/Mage.Sets/src/mage/cards/g/GargoyleSentinel.java b/Mage.Sets/src/mage/cards/g/GargoyleSentinel.java
index a3240598e95..5e7f34fc2c6 100644
--- a/Mage.Sets/src/mage/cards/g/GargoyleSentinel.java
+++ b/Mage.Sets/src/mage/cards/g/GargoyleSentinel.java
@@ -66,7 +66,7 @@ class GargoyleSentinelEffect extends ContinuousEffectImpl {
switch (layer) {
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
- permanent.getAbilities().removeIf(entry -> entry.getId().equals(DefenderAbility.getInstance().getId()));
+ permanent.removeAbility(DefenderAbility.getInstance(), source.getSourceId(), game);
permanent.getAbilities().add(FlyingAbility.getInstance());
}
break;
diff --git a/Mage.Sets/src/mage/cards/g/GarrisonCat.java b/Mage.Sets/src/mage/cards/g/GarrisonCat.java
index cb8a54b5127..5050906846b 100644
--- a/Mage.Sets/src/mage/cards/g/GarrisonCat.java
+++ b/Mage.Sets/src/mage/cards/g/GarrisonCat.java
@@ -1,7 +1,7 @@
package mage.cards.g;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class GarrisonCat extends CardImpl {
this.toughness = new MageInt(1);
// When Garrison Cat dies, create a 1/1 white Human Soldier creature token.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new HumanSoldierToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new HumanSoldierToken())));
}
private GarrisonCat(final GarrisonCat card) {
diff --git a/Mage.Sets/src/mage/cards/g/GarrukSavageHerald.java b/Mage.Sets/src/mage/cards/g/GarrukSavageHerald.java
new file mode 100644
index 00000000000..5d2aaf48a86
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GarrukSavageHerald.java
@@ -0,0 +1,113 @@
+package mage.cards.g;
+
+import mage.abilities.Ability;
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.DamageAsThoughNotBlockedAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect;
+import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.constants.Zone;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.AnotherTargetPredicate;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetControlledCreaturePermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class GarrukSavageHerald extends CardImpl {
+
+ public GarrukSavageHerald(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{G}{G}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.GARRUK);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(5));
+
+ // +1: Reveal the top card of your library. If it's a creature card, put it into your hand. Otherwise, put it on the bottom of your library.
+ this.addAbility(new LoyaltyAbility(new GarrukSavageHeraldEffect(), 1));
+
+ // −2: Target creature you control deals damage equal to its power to another target creature.
+ Effect effect = new DamageWithPowerFromOneToAnotherTargetEffect();
+ effect.setText("Target creature you control deals damage equal to its power to another target creature");
+
+ Ability minusAbility = new LoyaltyAbility(effect, -2);
+ TargetControlledCreaturePermanent controlledCreature = new TargetControlledCreaturePermanent();
+ controlledCreature.setTargetTag(1);
+ minusAbility.addTarget(controlledCreature);
+
+ FilterCreaturePermanent filter = new FilterCreaturePermanent();
+ filter.add(new AnotherTargetPredicate(2));
+ TargetCreaturePermanent anotherTargetCreature = new TargetCreaturePermanent(filter);
+ minusAbility.addTarget(anotherTargetCreature.withChooseHint("another creature to deal damage to"));
+
+ this.addAbility(minusAbility);
+
+ // −7: Until end of turn, creatures you control gain "You may have this creature assign its combat damage as though it weren't blocked."
+ ContinuousEffect ultimateEffect = new GainAbilityControlledEffect(DamageAsThoughNotBlockedAbility.getInstance(), Duration.EndOfTurn);
+ ultimateEffect.setText("Until end of turn, creatures you control gain \"You may have this creature assign its combat damage as though it weren't blocked.\"");
+ this.addAbility(new LoyaltyAbility(ultimateEffect, -7));
+ }
+
+ private GarrukSavageHerald(final GarrukSavageHerald card) {
+ super(card);
+ }
+
+ @Override
+ public GarrukSavageHerald copy() {
+ return new GarrukSavageHerald(this);
+ }
+}
+
+class GarrukSavageHeraldEffect extends OneShotEffect {
+
+ GarrukSavageHeraldEffect() {
+ super(Outcome.Benefit);
+ staticText = "reveal the top card of your library. If it's a creature card, " +
+ "put it into your hand. Otherwise, put it on the bottom of your library";
+ }
+
+ private GarrukSavageHeraldEffect(final GarrukSavageHeraldEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public GarrukSavageHeraldEffect copy() {
+ return new GarrukSavageHeraldEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null) {
+ return false;
+ }
+ Card card = player.getLibrary().getFromTop(game);
+ if (card == null) {
+ return false;
+ }
+ player.revealCards(source, new CardsImpl(card), game);
+ if (card.isCreature()) {
+ return player.moveCards(card, Zone.HAND, source, game);
+ } else {
+ return player.putCardsOnBottomOfLibrary(card, game, source, false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/g/GarrukUnleashed.java b/Mage.Sets/src/mage/cards/g/GarrukUnleashed.java
new file mode 100644
index 00000000000..44e56a1345d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GarrukUnleashed.java
@@ -0,0 +1,71 @@
+package mage.cards.g;
+
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.condition.common.OpponentControlsMoreCondition;
+import mage.abilities.decorator.ConditionalOneShotEffect;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.GetEmblemEffect;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.effects.common.counter.AddCountersSourceEffect;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.counters.CounterType;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.game.command.emblems.GarrukUnleashedEmblem;
+import mage.game.permanent.token.BeastToken;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class GarrukUnleashed extends CardImpl {
+
+ public GarrukUnleashed(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{G}{G}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.GARRUK);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
+
+ // +1: Up to one target creature gets +3/+3 and gains trample until end of turn.
+ Effect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn)
+ .setText("up to one target creature gets +3/+3");
+ LoyaltyAbility ability = new LoyaltyAbility(effect, 1);
+ effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn)
+ .setText("and gains trample until end of turn");
+ ability.addEffect(effect);
+ ability.addTarget(new TargetCreaturePermanent(0, 1));
+ this.addAbility(ability);
+
+ // −2: Create a 3/3 green Beast creature token. Then if an opponent controls more creatures than you, put a loyalty counter on Garruk, Unleashed.
+ ability = new LoyaltyAbility(new CreateTokenEffect(new BeastToken()), -2);
+ ability.addEffect(new ConditionalOneShotEffect(
+ new AddCountersSourceEffect(CounterType.LOYALTY.createInstance()),
+ new OpponentControlsMoreCondition(new FilterCreaturePermanent()))
+ .setText("Then if an opponent controls more creatures than you, put a loyalty counter on {this}"));
+ this.addAbility(ability);
+
+ // −7: You get an emblem with "At the beginning of your end step, you may search your library for a creature card, put it onto the battlefield, then shuffle your library."
+ this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new GarrukUnleashedEmblem()), -7));
+ }
+
+ private GarrukUnleashed(final GarrukUnleashed card) {
+ super(card);
+ }
+
+ @Override
+ public GarrukUnleashed copy() {
+ return new GarrukUnleashed(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GarruksGorehorn.java b/Mage.Sets/src/mage/cards/g/GarruksGorehorn.java
new file mode 100644
index 00000000000..237734487ff
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GarruksGorehorn.java
@@ -0,0 +1,32 @@
+package mage.cards.g;
+
+import mage.MageInt;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class GarruksGorehorn extends CardImpl {
+
+ public GarruksGorehorn(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}");
+
+ this.subtype.add(SubType.BEAST);
+ this.power = new MageInt(7);
+ this.toughness = new MageInt(3);
+ }
+
+ private GarruksGorehorn(final GarruksGorehorn card) {
+ super(card);
+ }
+
+ @Override
+ public GarruksGorehorn copy() {
+ return new GarruksGorehorn(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GarruksHarbinger.java b/Mage.Sets/src/mage/cards/g/GarruksHarbinger.java
new file mode 100644
index 00000000000..1d21b265a21
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GarruksHarbinger.java
@@ -0,0 +1,86 @@
+package mage.cards.g;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
+import mage.abilities.dynamicvalue.common.StaticValue;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
+import mage.abilities.keyword.HexproofFromBlackAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.filter.FilterCard;
+import mage.filter.predicate.Predicates;
+import mage.game.Game;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class GarruksHarbinger extends CardImpl {
+
+ public GarruksHarbinger(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{G}");
+
+ this.subtype.add(SubType.BEAST);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(3);
+
+ // Hexproof from Black
+ this.addAbility(HexproofFromBlackAbility.getInstance());
+
+ // Whenever Garruk's Harbinger deals combat damage to a player or planeswalker, look at that many cards from the top of your library. You may reveal a creature card or Garruk planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
+ this.addAbility(
+ new DealsCombatDamageToAPlayerTriggeredAbility(new GarruksHarbingerEffect(), false, true)
+ .setOrPlaneswalker(true)
+ );
+ }
+
+ private GarruksHarbinger(final GarruksHarbinger card) {
+ super(card);
+ }
+
+ @Override
+ public GarruksHarbinger copy() {
+ return new GarruksHarbinger(this);
+ }
+}
+
+class GarruksHarbingerEffect extends OneShotEffect {
+
+ private static final FilterCard filter = new FilterCard("a creature or Garruk planeswalker card");
+
+ static {
+ filter.add(Predicates.or(CardType.CREATURE.getPredicate(), Predicates.and(CardType.PLANESWALKER.getPredicate(), SubType.GARRUK.getPredicate())));
+ }
+
+ GarruksHarbingerEffect() {
+ super(Outcome.Benefit);
+ staticText = "look at that many cards from the top of your library. You may reveal a creature card or Garruk planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in a random order";
+ }
+
+ private GarruksHarbingerEffect(GarruksHarbingerEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public GarruksHarbingerEffect copy() {
+ return new GarruksHarbingerEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Integer damage = (Integer) getValue("damage");
+ if (damage != null) {
+ LookLibraryAndPickControllerEffect effect = new LookLibraryAndPickControllerEffect(StaticValue.get(damage), false, StaticValue.get(1), filter, false);
+ effect.setBackInRandomOrder(true);
+ return effect.apply(game, source);
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/g/GarruksUprising.java b/Mage.Sets/src/mage/cards/g/GarruksUprising.java
new file mode 100644
index 00000000000..4ed2994409e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GarruksUprising.java
@@ -0,0 +1,65 @@
+package mage.cards.g;
+
+import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.FerociousCondition;
+import mage.abilities.decorator.ConditionalOneShotEffect;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
+import mage.abilities.hint.common.FerociousHint;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.ComparisonType;
+import mage.constants.Duration;
+import mage.constants.Zone;
+import mage.filter.FilterPermanent;
+import mage.filter.StaticFilters;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.PowerPredicate;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class GarruksUprising extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterCreaturePermanent("a creature with power 4 or greater");
+
+ static {
+ filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3));
+ }
+
+ public GarruksUprising(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
+
+ // When Garruk's Uprising enters the battlefield, if you control a creature with power 4 or greater, draw a card.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(
+ new DrawCardSourceControllerEffect(1), FerociousCondition.instance))
+ .addHint(FerociousHint.instance));
+
+ // Creatures you control have trample.
+ this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
+ TrampleAbility.getInstance(), Duration.WhileOnBattlefield,
+ StaticFilters.FILTER_PERMANENT_CREATURES
+ )));
+
+ // Whenever a creature with power 4 or greater enters the battlefield under your control, draw a card.
+ this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
+ Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), filter, false
+ ));
+ }
+
+ private GarruksUprising(final GarruksUprising card) {
+ super(card);
+ }
+
+ @Override
+ public GarruksUprising copy() {
+ return new GarruksUprising(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GarruksWarsteed.java b/Mage.Sets/src/mage/cards/g/GarruksWarsteed.java
new file mode 100644
index 00000000000..8652a4ad3b4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GarruksWarsteed.java
@@ -0,0 +1,50 @@
+package mage.cards.g;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect;
+import mage.abilities.keyword.VigilanceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterCard;
+import mage.filter.predicate.mageobject.NamePredicate;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class GarruksWarsteed extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard("Garruk, Savage Herald");
+
+ static {
+ filter.add(new NamePredicate("Garruk, Savage Herald"));
+ }
+
+ public GarruksWarsteed(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
+
+ this.subtype.add(SubType.RHINO);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(5);
+
+ // Vigilance
+ this.addAbility(VigilanceAbility.getInstance());
+
+ // When Garruk's Warsteed enters the battlefield, you may search your library and/or graveyard for a card named Garruk, Savage Herald, reveal it, and put it into your hand. If you search your library this way, shuffle it.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryGraveyardPutInHandEffect(filter, false, true)));
+ }
+
+ private GarruksWarsteed(final GarruksWarsteed card) {
+ super(card);
+ }
+
+ @Override
+ public GarruksWarsteed copy() {
+ return new GarruksWarsteed(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GateColossus.java b/Mage.Sets/src/mage/cards/g/GateColossus.java
index 42420c65f44..000c9e26924 100644
--- a/Mage.Sets/src/mage/cards/g/GateColossus.java
+++ b/Mage.Sets/src/mage/cards/g/GateColossus.java
@@ -5,9 +5,11 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.common.SimpleEvasionAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.common.GateYouControlCount;
import mage.abilities.effects.common.PutOnLibrarySourceEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
import mage.abilities.hint.common.GateYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -39,8 +41,10 @@ public final class GateColossus extends CardImpl {
this.toughness = new MageInt(8);
// This spell costs {1} less to cast for each Gate you control.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new GateColossusCostReductionEffect())
- .addHint(GateYouControlHint.instance));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL,
+ new SpellCostReductionForEachSourceEffect(1, GateYouControlCount.instance))
+ .addHint(GateYouControlHint.instance)
+ );
// Gate Colossus can't be blocked by creatures with power 2 or less.
this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield)));
@@ -84,9 +88,7 @@ class GateColossusCostReductionEffect extends CostModificationEffectImpl {
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
int count = game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game).size();
- if (count > 0) {
- CardUtil.reduceCost(abilityToModify, count);
- }
+ CardUtil.reduceCost(abilityToModify, count);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/g/GateHound.java b/Mage.Sets/src/mage/cards/g/GateHound.java
index c25ebded1b1..357df06b8fb 100644
--- a/Mage.Sets/src/mage/cards/g/GateHound.java
+++ b/Mage.Sets/src/mage/cards/g/GateHound.java
@@ -24,7 +24,7 @@ public final class GateHound extends CardImpl {
public GateHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/g/GatekeeperGargoyle.java b/Mage.Sets/src/mage/cards/g/GatekeeperGargoyle.java
index 43a32187775..b112771820c 100644
--- a/Mage.Sets/src/mage/cards/g/GatekeeperGargoyle.java
+++ b/Mage.Sets/src/mage/cards/g/GatekeeperGargoyle.java
@@ -29,7 +29,7 @@ public final class GatekeeperGargoyle extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
- // Gargoyle Guardian enters the battlefield with a +1/+1 counter on it for each Gate you control.
+ // Gatekeeper Gargoyle enters the battlefield with a +1/+1 counter on it for each Gate you control.
this.addAbility(new EntersBattlefieldAbility(
new AddCountersSourceEffect(
CounterType.P1P1.createInstance(),
diff --git a/Mage.Sets/src/mage/cards/g/GearseekerSerpent.java b/Mage.Sets/src/mage/cards/g/GearseekerSerpent.java
index f4fffd3401d..8b955be6077 100644
--- a/Mage.Sets/src/mage/cards/g/GearseekerSerpent.java
+++ b/Mage.Sets/src/mage/cards/g/GearseekerSerpent.java
@@ -1,35 +1,37 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.filter.common.FilterControlledPermanent;
-import mage.game.Game;
-import mage.util.CardUtil;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.Zone;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class GearseekerSerpent extends CardImpl {
public GearseekerSerpent(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}");
this.subtype.add(SubType.SERPENT);
this.power = new MageInt(5);
this.toughness = new MageInt(6);
// Gearseeker Serpent costs {1} less to cast for each artifact you control
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new GearseekerSerpentCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL,
+ new SpellCostReductionForEachSourceEffect(1, ArtifactYouControlCount.instance)
+ ).addHint(ArtifactYouControlHint.instance));
// 5U: Gearseeker Serpent can't be blocked this turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
@@ -46,41 +48,3 @@ public final class GearseekerSerpent extends CardImpl {
return new GearseekerSerpent(this);
}
}
-
-class GearseekerSerpentCostReductionEffect extends CostModificationEffectImpl {
-
- private static final FilterControlledPermanent filter = new FilterControlledPermanent();
-
- static {
- filter.add(CardType.ARTIFACT.getPredicate());
- }
-
- public GearseekerSerpentCostReductionEffect() {
- super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {1} less to cast for each artifact you control";
- }
-
- protected GearseekerSerpentCostReductionEffect(final GearseekerSerpentCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- int count = game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game).size();
- if (count > 0) {
- CardUtil.reduceCost(abilityToModify, count);
- }
-
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- return abilityToModify.getSourceId().equals(source.getSourceId());
- }
-
- @Override
- public GearseekerSerpentCostReductionEffect copy() {
- return new GearseekerSerpentCostReductionEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/g/GeistFueledScarecrow.java b/Mage.Sets/src/mage/cards/g/GeistFueledScarecrow.java
index 2393e2b07b1..b64c673afbd 100644
--- a/Mage.Sets/src/mage/cards/g/GeistFueledScarecrow.java
+++ b/Mage.Sets/src/mage/cards/g/GeistFueledScarecrow.java
@@ -1,24 +1,23 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementControllerEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
+import java.util.UUID;
+
/**
- *
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public final class GeistFueledScarecrow extends CardImpl {
-
+
private static final FilterCard filter = new FilterCard("Creature spells");
static {
@@ -26,14 +25,14 @@ public final class GeistFueledScarecrow extends CardImpl {
}
public GeistFueledScarecrow(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}");
this.subtype.add(SubType.SCARECROW);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Creature spells you cast cost {1} more to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
- new SpellsCostIncreasementControllerEffect(filter, new ManaCostsImpl("{1}"))));
+ new SpellsCostIncreasingAllEffect(1, filter, TargetController.YOU)));
}
public GeistFueledScarecrow(final GeistFueledScarecrow card) {
diff --git a/Mage.Sets/src/mage/cards/g/GeistHonoredMonk.java b/Mage.Sets/src/mage/cards/g/GeistHonoredMonk.java
index 879fce467c0..d6d1174281e 100644
--- a/Mage.Sets/src/mage/cards/g/GeistHonoredMonk.java
+++ b/Mage.Sets/src/mage/cards/g/GeistHonoredMonk.java
@@ -38,7 +38,7 @@ public final class GeistHonoredMonk extends CardImpl {
.addHint(CreaturesYouControlHint.instance));
// When Geist-Honored Monk enters the battlefield, create two 1/1 white Spirit creature tokens with flying.
- this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken("ISD"), 2)));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken(), 2)));
}
public GeistHonoredMonk(final GeistHonoredMonk card) {
diff --git a/Mage.Sets/src/mage/cards/g/GeneralKudroOfDrannith.java b/Mage.Sets/src/mage/cards/g/GeneralKudroOfDrannith.java
index 4a24e6d9346..a9c81282e63 100644
--- a/Mage.Sets/src/mage/cards/g/GeneralKudroOfDrannith.java
+++ b/Mage.Sets/src/mage/cards/g/GeneralKudroOfDrannith.java
@@ -2,7 +2,7 @@ package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
@@ -32,7 +32,7 @@ public final class GeneralKudroOfDrannith extends CardImpl {
private static final FilterCreaturePermanent filter
= new FilterCreaturePermanent(SubType.HUMAN, "Humans");
private static final FilterPermanent filter2
- = new FilterPermanent(SubType.HUMAN, "{this} or another Human");
+ = new FilterPermanent(SubType.HUMAN, "Human");
private static final FilterCard filter3
= new FilterCard("card from an opponent's graveyard");
private static final FilterControlledPermanent filter4
@@ -59,7 +59,7 @@ public final class GeneralKudroOfDrannith extends CardImpl {
)));
// Whenever General Kudro of Drannith or another Human enters the battlefield under your control, exile target card from an opponent's graveyard.
- Ability ability = new EntersBattlefieldControlledTriggeredAbility(new ExileTargetEffect(), filter2);
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(new ExileTargetEffect(), filter2, false, true);
ability.addTarget(new TargetCardInOpponentsGraveyard(filter3));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/g/GeralfsMessenger.java b/Mage.Sets/src/mage/cards/g/GeralfsMessenger.java
index f2445f84dd6..347c139b77c 100644
--- a/Mage.Sets/src/mage/cards/g/GeralfsMessenger.java
+++ b/Mage.Sets/src/mage/cards/g/GeralfsMessenger.java
@@ -1,7 +1,5 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTappedAbility;
@@ -14,14 +12,15 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class GeralfsMessenger extends CardImpl {
public GeralfsMessenger(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(3);
@@ -29,10 +28,12 @@ public final class GeralfsMessenger extends CardImpl {
// Geralf's Messenger enters the battlefield tapped.
this.addAbility(new EntersBattlefieldTappedAbility());
+
// When Geralf's Messenger enters the battlefield, target opponent loses 2 life.
Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(2));
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
+
// Undying
this.addAbility(new UndyingAbility());
}
diff --git a/Mage.Sets/src/mage/cards/g/GerrardWeatherlightHero.java b/Mage.Sets/src/mage/cards/g/GerrardWeatherlightHero.java
index 63374c19733..9e627ba1b4e 100644
--- a/Mage.Sets/src/mage/cards/g/GerrardWeatherlightHero.java
+++ b/Mage.Sets/src/mage/cards/g/GerrardWeatherlightHero.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.keyword.FirstStrikeAbility;
@@ -40,7 +40,7 @@ public final class GerrardWeatherlightHero extends CardImpl {
this.addAbility(FirstStrikeAbility.getInstance());
// When Gerrard, Weatherlight Hero dies, exile it and return to the battlefield all artifact and creature cards in your graveyard that were put there from the battlefield this turn.
- Ability ability = new DiesTriggeredAbility(new ExileSourceEffect().setText("exile it"));
+ Ability ability = new DiesSourceTriggeredAbility(new ExileSourceEffect().setText("exile it"));
ability.addEffect(new GerrardWeatherlightHeroEffect());
this.addAbility(ability, new GerrardWeatherlightHeroWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java b/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java
index 3db2f0e8b7d..6d96b9f29fe 100644
--- a/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java
+++ b/Mage.Sets/src/mage/cards/g/GethLordOfTheVault.java
@@ -1,6 +1,5 @@
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -10,12 +9,7 @@ import mage.abilities.keyword.IntimidateAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Outcome;
-import mage.constants.SuperType;
-import mage.constants.TargetController;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game;
@@ -23,6 +17,8 @@ import mage.players.Player;
import mage.target.common.TargetCardInGraveyard;
import mage.target.targetadjustment.XCMCGraveyardAdjuster;
+import java.util.UUID;
+
/**
* @author nantuko
*/
@@ -70,7 +66,7 @@ class GethLordOfTheVaultEffect extends OneShotEffect {
public GethLordOfTheVaultEffect() {
super(Outcome.Benefit);
- staticText = "Put target artifact or creature card with converted mana cost X from an opponent's graveyard onto the battlefield under your control tapped. Then that player puts the top X cards of their library into their graveyard";
+ staticText = "Put target artifact or creature card with converted mana cost X from an opponent's graveyard onto the battlefield under your control tapped. Then that player mills X cards";
}
public GethLordOfTheVaultEffect(final GethLordOfTheVaultEffect effect) {
@@ -80,18 +76,19 @@ class GethLordOfTheVaultEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Card card = game.getCard(getTargetPointer().getFirst(game, source));
- if (card != null) {
- controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
- Player player = game.getPlayer(card.getOwnerId());
- if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, card.getConvertedManaCost()), Zone.GRAVEYARD, source, game);
- }
- }
+ if (controller == null) {
+ return false;
+ }
+ Card card = game.getCard(getTargetPointer().getFirst(game, source));
+ if (card == null) {
return true;
}
- return false;
+ controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null);
+ Player player = game.getPlayer(card.getOwnerId());
+ if (player != null) {
+ player.millCards(card.getConvertedManaCost(), source, game);
+ }
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/g/GhaltaPrimalHunger.java b/Mage.Sets/src/mage/cards/g/GhaltaPrimalHunger.java
index e60680a5b6f..c4dcf0929cb 100644
--- a/Mage.Sets/src/mage/cards/g/GhaltaPrimalHunger.java
+++ b/Mage.Sets/src/mage/cards/g/GhaltaPrimalHunger.java
@@ -40,7 +40,7 @@ public final class GhaltaPrimalHunger extends CardImpl {
this.toughness = new MageInt(12);
// Ghalta, Primal Hunger costs {X} less to cast, where X is the total power of creatures you control.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new GhaltaPrimalHungerCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new GhaltaPrimalHungerCostReductionEffect()));
// Trample
this.addAbility(TrampleAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/g/GhostCouncilOfOrzhova.java b/Mage.Sets/src/mage/cards/g/GhostCouncilOfOrzhova.java
index e9181831f26..d4b7ec441a3 100644
--- a/Mage.Sets/src/mage/cards/g/GhostCouncilOfOrzhova.java
+++ b/Mage.Sets/src/mage/cards/g/GhostCouncilOfOrzhova.java
@@ -1,29 +1,28 @@
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.GenericManaCost;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileReturnBattlefieldOwnerNextEndStepSourceEffect;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
-import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
-import mage.game.Game;
-import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
+import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
+
/**
- *
* @author Loki
*/
public final class GhostCouncilOfOrzhova extends CardImpl {
@@ -37,7 +36,8 @@ public final class GhostCouncilOfOrzhova extends CardImpl {
this.toughness = new MageInt(4);
// When Ghost Council of Orzhova enters the battlefield, target opponent loses 1 life and you gain 1 life.
- Ability ability = new EntersBattlefieldTriggeredAbility(new GhostCouncilOfOrzhovaEffect());
+ Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(1));
+ ability.addEffect(new GainLifeEffect(1).concatBy("and"));
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
@@ -62,34 +62,3 @@ public final class GhostCouncilOfOrzhova extends CardImpl {
}
}
-
-class GhostCouncilOfOrzhovaEffect extends OneShotEffect {
-
- GhostCouncilOfOrzhovaEffect() {
- super(Outcome.GainLife);
- staticText = "target opponent loses 1 life and you gain 1 life";
- }
-
- GhostCouncilOfOrzhovaEffect(final GhostCouncilOfOrzhovaEffect effect) {
- super(effect);
- }
-
- @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) {
- targetPlayer.loseLife(1, game, false);
- controller.gainLife(1, game, source);
- return true;
- }
- return false;
- }
-
- @Override
- public GhostCouncilOfOrzhovaEffect copy() {
- return new GhostCouncilOfOrzhovaEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/g/GhostHounds.java b/Mage.Sets/src/mage/cards/g/GhostHounds.java
index 1dcdcad4650..6ec9ac4172f 100644
--- a/Mage.Sets/src/mage/cards/g/GhostHounds.java
+++ b/Mage.Sets/src/mage/cards/g/GhostHounds.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.VigilanceAbility;
@@ -31,7 +31,7 @@ public final class GhostHounds extends CardImpl {
public GhostHounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SPIRIT);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
@@ -40,7 +40,7 @@ public final class GhostHounds extends CardImpl {
this.addAbility(VigilanceAbility.getInstance());
// Whenever Ghost Hounds blocks or becomes blocked by a white creature, Ghost Hounds gains first strike until end of turn.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), filter, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), filter, false));
}
diff --git a/Mage.Sets/src/mage/cards/g/GhostlyFlicker.java b/Mage.Sets/src/mage/cards/g/GhostlyFlicker.java
index e69fb17a014..cf35f53a13a 100644
--- a/Mage.Sets/src/mage/cards/g/GhostlyFlicker.java
+++ b/Mage.Sets/src/mage/cards/g/GhostlyFlicker.java
@@ -81,7 +81,7 @@ class GhostlyFlickerEffect extends OneShotEffect {
}
}
controller.moveCards(toExile, Zone.EXILED, source, game);
- game.applyEffects();
+ game.getState().processAction(game);
Set toBattlefield = new HashSet<>();
for (Card card : toExile) {
Zone currentZone = game.getState().getZone(card.getId());
diff --git a/Mage.Sets/src/mage/cards/g/GhostlyPilferer.java b/Mage.Sets/src/mage/cards/g/GhostlyPilferer.java
new file mode 100644
index 00000000000..68ffecfd523
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GhostlyPilferer.java
@@ -0,0 +1,94 @@
+package mage.cards.g;
+
+import mage.MageInt;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.DiscardCardCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect;
+import mage.abilities.keyword.InspiredAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.stack.Spell;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class GhostlyPilferer extends CardImpl {
+
+ public GhostlyPilferer(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
+
+ this.subtype.add(SubType.SPIRIT);
+ this.subtype.add(SubType.ROGUE);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // Whenever Ghostly Pilferer becomes untapped, you may pay {2}. If you do, draw a card.
+ this.addAbility(new InspiredAbility(new DoIfCostPaid(
+ new DrawCardSourceControllerEffect(1), new GenericManaCost(2)
+ ), false, false));
+
+ // Whenever an opponent casts a spell from anywhere other than their hand, draw a card.
+ this.addAbility(new GhostlyPilfererTriggeredAbility());
+
+ // Discard a card: Ghostly Pilferer can't be blocked this turn.
+ this.addAbility(new SimpleActivatedAbility(
+ new CantBeBlockedSourceEffect(Duration.EndOfTurn), new DiscardCardCost()
+ ));
+ }
+
+ private GhostlyPilferer(final GhostlyPilferer card) {
+ super(card);
+ }
+
+ @Override
+ public GhostlyPilferer copy() {
+ return new GhostlyPilferer(this);
+ }
+}
+
+class GhostlyPilfererTriggeredAbility extends TriggeredAbilityImpl {
+
+ GhostlyPilfererTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false);
+ }
+
+ private GhostlyPilfererTriggeredAbility(final GhostlyPilfererTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public GhostlyPilfererTriggeredAbility copy() {
+ return new GhostlyPilfererTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.SPELL_CAST;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (event.getZone() == Zone.HAND) {
+ return false;
+ }
+ Spell spell = game.getStack().getSpell(event.getTargetId());
+ return spell != null;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever an opponent casts a spell from anywhere other than their hand, draw a card.";
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GhoulcallersBell.java b/Mage.Sets/src/mage/cards/g/GhoulcallersBell.java
index 6ad15678fbf..e7638cd5de8 100644
--- a/Mage.Sets/src/mage/cards/g/GhoulcallersBell.java
+++ b/Mage.Sets/src/mage/cards/g/GhoulcallersBell.java
@@ -1,22 +1,16 @@
-
package mage.cards.g;
-import java.util.UUID;
-import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.players.Player;
+import mage.constants.TargetController;
+
+import java.util.UUID;
/**
- *
* @author North
*/
public final class GhoulcallersBell extends CardImpl {
@@ -25,10 +19,10 @@ public final class GhoulcallersBell extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
// {T}: Each player puts the top card of their library into their graveyard.
- this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GhoulcallersBellEffect(), new TapSourceCost()));
+ this.addAbility(new SimpleActivatedAbility(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.ANY), new TapSourceCost()));
}
- public GhoulcallersBell(final GhoulcallersBell card) {
+ private GhoulcallersBell(final GhoulcallersBell card) {
super(card);
}
@@ -37,34 +31,3 @@ public final class GhoulcallersBell extends CardImpl {
return new GhoulcallersBell(this);
}
}
-
-class GhoulcallersBellEffect extends OneShotEffect {
-
- public GhoulcallersBellEffect() {
- super(Outcome.Discard);
- this.staticText = "Each player puts the top card of their library into their graveyard";
- }
-
- public GhoulcallersBellEffect(final GhoulcallersBellEffect effect) {
- super(effect);
- }
-
- @Override
- public GhoulcallersBellEffect copy() {
- return new GhoulcallersBellEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Card card = player.getLibrary().getFromTop(game);
- if (card != null) {
- player.moveCards(card, Zone.GRAVEYARD, source, game);
- }
- }
- }
- return true;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/g/Ghoultree.java b/Mage.Sets/src/mage/cards/g/Ghoultree.java
index 63a9982da0b..ae65b248300 100644
--- a/Mage.Sets/src/mage/cards/g/Ghoultree.java
+++ b/Mage.Sets/src/mage/cards/g/Ghoultree.java
@@ -1,9 +1,12 @@
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
+import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -11,8 +14,9 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class Ghoultree extends CardImpl {
@@ -26,7 +30,11 @@ public final class Ghoultree extends CardImpl {
this.toughness = new MageInt(10);
// Ghoultree costs {1} less to cast for each creature card in your graveyard.
- this.addAbility(new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_CREATURE)));
+ DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
+ ability.setRuleAtTheTop(true);
+ ability.addHint(new ValueHint("Creature card in your graveyard", xValue));
+ this.addAbility(ability);
}
public Ghoultree(final Ghoultree card) {
diff --git a/Mage.Sets/src/mage/cards/g/GiantAlbatross.java b/Mage.Sets/src/mage/cards/g/GiantAlbatross.java
index e81634de131..ceaa56f5b1f 100644
--- a/Mage.Sets/src/mage/cards/g/GiantAlbatross.java
+++ b/Mage.Sets/src/mage/cards/g/GiantAlbatross.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -39,7 +39,7 @@ public final class GiantAlbatross extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Giant Albatross dies, you may pay {1}{U}. If you do, for each creature that dealt damage to Giant Albatross this turn, destroy that creature unless its controller pays 2 life. A creature destroyed this way can't be regenerated.
- Ability ability = new DiesTriggeredAbility(new DoIfCostPaid(new GiantAlbatrossEffect(), new ManaCostsImpl("{1}{U}")));
+ Ability ability = new DiesSourceTriggeredAbility(new DoIfCostPaid(new GiantAlbatrossEffect(), new ManaCostsImpl("{1}{U}")));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GiantShark.java b/Mage.Sets/src/mage/cards/g/GiantShark.java
index 3adccfc3a95..9ebb586001e 100644
--- a/Mage.Sets/src/mage/cards/g/GiantShark.java
+++ b/Mage.Sets/src/mage/cards/g/GiantShark.java
@@ -2,7 +2,7 @@ package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.ControlsPermanentsControllerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.SacrificeSourceEffect;
@@ -43,7 +43,7 @@ public final class GiantShark extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackUnlessDefenderControllsPermanent(filter)));
// Whenever Giant Shark blocks or becomes blocked by a creature that has been dealt damage this turn, Giant Shark gets +2/+0 and gains trample until end of turn.
- Ability ability = new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(2, 0, Duration.EndOfTurn).setText("{this} gets +2/+0"), filter2, false);
+ Ability ability = new BlocksOrBecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(2, 0, Duration.EndOfTurn).setText("{this} gets +2/+0"), filter2, false);
ability.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn).setText("and gains trample until end of turn"));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/g/GideonsDefeat.java b/Mage.Sets/src/mage/cards/g/GideonsDefeat.java
index b73f9f2dec4..de6db2d9218 100644
--- a/Mage.Sets/src/mage/cards/g/GideonsDefeat.java
+++ b/Mage.Sets/src/mage/cards/g/GideonsDefeat.java
@@ -71,7 +71,7 @@ class GideonsDefeatEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (controller != null && permanent != null) {
controller.moveCards(permanent, Zone.EXILED, source, game);
- game.applyEffects();
+ game.getState().processAction(game);
if (permanent.isPlaneswalker() && permanent.hasSubtype(SubType.GIDEON, game)) {
controller.gainLife(5, game, source);
}
diff --git a/Mage.Sets/src/mage/cards/g/GideonsIntervention.java b/Mage.Sets/src/mage/cards/g/GideonsIntervention.java
index 9ab17cfb9b8..1a679be278d 100644
--- a/Mage.Sets/src/mage/cards/g/GideonsIntervention.java
+++ b/Mage.Sets/src/mage/cards/g/GideonsIntervention.java
@@ -20,6 +20,7 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.PreventDamageEvent;
import mage.game.permanent.Permanent;
+import mage.util.CardUtil;
import java.util.UUID;
@@ -132,11 +133,12 @@ class GideonsInterventionPreventAllDamageEffect extends PreventionEffectImpl {
public boolean applies(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
Permanent targetPerm = game.getPermanent(event.getTargetId());
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
if (object != null && (event.getType() == GameEvent.EventType.DAMAGE_PLAYER
|| targetPerm != null && (event.getType() == GameEvent.EventType.DAMAGE_CREATURE
|| event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER))) {
- if (object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))
+ if (CardUtil.haveSameNames(object, cardName, game)
&& (event.getTargetId().equals(source.getControllerId())
|| targetPerm != null && targetPerm.isControlledBy(source.getControllerId()))) {
return super.applies(event, source, game);
diff --git a/Mage.Sets/src/mage/cards/g/GiftOfTheWoods.java b/Mage.Sets/src/mage/cards/g/GiftOfTheWoods.java
index 185f1a9eb7b..1d88c170a78 100644
--- a/Mage.Sets/src/mage/cards/g/GiftOfTheWoods.java
+++ b/Mage.Sets/src/mage/cards/g/GiftOfTheWoods.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
@@ -37,7 +37,7 @@ public final class GiftOfTheWoods extends CardImpl {
// Whenever enchanted creature blocks or becomes blocked, it gets +0/+3 until
// end of turn and you gain 1 life.
- Ability ability2 = new BlocksOrBecomesBlockedTriggeredAbility(
+ Ability ability2 = new BlocksOrBecomesBlockedSourceTriggeredAbility(
new BoostEnchantedEffect(0, 3, Duration.EndOfTurn), false);
ability2.addEffect(new GainLifeEffect(1).concatBy("and"));
this.addAbility(ability2);
diff --git a/Mage.Sets/src/mage/cards/g/GlaiveOfTheGuildpact.java b/Mage.Sets/src/mage/cards/g/GlaiveOfTheGuildpact.java
index 160e3ddda00..69eaad01676 100644
--- a/Mage.Sets/src/mage/cards/g/GlaiveOfTheGuildpact.java
+++ b/Mage.Sets/src/mage/cards/g/GlaiveOfTheGuildpact.java
@@ -29,10 +29,7 @@ public final class GlaiveOfTheGuildpact extends CardImpl {
this.subtype.add(SubType.EQUIPMENT);
// Equipped creature gets +1/+0 for each Gate you control and has vigilance and menace.
- Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(
- GateYouControlCount.instance,
- StaticValue.get(0)
- ).setText("Equipped creature gets +1/+0 for each Gate you control"));
+ Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(GateYouControlCount.instance, StaticValue.get(0)));
ability.addEffect(new GainAbilityAttachedEffect(
VigilanceAbility.getInstance(), AttachmentType.EQUIPMENT
).setText("and has vigilance"));
diff --git a/Mage.Sets/src/mage/cards/g/GleamingBarrier.java b/Mage.Sets/src/mage/cards/g/GleamingBarrier.java
index 8a0c60476a4..fc03735d675 100644
--- a/Mage.Sets/src/mage/cards/g/GleamingBarrier.java
+++ b/Mage.Sets/src/mage/cards/g/GleamingBarrier.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl;
@@ -29,7 +29,7 @@ public final class GleamingBarrier extends CardImpl {
this.addAbility(DefenderAbility.getInstance());
// When Gleaming Barrier dies, create a colorless Treasure artifact token with "{t}, Sacrifice this artifact: Add one mana of any color."
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new TreasureToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new TreasureToken())));
}
public GleamingBarrier(final GleamingBarrier card) {
diff --git a/Mage.Sets/src/mage/cards/g/Gloom.java b/Mage.Sets/src/mage/cards/g/Gloom.java
index 43a47d98b62..8df36787ea5 100644
--- a/Mage.Sets/src/mage/cards/g/Gloom.java
+++ b/Mage.Sets/src/mage/cards/g/Gloom.java
@@ -1,13 +1,11 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@@ -16,23 +14,25 @@ import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.util.CardUtil;
+import java.util.UUID;
+
/**
- *
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public final class Gloom extends CardImpl {
-
+
private static final FilterCard filter = new FilterCard("White spells");
+
static {
filter.add(new ColorPredicate(ObjectColor.WHITE));
}
public Gloom(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}");
// White spells cost {3} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasementAllEffect(filter, 3)));
-
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(3, filter, TargetController.ANY)));
+
// Activated abilities of white enchantments cost {3} more to activate.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GloomCostIncreaseEffect()));
}
@@ -63,12 +63,12 @@ class GloomCostIncreaseEffect extends CostModificationEffectImpl {
CardUtil.increaseCost(abilityToModify, 3);
return true;
}
-
+
@Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
+ public boolean applies(Ability abilityToModify, Ability source, Game game) {
boolean isWhiteEnchantment = false;
boolean isActivated = abilityToModify.getAbilityType() == AbilityType.ACTIVATED;
- if (isActivated) {
+ if (isActivated) {
MageObject permanent = game.getPermanent(abilityToModify.getSourceId());
if (permanent != null) {
isWhiteEnchantment = permanent.isEnchantment() && permanent.getColor(game).isWhite();
diff --git a/Mage.Sets/src/mage/cards/g/GloomSower.java b/Mage.Sets/src/mage/cards/g/GloomSower.java
new file mode 100644
index 00000000000..29db3f13c6a
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GloomSower.java
@@ -0,0 +1,81 @@
+package mage.cards.g;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+
+import java.util.UUID;
+
+/**
+ * @author arcox
+ */
+public final class GloomSower extends CardImpl {
+
+ public GloomSower(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}");
+
+ this.subtype.add(SubType.HORROR);
+ this.power = new MageInt(8);
+ this.toughness = new MageInt(6);
+
+ // Whenever Gloom Sower becomes blocked by a creature, that creature’s controller loses 2 life and you gain 2 life.
+ Ability ability = new BecomesBlockedByCreatureTriggeredAbility(new GloomSowerEffect(), false);
+ Effect effect = new GainLifeEffect(2);
+ effect.setText("and you gain 2 life");
+ ability.addEffect(effect);
+ this.addAbility(ability);
+ }
+
+ private GloomSower(final GloomSower card) {
+ super(card);
+ }
+
+ @Override
+ public GloomSower copy() {
+ return new GloomSower(this);
+ }
+}
+
+class GloomSowerEffect extends OneShotEffect {
+
+ GloomSowerEffect() {
+ super(Outcome.LoseLife);
+ staticText = "that creature's controller loses 2 life";
+ }
+
+ private GloomSowerEffect(final GloomSowerEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public GloomSowerEffect copy() {
+ return new GloomSowerEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
+ if (permanent == null) {
+ return false;
+ }
+
+ Player player = game.getPlayer(permanent.getControllerId());
+ if (player == null) {
+ return false;
+ }
+
+ player.loseLife(2, game, false);
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/Glowrider.java b/Mage.Sets/src/mage/cards/g/Glowrider.java
index 3ff76638970..7948e732c91 100644
--- a/Mage.Sets/src/mage/cards/g/Glowrider.java
+++ b/Mage.Sets/src/mage/cards/g/Glowrider.java
@@ -1,25 +1,30 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
-import mage.cards.Card;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.util.CardUtil;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+import mage.filter.predicate.Predicates;
+
+import java.util.UUID;
/**
- *
* @author fireshoes
*/
public final class Glowrider extends CardImpl {
+ private static final FilterCard filter = new FilterCard("Noncreature spells");
+
+ static {
+ filter.add(Predicates.not(CardType.CREATURE.getPredicate()));
+ }
+
public Glowrider(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
@@ -28,7 +33,7 @@ public final class Glowrider extends CardImpl {
this.toughness = new MageInt(1);
// Noncreature spells cost {1} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GlowriderCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(1, filter, TargetController.ANY)));
}
public Glowrider(final Glowrider card) {
@@ -40,38 +45,3 @@ public final class Glowrider extends CardImpl {
return new Glowrider(this);
}
}
-
-class GlowriderCostReductionEffect extends CostModificationEffectImpl {
-
- GlowriderCostReductionEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Noncreature spells cost {1} more to cast";
- }
-
- GlowriderCostReductionEffect(GlowriderCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- CardUtil.increaseCost(abilityToModify, 1);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- Card card = game.getCard(abilityToModify.getSourceId());
- if (card != null && !card.isCreature()) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public GlowriderCostReductionEffect copy() {
- return new GlowriderCostReductionEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/g/GnarledSage.java b/Mage.Sets/src/mage/cards/g/GnarledSage.java
new file mode 100644
index 00000000000..8b5ff451c9b
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GnarledSage.java
@@ -0,0 +1,72 @@
+package mage.cards.g;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.ReachAbility;
+import mage.abilities.keyword.VigilanceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.game.Game;
+import mage.watchers.common.CardsDrawnThisTurnWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author arcox
+ */
+public final class GnarledSage extends CardImpl {
+
+ public GnarledSage(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
+
+ this.subtype.add(SubType.TREEFOLK);
+ this.subtype.add(SubType.DRUID);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(4);
+
+ this.addAbility(ReachAbility.getInstance());
+
+ // As long as you’ve drawn two or more cards this turn, Gnarled Sage gets +0/+2 and has vigilance.
+ Ability ability = new SimpleStaticAbility(
+ new ConditionalContinuousEffect(
+ new BoostSourceEffect(0, 2, Duration.WhileOnBattlefield),
+ GnarledSageCondition.instance,
+ "As long as you've drawn two or more cards this turn, {this} gets +0/+2"
+ ));
+
+ ability.addEffect(new ConditionalContinuousEffect(
+ new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield),
+ GnarledSageCondition.instance,
+ "and has vigilance"
+ ));
+
+ this.addAbility(ability, new CardsDrawnThisTurnWatcher());
+ }
+
+ private GnarledSage(final GnarledSage card) {
+ super(card);
+ }
+
+ @Override
+ public GnarledSage copy() {
+ return new GnarledSage(this);
+ }
+}
+
+enum GnarledSageCondition implements Condition {
+ instance;
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ CardsDrawnThisTurnWatcher watcher = game.getState().getWatcher(CardsDrawnThisTurnWatcher.class);
+ return watcher != null && watcher.getCardsDrawnThisTurn(source.getControllerId()) > 1;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/g/GoblinArsonist.java b/Mage.Sets/src/mage/cards/g/GoblinArsonist.java
index df8e6b48d3a..3e6e67a7ff9 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinArsonist.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinArsonist.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -27,7 +27,7 @@ public final class GoblinArsonist extends CardImpl {
this.toughness = new MageInt(1);
// When Goblin Arsonist dies, you may have it deal 1 damage to any target.
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(1), true);
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(1), true);
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GoblinAssassin.java b/Mage.Sets/src/mage/cards/g/GoblinAssassin.java
index c94cb90e398..20e0ebebe13 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinAssassin.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinAssassin.java
@@ -1,44 +1,44 @@
-
package mage.cards.g;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
+import mage.filter.FilterPermanent;
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.TargetControlledCreaturePermanent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
/**
* @author BursegSardaukar
*/
public final class GoblinAssassin extends CardImpl {
+ private static final FilterPermanent filter = new FilterPermanent(SubType.GOBLIN, "Goblin");
+
public GoblinAssassin(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}");
this.subtype.add(SubType.GOBLIN);
this.subtype.add(SubType.ASSASSIN);
-
+
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Goblin Assassin or another Goblin enters the battlefield, each player flips a coin. Each player whose coin comes up tails sacrifices a creature.
- this.addAbility(new GoblinAssassinTriggeredAbiliy());
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(new GoblinAssassinTriggeredEffect(), filter));
}
- public GoblinAssassin(final GoblinAssassin card) {
+ private GoblinAssassin(final GoblinAssassin card) {
super(card);
}
@@ -48,55 +48,21 @@ public final class GoblinAssassin extends CardImpl {
}
}
-class GoblinAssassinTriggeredAbiliy extends TriggeredAbilityImpl {
- GoblinAssassinTriggeredAbiliy() {
- super(Zone.BATTLEFIELD, new GoblinAssassinTriggeredEffect(), false);
- }
-
- GoblinAssassinTriggeredAbiliy(final GoblinAssassinTriggeredAbiliy ability) {
- super(ability);
- }
-
- @Override
- public GoblinAssassinTriggeredAbiliy copy() {
- return new GoblinAssassinTriggeredAbiliy(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == EventType.ENTERS_THE_BATTLEFIELD;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- UUID targetId = event.getTargetId();
- Permanent permanent = game.getPermanent(targetId);
- if ((targetId.equals(this.getSourceId())) || (permanent.hasSubtype(SubType.GOBLIN, game) && !targetId.equals(this.getSourceId()))) {
- return true;
- }
- return false;
- }
-
- @Override
- public String getRule() {
- return "Whenever {this} or another Goblin enters battlefield, each player flips a coin. Each player whose coin comes up tails sacrifices a creature.";
- }
-}
-
class GoblinAssassinTriggeredEffect extends OneShotEffect {
+
GoblinAssassinTriggeredEffect() {
super(Outcome.Sacrifice);
}
- GoblinAssassinTriggeredEffect(final GoblinAssassinTriggeredEffect effect) {
+ private GoblinAssassinTriggeredEffect(final GoblinAssassinTriggeredEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
- List perms = new ArrayList<>();
+ List perms = new ArrayList<>();
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
+ if (controller != null) {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null && !player.flipCoin(source, game, false)) {
@@ -114,7 +80,7 @@ class GoblinAssassinTriggeredEffect extends OneShotEffect {
permanent.sacrifice(source.getSourceId(), game);
}
}
- return true;
+ return true;
}
return false;
}
@@ -123,4 +89,4 @@ class GoblinAssassinTriggeredEffect extends OneShotEffect {
public GoblinAssassinTriggeredEffect copy() {
return new GoblinAssassinTriggeredEffect(this);
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/g/GoblinAssaultTeam.java b/Mage.Sets/src/mage/cards/g/GoblinAssaultTeam.java
index 6efdad649ab..119ff344a29 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinAssaultTeam.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinAssaultTeam.java
@@ -2,7 +2,7 @@ package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
@@ -31,7 +31,7 @@ public final class GoblinAssaultTeam extends CardImpl {
this.addAbility(HasteAbility.getInstance());
// When Goblin Assault Team dies, put a +1/+1 counter on target creature you control.
- Ability ability = new DiesTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
+ Ability ability = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GoblinCadets.java b/Mage.Sets/src/mage/cards/g/GoblinCadets.java
index dff65dab69c..318f94c7f2e 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinCadets.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinCadets.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -27,7 +27,7 @@ public final class GoblinCadets extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Goblin Cadets blocks or becomes blocked, target opponent gains control of it.
- Ability ability = new BlocksOrBecomesBlockedTriggeredAbility(new GoblinCadetsChangeControlEffect(), false);
+ Ability ability = new BlocksOrBecomesBlockedSourceTriggeredAbility(new GoblinCadetsChangeControlEffect(), false);
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/g/GoblinEliteInfantry.java b/Mage.Sets/src/mage/cards/g/GoblinEliteInfantry.java
index 4207a963e5c..bc9233e3356 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinEliteInfantry.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinEliteInfantry.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class GoblinEliteInfantry extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(-1, -1, Duration.EndOfTurn), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(-1, -1, Duration.EndOfTurn), false));
}
public GoblinEliteInfantry(final GoblinEliteInfantry card) {
diff --git a/Mage.Sets/src/mage/cards/g/GoblinFlotilla.java b/Mage.Sets/src/mage/cards/g/GoblinFlotilla.java
index 2abda792419..dd281d53868 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinFlotilla.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinFlotilla.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DoUnlessControllerPaysEffect;
@@ -37,7 +37,7 @@ public final class GoblinFlotilla extends CardImpl {
// At the beginning of each combat, unless you pay {R}, whenever Goblin Flotilla blocks or becomes blocked by a creature this combat, that creature gains first strike until end of turn.
Effect effect = new DoUnlessControllerPaysEffect(
new GainAbilitySourceEffect(
- new BlocksOrBecomesBlockedTriggeredAbility(
+ new BlocksOrBecomesBlockedSourceTriggeredAbility(
new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(),
Duration.EndOfTurn,
"Blocks or Blocked by Goblin Flotilla"),
diff --git a/Mage.Sets/src/mage/cards/g/GoblinGardener.java b/Mage.Sets/src/mage/cards/g/GoblinGardener.java
index 63f5b185917..ae7e2be66ea 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinGardener.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinGardener.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class GoblinGardener extends CardImpl {
this.toughness = new MageInt(1);
// When Goblin Gardener dies, destroy target land.
- Ability ability = new DiesTriggeredAbility(new DestroyTargetEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DestroyTargetEffect(), false);
ability.addTarget(new TargetLandPermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GoblinMasons.java b/Mage.Sets/src/mage/cards/g/GoblinMasons.java
index 7d6fff41006..4afef73b5c7 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinMasons.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinMasons.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -33,7 +33,7 @@ public final class GoblinMasons extends CardImpl {
this.toughness = new MageInt(1);
//When Goblin Masons dies, destroy target Wall
- DiesTriggeredAbility ability = new DiesTriggeredAbility(new DestroyTargetEffect(), false);
+ DiesSourceTriggeredAbility ability = new DiesSourceTriggeredAbility(new DestroyTargetEffect(), false);
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/g/GoblinSwineRider.java b/Mage.Sets/src/mage/cards/g/GoblinSwineRider.java
index 44cd1c855b6..97d586821bd 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinSwineRider.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinSwineRider.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.DamageAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class GoblinSwineRider extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Goblin Swine-Rider becomes blocked, it deals 2 damage to each attacking creature and each blocking creature.
- this.addAbility(new BecomesBlockedTriggeredAbility(new DamageAllEffect(2, "it", new FilterAttackingOrBlockingCreature("attacking creature and each blocking creature")), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new DamageAllEffect(2, "it", new FilterAttackingOrBlockingCreature("attacking creature and each blocking creature")), false));
}
public GoblinSwineRider(final GoblinSwineRider card) {
diff --git a/Mage.Sets/src/mage/cards/g/GoblinWarchief.java b/Mage.Sets/src/mage/cards/g/GoblinWarchief.java
index 13106e9ba21..9ae91949618 100644
--- a/Mage.Sets/src/mage/cards/g/GoblinWarchief.java
+++ b/Mage.Sets/src/mage/cards/g/GoblinWarchief.java
@@ -1,7 +1,5 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
@@ -16,8 +14,9 @@ import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author jonubuu
*/
public final class GoblinWarchief extends CardImpl {
@@ -38,6 +37,7 @@ public final class GoblinWarchief extends CardImpl {
// Goblin spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filterSpells, 1)));
+
// Goblins you control have haste.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(HasteAbility.getInstance(),
Duration.WhileOnBattlefield, new FilterCreaturePermanent(SubType.GOBLIN, "Goblins"), false)));
diff --git a/Mage.Sets/src/mage/cards/g/GoblinWizardry.java b/Mage.Sets/src/mage/cards/g/GoblinWizardry.java
new file mode 100644
index 00000000000..c24367aeac9
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GoblinWizardry.java
@@ -0,0 +1,31 @@
+package mage.cards.g;
+
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.game.permanent.token.GoblinWizardToken;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class GoblinWizardry extends CardImpl {
+
+ public GoblinWizardry(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}");
+
+ // Create two 1/1 red Goblin Wizard creature tokens with prowess.
+ this.getSpellAbility().addEffect(new CreateTokenEffect(new GoblinWizardToken(), 2));
+ }
+
+ private GoblinWizardry(final GoblinWizardry card) {
+ super(card);
+ }
+
+ @Override
+ public GoblinWizardry copy() {
+ return new GoblinWizardry(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GodPharaohsStatue.java b/Mage.Sets/src/mage/cards/g/GodPharaohsStatue.java
index 2e2c67444d1..1fbd05ac206 100644
--- a/Mage.Sets/src/mage/cards/g/GodPharaohsStatue.java
+++ b/Mage.Sets/src/mage/cards/g/GodPharaohsStatue.java
@@ -1,16 +1,15 @@
package mage.cards.g;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.util.CardUtil;
+import mage.constants.CardType;
+import mage.constants.SuperType;
+import mage.constants.TargetController;
+import mage.filter.FilterCard;
import java.util.UUID;
@@ -25,7 +24,7 @@ public final class GodPharaohsStatue extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
// Spells your opponents cast cost {2} more to cast.
- this.addAbility(new SimpleStaticAbility(new GodPharaohsStatueEffect()));
+ this.addAbility(new SimpleStaticAbility(new SpellsCostIncreasingAllEffect(2, new FilterCard("Spells"), TargetController.OPPONENT)));
// At the beginning of your end step, each opponent loses 1 life.
this.addAbility(new BeginningOfEndStepTriggeredAbility(
@@ -42,40 +41,3 @@ public final class GodPharaohsStatue extends CardImpl {
return new GodPharaohsStatue(this);
}
}
-
-class GodPharaohsStatueEffect extends CostModificationEffectImpl {
-
- private static final String effectText = "Spells your opponents cast cost {2} more to cast";
-
- GodPharaohsStatueEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = effectText;
- }
-
- private GodPharaohsStatueEffect(GodPharaohsStatueEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public GodPharaohsStatueEffect copy() {
- return new GodPharaohsStatueEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/g/GolgariFindbroker.java b/Mage.Sets/src/mage/cards/g/GolgariFindbroker.java
index e95d580c617..06ee57f2aa9 100644
--- a/Mage.Sets/src/mage/cards/g/GolgariFindbroker.java
+++ b/Mage.Sets/src/mage/cards/g/GolgariFindbroker.java
@@ -1,27 +1,24 @@
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
-import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.filter.FilterCard;
-import mage.filter.common.FilterPermanentCard;
+import mage.constants.SubType;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInYourGraveyard;
+import java.util.UUID;
+
/**
*
* @author TheElk801
*/
public final class GolgariFindbroker extends CardImpl {
- private static final FilterCard filter
- = new FilterPermanentCard("permanent card from your graveyard");
-
public GolgariFindbroker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}{G}{G}");
@@ -32,9 +29,10 @@ public final class GolgariFindbroker extends CardImpl {
// When Golgari Findbroker enters the battlefield, return target permanent card from your graveyard to your hand.
Ability ability = new EntersBattlefieldTriggeredAbility(
- new ReturnFromGraveyardToHandTargetEffect(), false
+ new ReturnFromGraveyardToHandTargetEffect().setText("return target permanent card from your graveyard to your hand"),
+ false
);
- ability.addTarget(new TargetCardInYourGraveyard(filter));
+ ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_PERMANENT));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GolgariThug.java b/Mage.Sets/src/mage/cards/g/GolgariThug.java
index 98b5759fed2..2054216b9a7 100644
--- a/Mage.Sets/src/mage/cards/g/GolgariThug.java
+++ b/Mage.Sets/src/mage/cards/g/GolgariThug.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.PutOnLibraryTargetEffect;
import mage.abilities.keyword.DredgeAbility;
import mage.cards.CardImpl;
@@ -35,7 +35,7 @@ public final class GolgariThug extends CardImpl {
this.toughness = new MageInt(1);
// When Golgari Thug dies, put target creature card from your graveyard on top of your library.
- Ability ability = new DiesTriggeredAbility(new PutOnLibraryTargetEffect(true));
+ Ability ability = new DiesSourceTriggeredAbility(new PutOnLibraryTargetEffect(true));
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
// Dredge 4
diff --git a/Mage.Sets/src/mage/cards/g/GolosTirelessPilgrim.java b/Mage.Sets/src/mage/cards/g/GolosTirelessPilgrim.java
index 1f4d3077e20..83d87fc44b3 100644
--- a/Mage.Sets/src/mage/cards/g/GolosTirelessPilgrim.java
+++ b/Mage.Sets/src/mage/cards/g/GolosTirelessPilgrim.java
@@ -7,9 +7,9 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
@@ -19,7 +19,7 @@ import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
-import mage.target.targetpointer.FixedTarget;
+import mage.target.targetpointer.FixedTargets;
/**
* @author TheElk801
@@ -75,15 +75,8 @@ class GolosTirelessPilgrimEffect extends OneShotEffect {
return false;
}
Set cards = player.getLibrary().getTopCards(game, 3);
- player.moveCards(cards, Zone.EXILED, source, game);
- cards.stream()
- .filter(card -> game.getState().getZone(card.getId()) == Zone.EXILED)
- .forEach(card -> {
- ContinuousEffect effect = new GolosTirelessPilgrimCastFromExileEffect();
- effect.setTargetPointer(new FixedTarget(card, game));
- game.addEffect(effect, source);
- });
- return true;
+ return PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(game, source, cards,
+ TargetController.YOU, Duration.EndOfTurn, true);
}
@Override
@@ -91,41 +84,3 @@ class GolosTirelessPilgrimEffect extends OneShotEffect {
return new GolosTirelessPilgrimEffect(this);
}
}
-
-class GolosTirelessPilgrimCastFromExileEffect extends AsThoughEffectImpl {
-
- GolosTirelessPilgrimCastFromExileEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
- }
-
- private GolosTirelessPilgrimCastFromExileEffect(final GolosTirelessPilgrimCastFromExileEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public GolosTirelessPilgrimCastFromExileEffect copy() {
- return new GolosTirelessPilgrimCastFromExileEffect(this);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- if (!objectId.equals(getTargetPointer().getFirst(game, source))
- || !affectedControllerId.equals(source.getControllerId())) {
- return false;
- }
- Card card = game.getCard(objectId);
- if (card == null || card.isLand() || card.getSpellAbility().getCosts() == null) {
- return true;
- }
- Player player = game.getPlayer(affectedControllerId);
- if (player != null) {
- player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
- }
- return true;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/g/GontisAetherHeart.java b/Mage.Sets/src/mage/cards/g/GontisAetherHeart.java
index edac7052ffb..4f35197bd96 100644
--- a/Mage.Sets/src/mage/cards/g/GontisAetherHeart.java
+++ b/Mage.Sets/src/mage/cards/g/GontisAetherHeart.java
@@ -1,9 +1,8 @@
package mage.cards.g;
-import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.ExileSourceCost;
import mage.abilities.costs.common.PayEnergyCost;
@@ -13,37 +12,33 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SuperType;
-import mage.constants.TargetController;
-import mage.constants.Zone;
-import mage.filter.common.FilterArtifactPermanent;
+import mage.filter.StaticFilters;
+
+import java.util.UUID;
/**
- *
* @author fireshoes
*/
public final class GontisAetherHeart extends CardImpl {
- private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("{this} or another artifact");
-
- static {
- filter.add(TargetController.YOU.getControllerPredicate());
- }
-
public GontisAetherHeart(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}");
addSuperType(SuperType.LEGENDARY);
// Whenever Gonti's Aether Heart or another artifact enters the battlefield under your control, you get {E}{E} (two energy counters).
- this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new GetEnergyCountersControllerEffect(2), filter, false));
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new GetEnergyCountersControllerEffect(2),
+ StaticFilters.FILTER_PERMANENT_ARTIFACT, false, true
+ ));
// Pay {E}{E}{E}{E}{E}{E}{E}{E}, Exile Gonti's Aether Heart: Take an extra turn after this one.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddExtraTurnControllerEffect(), new PayEnergyCost(8));
+ Ability ability = new SimpleActivatedAbility(new AddExtraTurnControllerEffect(), new PayEnergyCost(8));
ability.addCost(new ExileSourceCost());
this.addAbility(ability);
}
- public GontisAetherHeart(final GontisAetherHeart card) {
+ private GontisAetherHeart(final GontisAetherHeart card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/g/GoreVassal.java b/Mage.Sets/src/mage/cards/g/GoreVassal.java
index cdfbfbb0945..4435be0dac8 100644
--- a/Mage.Sets/src/mage/cards/g/GoreVassal.java
+++ b/Mage.Sets/src/mage/cards/g/GoreVassal.java
@@ -23,7 +23,7 @@ public final class GoreVassal extends CardImpl {
public GoreVassal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/g/Goremand.java b/Mage.Sets/src/mage/cards/g/Goremand.java
new file mode 100644
index 00000000000..89a708bb09d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/Goremand.java
@@ -0,0 +1,55 @@
+package mage.cards.g;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.costs.common.SacrificeTargetCost;
+import mage.abilities.effects.common.SacrificeOpponentsEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.StaticFilters;
+import mage.target.common.TargetControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class Goremand extends CardImpl {
+
+ public Goremand(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}");
+
+ this.subtype.add(SubType.DEMON);
+ this.power = new MageInt(5);
+ this.toughness = new MageInt(5);
+
+ // As an additional cost to cast this spell, sacrifice a creature.
+ this.getSpellAbility().addCost(new SacrificeTargetCost(
+ new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT)
+ ));
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Trample
+ this.addAbility(TrampleAbility.getInstance());
+
+ // When Goremand enters the battlefield, each opponent sacrifices a creature.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(
+ new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_A_CREATURE)
+ ));
+ }
+
+ private Goremand(final Goremand card) {
+ super(card);
+ }
+
+ @Override
+ public Goremand copy() {
+ return new Goremand(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GorgingVulture.java b/Mage.Sets/src/mage/cards/g/GorgingVulture.java
index 5f042ced902..1c35c788b6c 100644
--- a/Mage.Sets/src/mage/cards/g/GorgingVulture.java
+++ b/Mage.Sets/src/mage/cards/g/GorgingVulture.java
@@ -5,7 +5,9 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
-import mage.cards.*;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
@@ -48,8 +50,7 @@ class GorgingVultureEffect extends OneShotEffect {
GorgingVultureEffect() {
super(Outcome.Benefit);
- staticText = "put the top four cards of your library into your graveyard. " +
- "You gain 1 life for each creature card put into your graveyard this way.";
+ staticText = "mill four cards. You gain 1 life for each creature card put into your graveyard this way.";
}
private GorgingVultureEffect(final GorgingVultureEffect effect) {
@@ -67,9 +68,8 @@ class GorgingVultureEffect extends OneShotEffect {
if (player == null) {
return false;
}
- Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 4));
- player.moveCards(cards, Zone.GRAVEYARD, source, game);
- int lifeToGain = cards
+ int lifeToGain = player
+ .millCards(4, source, game)
.getCards(game)
.stream()
.filter(Card::isCreature)
diff --git a/Mage.Sets/src/mage/cards/g/GorgonRecluse.java b/Mage.Sets/src/mage/cards/g/GorgonRecluse.java
index f9730324bda..1fa3627c589 100644
--- a/Mage.Sets/src/mage/cards/g/GorgonRecluse.java
+++ b/Mage.Sets/src/mage/cards/g/GorgonRecluse.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
@@ -40,7 +40,7 @@ public final class GorgonRecluse extends CardImpl {
// Whenever Gorgon Recluse blocks or becomes blocked by a nonblack creature, destroy that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true);
effect.setText("destroy that creature at end of combat");
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, filter, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, filter, false));
// Madness {B}{B}
this.addAbility(new MadnessAbility(this, new ManaCostsImpl("{B}{B}")));
diff --git a/Mage.Sets/src/mage/cards/g/GrandArbiterAugustinIV.java b/Mage.Sets/src/mage/cards/g/GrandArbiterAugustinIV.java
index 93c96922779..518db6f2abc 100644
--- a/Mage.Sets/src/mage/cards/g/GrandArbiterAugustinIV.java
+++ b/Mage.Sets/src/mage/cards/g/GrandArbiterAugustinIV.java
@@ -1,37 +1,33 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ColorPredicate;
-import mage.game.Game;
-import mage.util.CardUtil;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class GrandArbiterAugustinIV extends CardImpl {
private static final FilterCard filterWhite = new FilterCard("White spells");
private static final FilterCard filterBlue = new FilterCard("Blue spells");
+
static {
filterWhite.add(new ColorPredicate(ObjectColor.WHITE));
filterBlue.add(new ColorPredicate(ObjectColor.BLUE));
}
public GrandArbiterAugustinIV(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ADVISOR);
@@ -41,10 +37,12 @@ public final class GrandArbiterAugustinIV extends CardImpl {
// White spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filterWhite, 1)));
+
// Blue spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filterBlue, 1)));
+
// Spells your opponents cast cost {1} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GrandArbiterAugustinIVCostIncreaseEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(1, new FilterCard("Spells"), TargetController.OPPONENT)));
}
public GrandArbiterAugustinIV(final GrandArbiterAugustinIV card) {
@@ -56,40 +54,3 @@ public final class GrandArbiterAugustinIV extends CardImpl {
return new GrandArbiterAugustinIV(this);
}
}
-
-class GrandArbiterAugustinIVCostIncreaseEffect extends CostModificationEffectImpl {
-
- private static final String effectText = "Spells your opponents cast cost {1} more to cast";
-
- GrandArbiterAugustinIVCostIncreaseEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = effectText;
- }
-
- GrandArbiterAugustinIVCostIncreaseEffect(GrandArbiterAugustinIVCostIncreaseEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -1);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public GrandArbiterAugustinIVCostIncreaseEffect copy() {
- return new GrandArbiterAugustinIVCostIncreaseEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/g/Grapeshot.java b/Mage.Sets/src/mage/cards/g/Grapeshot.java
index 82a6a8b5c67..5101aaa10fd 100644
--- a/Mage.Sets/src/mage/cards/g/Grapeshot.java
+++ b/Mage.Sets/src/mage/cards/g/Grapeshot.java
@@ -1,7 +1,5 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.StormAbility;
import mage.cards.CardImpl;
@@ -9,19 +7,20 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
- *
* @author Plopman
*/
public final class Grapeshot extends CardImpl {
public Grapeshot(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{R}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}");
// Grapeshot deals 1 damage to any target.
this.getSpellAbility().addTarget(new TargetAnyTarget());
this.getSpellAbility().addEffect(new DamageTargetEffect(1));
+
// Storm
this.addAbility(new StormAbility());
}
diff --git a/Mage.Sets/src/mage/cards/g/GraveStrength.java b/Mage.Sets/src/mage/cards/g/GraveStrength.java
index 229eef94cbb..84bdb9d4106 100644
--- a/Mage.Sets/src/mage/cards/g/GraveStrength.java
+++ b/Mage.Sets/src/mage/cards/g/GraveStrength.java
@@ -24,7 +24,7 @@ public final class GraveStrength extends CardImpl {
// Choose target creature. Put the top three cards of your library into your graveyard, then put a +1/+1 counter on that creature for each creature card in your graveyard.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
Effect effect = new PutTopCardOfLibraryIntoGraveControllerEffect(3);
- effect.setText("Choose target creature. Put the top three cards of your library into your graveyard");
+ effect.setText("Choose target creature. Mill three cards");
this.getSpellAbility().addEffect(effect);
effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(0), new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE));
effect.setText(", then put a +1/+1 counter on that creature for each creature card in your graveyard");
diff --git a/Mage.Sets/src/mage/cards/g/GraveUpheaval.java b/Mage.Sets/src/mage/cards/g/GraveUpheaval.java
index f75d9f37890..3afdacc9c70 100644
--- a/Mage.Sets/src/mage/cards/g/GraveUpheaval.java
+++ b/Mage.Sets/src/mage/cards/g/GraveUpheaval.java
@@ -1,26 +1,15 @@
package mage.cards.g;
-import java.util.UUID;
-import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.ContinuousEffect;
-import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.effects.common.ReturnCreatureFromGraveyardToBattlefieldAndGainHasteEffect;
import mage.abilities.keyword.BasicLandcyclingAbility;
-import mage.abilities.keyword.HasteAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.filter.StaticFilters;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
import mage.target.common.TargetCardInGraveyard;
-import mage.target.targetpointer.FixedTarget;
+
+import java.util.UUID;
/**
*
@@ -32,7 +21,7 @@ public final class GraveUpheaval extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{R}");
// Put target creature card from a graveyard onto the battlefield under your control. It gains haste.
- this.getSpellAbility().addEffect(new GraveUpheavalEffect());
+ this.getSpellAbility().addEffect(new ReturnCreatureFromGraveyardToBattlefieldAndGainHasteEffect());
this.getSpellAbility().addTarget(new TargetCardInGraveyard(StaticFilters.FILTER_CARD_CREATURE));
// Basic landcycling {2}
@@ -49,40 +38,3 @@ public final class GraveUpheaval extends CardImpl {
}
}
-class GraveUpheavalEffect extends OneShotEffect {
-
- public GraveUpheavalEffect() {
- super(Outcome.PutCreatureInPlay);
- this.staticText = "Put target creature card from a graveyard onto the battlefield under your control. It gains haste";
- }
-
- public GraveUpheavalEffect(final GraveUpheavalEffect effect) {
- super(effect);
- }
-
- @Override
- public GraveUpheavalEffect copy() {
- return new GraveUpheavalEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller == null) {
- return false;
- }
- Card card = game.getCard(source.getFirstTarget());
- if (card != null) {
- controller.moveCards(card, Zone.BATTLEFIELD, source, game);
- Permanent permanent = game.getPermanent(card.getId());
- if (permanent != null) {
- ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom);
- effect.setTargetPointer(new FixedTarget(permanent, game));
- game.addEffect(effect, source);
- }
- return true;
- }
-
- return false;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/g/GravebaneZombie.java b/Mage.Sets/src/mage/cards/g/GravebaneZombie.java
index 43d6a30779f..6717c313779 100644
--- a/Mage.Sets/src/mage/cards/g/GravebaneZombie.java
+++ b/Mage.Sets/src/mage/cards/g/GravebaneZombie.java
@@ -18,6 +18,7 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
+import mage.players.Player;
/**
*
@@ -50,7 +51,7 @@ class GravebaneZombieEffect extends ReplacementEffectImpl {
GravebaneZombieEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
- staticText = "If {this} would die, put Gravebane Zombie on top of its owner's library instead";
+ staticText = "If {this} would die, put {this} on top of its owner's library instead";
}
GravebaneZombieEffect(final GravebaneZombieEffect effect) {
@@ -60,11 +61,9 @@ class GravebaneZombieEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent permanent = ((ZoneChangeEvent) event).getTarget();
- if (permanent != null) {
- if (permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true)) {
- game.informPlayers(permanent.getName() + " was put on the top of its owner's library");
- return true;
- }
+ Player controller = game.getPlayer(source.getControllerId());
+ if (permanent != null && controller !=null) {
+ return controller.putCardsOnTopOfLibrary(permanent, game, source, true);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/g/Gravegouger.java b/Mage.Sets/src/mage/cards/g/Gravegouger.java
index 57f99373d06..ea67ffe5193 100644
--- a/Mage.Sets/src/mage/cards/g/Gravegouger.java
+++ b/Mage.Sets/src/mage/cards/g/Gravegouger.java
@@ -4,7 +4,6 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.abilities.effects.common.ReturnFromExileForSourceEffect;
import mage.cards.CardImpl;
@@ -12,7 +11,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInASingleGraveyard;
import java.util.UUID;
@@ -30,9 +29,8 @@ public final class Gravegouger extends CardImpl {
this.toughness = new MageInt(2);
// When Gravegouger enters the battlefield, exile up to two target cards from a single graveyard.
- Effect effect = new ExileTargetForSourceEffect();
- Ability ability = new EntersBattlefieldTriggeredAbility(effect, false);
- ability.addTarget(new TargetCardInASingleGraveyard(0, 2, new FilterCard("cards from a single graveyard")));
+ Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect(), false);
+ ability.addTarget(new TargetCardInASingleGraveyard(0, 2, StaticFilters.FILTER_CARD_CARDS));
this.addAbility(ability);
// When Gravegouger leaves the battlefield, return the exiled cards to their owner's graveyard.
diff --git a/Mage.Sets/src/mage/cards/g/GraveyardShovel.java b/Mage.Sets/src/mage/cards/g/GraveyardShovel.java
index b19130c100f..9e348846c11 100644
--- a/Mage.Sets/src/mage/cards/g/GraveyardShovel.java
+++ b/Mage.Sets/src/mage/cards/g/GraveyardShovel.java
@@ -69,7 +69,6 @@ class GraveyardShovelEffect extends OneShotEffect {
if (targetPlayer.chooseTarget(Outcome.Exile, target, source, game)) {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
- targetPlayer.getGraveyard().remove(card);
card.moveToExile(null, "", source.getSourceId(), game);
if (card.isCreature()) {
controller.gainLife(2, game, source);
diff --git a/Mage.Sets/src/mage/cards/g/GravityWell.java b/Mage.Sets/src/mage/cards/g/GravityWell.java
index 00f083c6d77..0efefec9103 100644
--- a/Mage.Sets/src/mage/cards/g/GravityWell.java
+++ b/Mage.Sets/src/mage/cards/g/GravityWell.java
@@ -100,7 +100,7 @@ class GravityWellEffect extends ContinuousEffectImpl {
switch (layer) {
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
- permanent.getAbilities().removeIf(entry -> entry.getId().equals(FlyingAbility.getInstance().getId()));
+ permanent.removeAbility(FlyingAbility.getInstance(), source.getSourceId(), game);
}
break;
}
diff --git a/Mage.Sets/src/mage/cards/g/GreaterMossdog.java b/Mage.Sets/src/mage/cards/g/GreaterMossdog.java
index 605af0ca90a..13c03b91872 100644
--- a/Mage.Sets/src/mage/cards/g/GreaterMossdog.java
+++ b/Mage.Sets/src/mage/cards/g/GreaterMossdog.java
@@ -18,7 +18,7 @@ public final class GreaterMossdog extends CardImpl {
public GreaterMossdog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
this.subtype.add(SubType.PLANT);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/g/Greedo.java b/Mage.Sets/src/mage/cards/g/Greedo.java
index 16bf9f64eb4..199ed4564f0 100644
--- a/Mage.Sets/src/mage/cards/g/Greedo.java
+++ b/Mage.Sets/src/mage/cards/g/Greedo.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
@@ -45,7 +45,7 @@ public final class Greedo extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filter, "Creatures blocking or blocked by {this} have first strike")));
// When Greedo dies, you may search your library for Hunter or Rogue card, reveal it, and put it into your hand.
- this.addAbility(new DiesTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filterCard), true), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filterCard), true), true));
}
public Greedo(final Greedo card) {
diff --git a/Mage.Sets/src/mage/cards/g/GreelMindRaker.java b/Mage.Sets/src/mage/cards/g/GreelMindRaker.java
index bc79a60e01e..d615d2a6837 100644
--- a/Mage.Sets/src/mage/cards/g/GreelMindRaker.java
+++ b/Mage.Sets/src/mage/cards/g/GreelMindRaker.java
@@ -1,7 +1,5 @@
-
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -15,17 +13,19 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
-import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInHand;
+import java.util.UUID;
+
/**
- *
* @author Styxo
*/
public final class GreelMindRaker extends CardImpl {
+ private static final FilterCard filter = new FilterCard("two cards");
+
public GreelMindRaker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
@@ -36,14 +36,16 @@ public final class GreelMindRaker extends CardImpl {
this.toughness = new MageInt(3);
// {X}{B}, {tap}, Discard two cards: Target player discards X cards at random.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(ManacostVariableValue.instance, true), new ManaCostsImpl("{X}{B}"));
+ Ability ability = new SimpleActivatedAbility(new DiscardTargetEffect(
+ ManacostVariableValue.instance, true
+ ), new ManaCostsImpl("{X}{B}"));
ability.addCost(new TapSourceCost());
- ability.addCost(new DiscardTargetCost(new TargetCardInHand(2, new FilterCard())));
+ ability.addCost(new DiscardTargetCost(new TargetCardInHand(2, filter)));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
- public GreelMindRaker(final GreelMindRaker card) {
+ private GreelMindRaker(final GreelMindRaker card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/g/GreenwardenOfMurasa.java b/Mage.Sets/src/mage/cards/g/GreenwardenOfMurasa.java
index 3a2bdfcaaaf..ab52e220560 100644
--- a/Mage.Sets/src/mage/cards/g/GreenwardenOfMurasa.java
+++ b/Mage.Sets/src/mage/cards/g/GreenwardenOfMurasa.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.effects.common.DoIfCostPaid;
@@ -33,7 +33,7 @@ public final class GreenwardenOfMurasa extends CardImpl {
this.addAbility(ability);
// When Greenwarden of Murasa dies, you may exile it. If you do, return target card from your graveyard to your hand.
- ability = new DiesTriggeredAbility(new DoIfCostPaid(new ReturnFromGraveyardToHandTargetEffect(), new ExileSourceFromGraveCost(),
+ ability = new DiesSourceTriggeredAbility(new DoIfCostPaid(new ReturnFromGraveyardToHandTargetEffect(), new ExileSourceFromGraveCost(),
"Exile {this} and return target card from your graveyard to your hand?", true), false);
ability.addTarget(new TargetCardInYourGraveyard());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/g/GriefTyrant.java b/Mage.Sets/src/mage/cards/g/GriefTyrant.java
index 603df5b9419..c30b52fd2e3 100644
--- a/Mage.Sets/src/mage/cards/g/GriefTyrant.java
+++ b/Mage.Sets/src/mage/cards/g/GriefTyrant.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@@ -34,7 +34,7 @@ public final class GriefTyrant extends CardImpl {
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance(4))));
// When Grief Tyrant dies, put a -1/-1 counter on target creature for each -1/-1 counter on Grief Tyrant.
- Ability ability = new DiesTriggeredAbility(new GriefTyrantEffect());
+ Ability ability = new DiesSourceTriggeredAbility(new GriefTyrantEffect());
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/g/GriffinAerie.java b/Mage.Sets/src/mage/cards/g/GriffinAerie.java
new file mode 100644
index 00000000000..a3e4a3297c8
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/g/GriffinAerie.java
@@ -0,0 +1,48 @@
+package mage.cards.g;
+
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.YouGainedLifeCondition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.hint.ConditionHint;
+import mage.abilities.hint.Hint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.ComparisonType;
+import mage.constants.TargetController;
+import mage.game.permanent.token.GriffinToken;
+import mage.watchers.common.PlayerGainedLifeWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class GriffinAerie extends CardImpl {
+
+ private static final Condition condition = new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2);
+ private static final Hint hint = new ConditionHint(condition, "You gained 3 or more life this turn");
+
+ public GriffinAerie(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
+
+ // At the beginning of your end step, if you gained 3 or more life this turn, create a 2/2 white Griffin creature token with flying.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfEndStepTriggeredAbility(
+ new CreateTokenEffect(new GriffinToken()), TargetController.YOU, false
+ ), condition, "At the beginning of your end step, " +
+ "if you gained 3 or more life this turn, create a 2/2 white Griffin creature token with flying."
+ ).addHint(hint), new PlayerGainedLifeWatcher());
+ }
+
+ private GriffinAerie(final GriffinAerie card) {
+ super(card);
+ }
+
+ @Override
+ public GriffinAerie copy() {
+ return new GriffinAerie(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/g/GrimInitiate.java b/Mage.Sets/src/mage/cards/g/GrimInitiate.java
index ac59582d80f..09e20471ba5 100644
--- a/Mage.Sets/src/mage/cards/g/GrimInitiate.java
+++ b/Mage.Sets/src/mage/cards/g/GrimInitiate.java
@@ -1,7 +1,7 @@
package mage.cards.g;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.keyword.AmassEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class GrimInitiate extends CardImpl {
this.addAbility(FirstStrikeAbility.getInstance());
// When Grim Initiate dies, amass 1.
- this.addAbility(new DiesTriggeredAbility(new AmassEffect(1)));
+ this.addAbility(new DiesSourceTriggeredAbility(new AmassEffect(1)));
}
private GrimInitiate(final GrimInitiate card) {
diff --git a/Mage.Sets/src/mage/cards/g/GrimPhysician.java b/Mage.Sets/src/mage/cards/g/GrimPhysician.java
index 598305c58e8..12daab2dd80 100644
--- a/Mage.Sets/src/mage/cards/g/GrimPhysician.java
+++ b/Mage.Sets/src/mage/cards/g/GrimPhysician.java
@@ -2,7 +2,7 @@ package mage.cards.g;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class GrimPhysician extends CardImpl {
this.toughness = new MageInt(1);
// When Grim Physician dies, target creature an opponent controls gets -1/-1 until end of turn.
- Ability ability = new DiesTriggeredAbility(new BoostTargetEffect(-1, -1));
+ Ability ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(-1, -1));
ability.addTarget(new TargetOpponentsCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/Grindclock.java b/Mage.Sets/src/mage/cards/g/Grindclock.java
index 0a873bff095..26b5840587b 100644
--- a/Mage.Sets/src/mage/cards/g/Grindclock.java
+++ b/Mage.Sets/src/mage/cards/g/Grindclock.java
@@ -1,7 +1,6 @@
package mage.cards.g;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@@ -18,8 +17,9 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class Grindclock extends CardImpl {
@@ -62,7 +62,7 @@ class GrindclockEffect extends OneShotEffect {
int amount = sourceObject.getCounters(game).getCount(CounterType.CHARGE);
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (targetPlayer != null) {
- targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ targetPlayer.millCards(amount, source, game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/g/Grindstone.java b/Mage.Sets/src/mage/cards/g/Grindstone.java
index 1b7c1e738d7..2e5d271aacc 100644
--- a/Mage.Sets/src/mage/cards/g/Grindstone.java
+++ b/Mage.Sets/src/mage/cards/g/Grindstone.java
@@ -1,22 +1,25 @@
-
package mage.cards.g;
-import java.util.UUID;
+import mage.ObjectColor;
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.OneShotEffect;
-import mage.cards.*;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
/**
- *
* @author LevelX2
*/
public final class Grindstone extends CardImpl {
@@ -25,11 +28,10 @@ public final class Grindstone extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
// {3}, {T}: Target player puts the top two cards of their library into their graveyard. If both cards share a color, repeat this process.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GrindstoneEffect(), new ManaCostsImpl("{3}"));
+ Ability ability = new SimpleActivatedAbility(new GrindstoneEffect(), new ManaCostsImpl("{3}"));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
-
}
public Grindstone(final Grindstone card) {
@@ -44,12 +46,12 @@ public final class Grindstone extends CardImpl {
class GrindstoneEffect extends OneShotEffect {
- public GrindstoneEffect() {
+ GrindstoneEffect() {
super(Outcome.Benefit);
- this.staticText = "Target player puts the top two cards of their library into their graveyard. If both cards share a color, repeat this process";
+ this.staticText = "target player mills two cards. If two cards that share a color were milled this way, repeat this process.";
}
- public GrindstoneEffect(final GrindstoneEffect effect) {
+ private GrindstoneEffect(final GrindstoneEffect effect) {
super(effect);
}
@@ -77,18 +79,33 @@ class GrindstoneEffect extends OneShotEffect {
return true;
}
colorShared = false;
- Card card1 = null;
- Cards toGraveyard = new CardsImpl();
- for (Card card : targetPlayer.getLibrary().getCards(game)) {
- toGraveyard.add(card);
- if (card1 == null) {
- card1 = card;
- } else {
- colorShared = card1.getColor(game).shares(card.getColor(game));
+ List cards = targetPlayer
+ .millCards(2, source, game)
+ .getCards(game)
+ .stream()
+ .collect(Collectors.toList());
+ if (cards.size() < 2) {
+ break;
+ }
+ for (int i = 0; i < cards.size(); i++) {
+ if (colorShared) {
break;
}
+ ObjectColor color1 = cards.get(i).getColor(game);
+ if (color1.isColorless()) {
+ continue;
+ }
+ for (int j = 0; j < cards.size(); j++) {
+ if (i >= j) {
+ continue;
+ }
+ ObjectColor color2 = cards.get(j).getColor(game);
+ if (color1.shares(color2)) {
+ colorShared = true;
+ break;
+ }
+ }
}
- targetPlayer.moveCards(toGraveyard, Zone.GRAVEYARD, source, game);
} while (colorShared);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/g/GripOfChaos.java b/Mage.Sets/src/mage/cards/g/GripOfChaos.java
index 479a74548de..158782a7f8e 100644
--- a/Mage.Sets/src/mage/cards/g/GripOfChaos.java
+++ b/Mage.Sets/src/mage/cards/g/GripOfChaos.java
@@ -1,4 +1,3 @@
-
package mage.cards.g;
import java.util.Iterator;
@@ -126,7 +125,7 @@ class GripOfChaosEffect extends OneShotEffect {
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
for (Target target : mode.getTargets()) {
UUID oldTargetId = target.getFirstTarget();
- Set possibleTargets = target.possibleTargets(stackObject.getId(), stackObject.getControllerId(), game);
+ Set possibleTargets = target.possibleTargets(stackObject.getSourceId(), stackObject.getControllerId(), game);
if (possibleTargets.contains(stackObject.getId())) { // The stackObject can't target itself
possibleTargets.remove(stackObject.getId());
}
diff --git a/Mage.Sets/src/mage/cards/g/GrislySpectacle.java b/Mage.Sets/src/mage/cards/g/GrislySpectacle.java
index 074d37f0f30..c2d21bb0d59 100644
--- a/Mage.Sets/src/mage/cards/g/GrislySpectacle.java
+++ b/Mage.Sets/src/mage/cards/g/GrislySpectacle.java
@@ -54,7 +54,7 @@ class GrislySpectacleEffect extends OneShotEffect {
public GrislySpectacleEffect() {
super(Outcome.DestroyPermanent);
- this.staticText = "Its controller puts a number of cards equal to that creature's power from the top of their library into their graveyard";
+ this.staticText = "Its controller mills cards equal to that creature's power";
}
public GrislySpectacleEffect(final GrislySpectacleEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/g/GrixisSojourners.java b/Mage.Sets/src/mage/cards/g/GrixisSojourners.java
index 9c8af92701c..1f15137feb9 100644
--- a/Mage.Sets/src/mage/cards/g/GrixisSojourners.java
+++ b/Mage.Sets/src/mage/cards/g/GrixisSojourners.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.CycleTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.keyword.CyclingAbility;
@@ -35,7 +35,7 @@ public final class GrixisSojourners extends CardImpl {
// When you cycle Grixis Sojourners or it dies, you may exile target card from a graveyard.
Ability ability1 = new CycleTriggeredAbility(new ExileTargetEffect(), true);
- Ability ability2 = new DiesTriggeredAbility(new ExileTargetEffect(), true);
+ Ability ability2 = new DiesSourceTriggeredAbility(new ExileTargetEffect(), true);
ability1.addTarget(new TargetCardInASingleGraveyard(1, 1, new FilterCard()));
ability2.addTarget(new TargetCardInASingleGraveyard(1, 1, new FilterCard()));
this.addAbility(ability1);
diff --git a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java
index b1715bac1f4..4726349725a 100644
--- a/Mage.Sets/src/mage/cards/g/GrizzledAngler.java
+++ b/Mage.Sets/src/mage/cards/g/GrizzledAngler.java
@@ -1,7 +1,6 @@
package mage.cards.g;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -12,22 +11,23 @@ import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.ColorlessPredicate;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class GrizzledAngler extends CardImpl {
public GrizzledAngler(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.HUMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
@@ -60,7 +60,7 @@ class GrizzledAnglerEffect extends OneShotEffect {
public GrizzledAnglerEffect() {
super(Outcome.Benefit);
- staticText = "Put the top two cards of your library into your graveyard. Then if there is a colorless creature card in your graveyard, transform {this}";
+ staticText = "Mill two cards. Then if there is a colorless creature card in your graveyard, transform {this}";
}
public GrizzledAnglerEffect(final GrizzledAnglerEffect effect) {
@@ -76,7 +76,7 @@ class GrizzledAnglerEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- controller.moveCards(controller.getLibrary().getTopCards(game, 2), Zone.GRAVEYARD, source, game);
+ controller.millCards(2, source, game);
if (controller.getGraveyard().count(filter, source.getSourceId(), source.getControllerId(), game) >= 1) {
return new TransformSourceEffect(true).apply(game, source);
}
diff --git a/Mage.Sets/src/mage/cards/g/Groffskithur.java b/Mage.Sets/src/mage/cards/g/Groffskithur.java
index 3a5bd1e9985..e11f64f130e 100644
--- a/Mage.Sets/src/mage/cards/g/Groffskithur.java
+++ b/Mage.Sets/src/mage/cards/g/Groffskithur.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -33,7 +33,7 @@ public final class Groffskithur extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Groffskithur becomes blocked, you may return target card named Groffskithur from your graveyard to your hand.
- Ability ability = new BecomesBlockedTriggeredAbility(new ReturnToHandTargetEffect(), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new ReturnToHandTargetEffect(), true);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java b/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java
index d7c445de70d..2237f3b4c8d 100644
--- a/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java
+++ b/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java
@@ -1,8 +1,5 @@
-
package mage.cards.g;
-import java.util.UUID;
-import mage.MageInt;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -11,20 +8,19 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.common.TapTargetCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
-import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
-import mage.game.permanent.token.TokenImpl;
-import mage.game.permanent.token.Token;
+import mage.game.permanent.token.GreenAndWhiteElementalToken;
import mage.target.common.TargetControlledCreaturePermanent;
+import java.util.UUID;
+
/**
* @author LevelX2
*/
@@ -43,7 +39,7 @@ public final class GroveOfTheGuardian extends CardImpl {
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.ColorlessMana(1), new TapSourceCost()));
// {3}{G}{W}, {T}, Tap two untapped creatures you control, Sacrifice Grove of the Guardian: Create an 8/8 green and white Elemental creature token with vigilance.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new ElementalToken(), 1), new ManaCostsImpl("{3}{G}{W}"));
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new GreenAndWhiteElementalToken(), 1), new ManaCostsImpl("{3}{G}{W}"));
ability.addCost(new TapSourceCost());
ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false)));
ability.addCost(new SacrificeSourceCost());
@@ -58,26 +54,4 @@ public final class GroveOfTheGuardian extends CardImpl {
public GroveOfTheGuardian copy() {
return new GroveOfTheGuardian(this);
}
-
- private static class ElementalToken extends TokenImpl {
-
- ElementalToken() {
- super("Elemental", "8/8 green and white Elemental creature token with vigilance");
-
- cardType.add(CardType.CREATURE);
- color.setGreen(true);
- color.setWhite(true);
- this.subtype.add(SubType.ELEMENTAL);
- power = new MageInt(8);
- toughness = new MageInt(8);
- this.addAbility(VigilanceAbility.getInstance());
- }
- public ElementalToken(final ElementalToken token) {
- super(token);
- }
-
- public ElementalToken copy() {
- return new ElementalToken(this);
- }
- }
}
diff --git a/Mage.Sets/src/mage/cards/g/GruesomeDiscovery.java b/Mage.Sets/src/mage/cards/g/GruesomeDiscovery.java
index 7e996c5a251..9d33d69e3c8 100644
--- a/Mage.Sets/src/mage/cards/g/GruesomeDiscovery.java
+++ b/Mage.Sets/src/mage/cards/g/GruesomeDiscovery.java
@@ -1,4 +1,3 @@
-
package mage.cards.g;
import mage.abilities.Ability;
@@ -6,19 +5,18 @@ import mage.abilities.condition.common.MorbidCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
+import mage.target.common.TargetCardInHand;
-import java.util.List;
import java.util.UUID;
/**
@@ -29,18 +27,18 @@ public final class GruesomeDiscovery extends CardImpl {
public GruesomeDiscovery(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}{B}");
-
// Target player discards two cards.
// Morbid — If a creature died this turn, instead that player reveals their hand, you choose two cards from it, then that player discards those cards.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
- new GruesomeDiscoveryEffect(),
- new DiscardTargetEffect(2),
- MorbidCondition.instance,
- "Target player discards two cards. Morbid — If a creature died this turn, instead that player reveals their hand, you choose two cards from it, then that player discards those cards"));
+ new GruesomeDiscoveryEffect(), new DiscardTargetEffect(2),
+ MorbidCondition.instance, "Target player discards two cards. " +
+ "
Morbid — If a creature died this turn, instead that player reveals their hand, " +
+ "you choose two cards from it, then that player discards those cards"
+ ));
this.getSpellAbility().addTarget(new TargetPlayer());
}
- public GruesomeDiscovery(final GruesomeDiscovery card) {
+ private GruesomeDiscovery(final GruesomeDiscovery card) {
super(card);
}
@@ -52,12 +50,11 @@ public final class GruesomeDiscovery extends CardImpl {
class GruesomeDiscoveryEffect extends OneShotEffect {
- public GruesomeDiscoveryEffect() {
+ GruesomeDiscoveryEffect() {
super(Outcome.Discard);
- this.staticText = "target player reveals their hand, you choose two cards from it, then that player discards those cards";
}
- public GruesomeDiscoveryEffect(final GruesomeDiscoveryEffect effect) {
+ private GruesomeDiscoveryEffect(final GruesomeDiscoveryEffect effect) {
super(effect);
}
@@ -70,25 +67,16 @@ class GruesomeDiscoveryEffect extends OneShotEffect {
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("Gruesome Discovery", targetPlayer.getHand(), game);
-
- if (targetPlayer.getHand().size() <= 2) {
- targetPlayer.discard(2, false, source, game);
- }
-
- TargetCard target = new TargetCard(2, Zone.HAND, new FilterCard());
- if (player.choose(Outcome.Benefit, targetPlayer.getHand(), target, game)) {
- List targets = target.getTargets();
- for (UUID targetId : targets) {
- Card card = targetPlayer.getHand().get(targetId, game);
- targetPlayer.discard(card, source, game);
-
- }
- }
- return true;
+ if (player == null || targetPlayer == null) {
+ return false;
}
- return false;
+ targetPlayer.revealCards(source, targetPlayer.getHand(), game);
+ if (targetPlayer.getHand().size() <= 2) {
+ targetPlayer.discard(2, false, source, game);
+ }
+ TargetCard target = new TargetCardInHand(2, StaticFilters.FILTER_CARD_CARDS);
+ player.choose(Outcome.Discard, targetPlayer.getHand(), target, game);
+ targetPlayer.discard(new CardsImpl(target.getTargets()), source, game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/g/GruulRagebeast.java b/Mage.Sets/src/mage/cards/g/GruulRagebeast.java
index 7a7ec1517a4..2ac9f509ae3 100644
--- a/Mage.Sets/src/mage/cards/g/GruulRagebeast.java
+++ b/Mage.Sets/src/mage/cards/g/GruulRagebeast.java
@@ -20,6 +20,7 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
+import mage.target.common.TargetOpponentsCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
@@ -28,12 +29,6 @@ import mage.target.targetpointer.FixedTarget;
*/
public final class GruulRagebeast extends CardImpl {
- private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature an opponent controls");
-
- static {
- filter2.add(TargetController.OPPONENT.getControllerPredicate());
- }
-
public GruulRagebeast(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{G}");
this.subtype.add(SubType.BEAST);
@@ -42,10 +37,7 @@ public final class GruulRagebeast extends CardImpl {
this.toughness = new MageInt(6);
// Whenever Gruul Ragebeast or another creature enters the battlefield under your control, that creature fights target creature an opponent controls.
- Ability ability = new GruulRagebeastTriggeredAbility();
-
- ability.addTarget(new TargetCreaturePermanent(filter2));
- this.addAbility(ability);
+ this.addAbility(new GruulRagebeastTriggeredAbility());
}
public GruulRagebeast(final GruulRagebeast card) {
@@ -61,10 +53,10 @@ public final class GruulRagebeast extends CardImpl {
class GruulRagebeastTriggeredAbility extends TriggeredAbilityImpl {
GruulRagebeastTriggeredAbility() {
- super(Zone.BATTLEFIELD, new GruulRagebeastEffect(), false);
+ super(Zone.BATTLEFIELD, new GruulRagebeastEffect(), false);this.addTarget(new TargetOpponentsCreaturePermanent());
}
- GruulRagebeastTriggeredAbility(final GruulRagebeastTriggeredAbility ability) {
+ private GruulRagebeastTriggeredAbility(final GruulRagebeastTriggeredAbility ability) {
super(ability);
}
@@ -106,7 +98,7 @@ class GruulRagebeastEffect extends OneShotEffect {
super(Outcome.Damage);
}
- GruulRagebeastEffect(final GruulRagebeastEffect effect) {
+ private GruulRagebeastEffect(final GruulRagebeastEffect effect) {
super(effect);
}
diff --git a/Mage.Sets/src/mage/cards/g/GuanYuSaintedWarrior.java b/Mage.Sets/src/mage/cards/g/GuanYuSaintedWarrior.java
index e47a6ea0b88..76b4dd93d75 100644
--- a/Mage.Sets/src/mage/cards/g/GuanYuSaintedWarrior.java
+++ b/Mage.Sets/src/mage/cards/g/GuanYuSaintedWarrior.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect;
import mage.abilities.keyword.HorsemanshipAbility;
import mage.cards.CardImpl;
@@ -30,7 +30,7 @@ public final class GuanYuSaintedWarrior extends CardImpl {
// Horsemanship
this.addAbility(HorsemanshipAbility.getInstance());
// When Guan Yu, Sainted Warrior is put into your graveyard from the battlefield, you may shuffle Guan Yu into your library.
- this.addAbility(new DiesTriggeredAbility(new ShuffleIntoLibrarySourceEffect(), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new ShuffleIntoLibrarySourceEffect(), true));
}
public GuanYuSaintedWarrior(final GuanYuSaintedWarrior card) {
diff --git a/Mage.Sets/src/mage/cards/g/GuardDogs.java b/Mage.Sets/src/mage/cards/g/GuardDogs.java
index 6101684b23b..30fe2c42ee9 100644
--- a/Mage.Sets/src/mage/cards/g/GuardDogs.java
+++ b/Mage.Sets/src/mage/cards/g/GuardDogs.java
@@ -30,7 +30,7 @@ public final class GuardDogs extends CardImpl {
public GuardDogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/g/GuardianAutomaton.java b/Mage.Sets/src/mage/cards/g/GuardianAutomaton.java
index 29da03f155a..62bb99b5ba1 100644
--- a/Mage.Sets/src/mage/cards/g/GuardianAutomaton.java
+++ b/Mage.Sets/src/mage/cards/g/GuardianAutomaton.java
@@ -3,7 +3,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class GuardianAutomaton extends CardImpl {
this.toughness = new MageInt(3);
// When Guardian Automaton dies, you gain 3 life.
- this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(3)));
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(3)));
}
public GuardianAutomaton(final GuardianAutomaton card) {
diff --git a/Mage.Sets/src/mage/cards/g/GuildSummit.java b/Mage.Sets/src/mage/cards/g/GuildSummit.java
index 1558862ef07..e6ef9058de8 100644
--- a/Mage.Sets/src/mage/cards/g/GuildSummit.java
+++ b/Mage.Sets/src/mage/cards/g/GuildSummit.java
@@ -1,6 +1,5 @@
package mage.cards.g;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -16,11 +15,13 @@ import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
+import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class GuildSummit extends CardImpl {
@@ -82,9 +83,10 @@ class GuildSummitEffect extends OneShotEffect {
Player you = game.getPlayer(source.getControllerId());
TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true);
if (target.canChoose(source.getControllerId(), game) && target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), game)) {
- for (UUID creature : target.getTargets()) {
+ for (UUID creatureId : target.getTargets()) {
+ Permanent creature = game.getPermanent(creatureId);
if (creature != null) {
- game.getPermanent(creature).tap(game);
+ creature.tap(game);
tappedAmount++;
}
}
diff --git a/Mage.Sets/src/mage/cards/g/GustOfWind.java b/Mage.Sets/src/mage/cards/g/GustOfWind.java
index bbbc825cf65..19c5a506f20 100644
--- a/Mage.Sets/src/mage/cards/g/GustOfWind.java
+++ b/Mage.Sets/src/mage/cards/g/GustOfWind.java
@@ -6,6 +6,7 @@ import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -42,8 +43,8 @@ public final class GustOfWind extends CardImpl {
// This spell costs {2} less to cast if you control a creature with flying.
this.addAbility(new SimpleStaticAbility(
- Zone.STACK, new SpellCostReductionSourceEffect(2, condition)
- ).setRuleAtTheTop(true));
+ Zone.ALL, new SpellCostReductionSourceEffect(2, condition)
+ ).setRuleAtTheTop(true).addHint(new ConditionHint(condition, "You control a creature with flying")));
// Return target nonland permanent you don't control to its owner's hand.
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
diff --git a/Mage.Sets/src/mage/cards/g/GustcloakCavalier.java b/Mage.Sets/src/mage/cards/g/GustcloakCavalier.java
index b8049a75f3d..335994260c0 100644
--- a/Mage.Sets/src/mage/cards/g/GustcloakCavalier.java
+++ b/Mage.Sets/src/mage/cards/g/GustcloakCavalier.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.RemoveFromCombatSourceEffect;
import mage.abilities.effects.common.TapTargetEffect;
@@ -39,7 +39,7 @@ public final class GustcloakCavalier extends CardImpl {
this.addAbility(ability);
// Whenever Gustcloak Cavalier becomes blocked, you may untap Gustcloak Cavalier and remove it from combat.
- Ability ability2 = new BecomesBlockedTriggeredAbility(new UntapSourceEffect(), true);
+ Ability ability2 = new BecomesBlockedSourceTriggeredAbility(new UntapSourceEffect(), true);
Effect effect = new RemoveFromCombatSourceEffect();
effect.setText("and remove it from combat");
ability2.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/g/GustcloakHarrier.java b/Mage.Sets/src/mage/cards/g/GustcloakHarrier.java
index fbc6a66b813..51c59a07049 100644
--- a/Mage.Sets/src/mage/cards/g/GustcloakHarrier.java
+++ b/Mage.Sets/src/mage/cards/g/GustcloakHarrier.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.RemoveFromCombatSourceEffect;
import mage.abilities.effects.common.UntapSourceEffect;
@@ -31,7 +31,7 @@ public final class GustcloakHarrier extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever Gustcloak Harrier becomes blocked, you may untap it and remove it from combat.
- Ability ability = new BecomesBlockedTriggeredAbility(new UntapSourceEffect(), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new UntapSourceEffect(), true);
Effect effect = new RemoveFromCombatSourceEffect();
effect.setText("and remove it from combat");
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/g/GustcloakRunner.java b/Mage.Sets/src/mage/cards/g/GustcloakRunner.java
index d7364a23363..924a806fbf9 100644
--- a/Mage.Sets/src/mage/cards/g/GustcloakRunner.java
+++ b/Mage.Sets/src/mage/cards/g/GustcloakRunner.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.RemoveFromCombatSourceEffect;
import mage.abilities.effects.common.UntapSourceEffect;
@@ -27,7 +27,7 @@ public final class GustcloakRunner extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Gustcloak Runner becomes blocked, you may untap it and remove it from combat.
- Ability ability = new BecomesBlockedTriggeredAbility(new UntapSourceEffect(), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new UntapSourceEffect(), true);
Effect effect = new RemoveFromCombatSourceEffect();
effect.setText("and remove it from combat");
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/g/GustcloakSentinel.java b/Mage.Sets/src/mage/cards/g/GustcloakSentinel.java
index 1b7a699fac7..276ce6da8c9 100644
--- a/Mage.Sets/src/mage/cards/g/GustcloakSentinel.java
+++ b/Mage.Sets/src/mage/cards/g/GustcloakSentinel.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.RemoveFromCombatSourceEffect;
import mage.abilities.effects.common.UntapSourceEffect;
@@ -28,7 +28,7 @@ public final class GustcloakSentinel extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Gustcloak Sentinel becomes blocked, you may untap it and remove it from combat.
- Ability ability = new BecomesBlockedTriggeredAbility(new UntapSourceEffect(), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new UntapSourceEffect(), true);
Effect effect = new RemoveFromCombatSourceEffect();
effect.setText("and remove it from combat");
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/g/GustcloakSkirmisher.java b/Mage.Sets/src/mage/cards/g/GustcloakSkirmisher.java
index 5520f5979af..732e2cd3e08 100644
--- a/Mage.Sets/src/mage/cards/g/GustcloakSkirmisher.java
+++ b/Mage.Sets/src/mage/cards/g/GustcloakSkirmisher.java
@@ -4,7 +4,7 @@ package mage.cards.g;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.RemoveFromCombatSourceEffect;
import mage.abilities.effects.common.UntapSourceEffect;
@@ -31,7 +31,7 @@ public final class GustcloakSkirmisher extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever Gustcloak Skirmisher becomes blocked, you may untap it and remove it from combat.
- Ability ability = new BecomesBlockedTriggeredAbility(new UntapSourceEffect(), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new UntapSourceEffect(), true);
Effect effect = new RemoveFromCombatSourceEffect();
effect.setText("and remove it from combat");
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/g/GyrudaDoomOfDepths.java b/Mage.Sets/src/mage/cards/g/GyrudaDoomOfDepths.java
index f96ad330fa3..effc47bf9a7 100644
--- a/Mage.Sets/src/mage/cards/g/GyrudaDoomOfDepths.java
+++ b/Mage.Sets/src/mage/cards/g/GyrudaDoomOfDepths.java
@@ -17,7 +17,6 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInGraveyard;
-import java.util.Collection;
import java.util.Set;
import java.util.UUID;
@@ -81,9 +80,8 @@ class GyrudaDoomOfDepthsEffect extends OneShotEffect {
GyrudaDoomOfDepthsEffect() {
super(Outcome.Benefit);
- staticText = "each player puts the top four cards of the library into their graveyard. " +
- "Put a creature card with an even converted mana cost from among those cards " +
- "onto the battlefield under your control.";
+ staticText = "each player mills four cards. Put a creature card with an even converted mana cost " +
+ "from among the milled cards onto the battlefield under your control";
}
private GyrudaDoomOfDepthsEffect(final GyrudaDoomOfDepthsEffect effect) {
@@ -102,15 +100,13 @@ class GyrudaDoomOfDepthsEffect extends OneShotEffect {
return false;
}
Cards cards = new CardsImpl();
- game.getState()
- .getPlayersInRange(source.getControllerId(), game)
- .stream()
- .map(game::getPlayer)
- .map(Player::getLibrary)
- .map(library -> library.getTopCards(game, 4))
- .flatMap(Collection::stream)
- .forEach(cards::add);
- controller.moveCards(cards, Zone.GRAVEYARD, source, game);
+ for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
+ }
+ cards.addAll(player.millCards(4, source, game));
+ }
cards.removeIf(cardId -> game.getState().getZone(cardId) != Zone.GRAVEYARD
&& game.getState().getZone(cardId) != Zone.EXILED);
if (cards.isEmpty()) {
diff --git a/Mage.Sets/src/mage/cards/h/HaakonStromgaldScourge.java b/Mage.Sets/src/mage/cards/h/HaakonStromgaldScourge.java
index edba324a79d..d9008934517 100644
--- a/Mage.Sets/src/mage/cards/h/HaakonStromgaldScourge.java
+++ b/Mage.Sets/src/mage/cards/h/HaakonStromgaldScourge.java
@@ -5,7 +5,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
@@ -41,7 +41,7 @@ public final class HaakonStromgaldScourge extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new HaakonPlayKnightsFromGraveyardEffect()));
// When Haakon dies, you lose 2 life.
- this.addAbility(new DiesTriggeredAbility(new LoseLifeSourceControllerEffect(2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new LoseLifeSourceControllerEffect(2)));
}
diff --git a/Mage.Sets/src/mage/cards/h/HaldanAvidArcanist.java b/Mage.Sets/src/mage/cards/h/HaldanAvidArcanist.java
index 0922bcbf4ef..4131e5765b5 100644
--- a/Mage.Sets/src/mage/cards/h/HaldanAvidArcanist.java
+++ b/Mage.Sets/src/mage/cards/h/HaldanAvidArcanist.java
@@ -34,7 +34,8 @@ public final class HaldanAvidArcanist extends CardImpl {
// Partner with Pako, Arcane Retriever
this.addAbility(new PartnerWithAbility("Pako, Arcane Retriever"));
- // You may play noncreature cards from exile with fetch counters on them if you exiled them, and you may spend mana as though it were mana of any color to cast those spells.
+ // You may play noncreature cards from exile with fetch counters on them if you
+ // exiled them, and you may spend mana as though it were mana of any color to cast those spells.
Ability ability = new SimpleStaticAbility(new HaldanAvidArcanistCastFromExileEffect());
ability.addEffect(new HaldanAvidArcanistSpendAnyManaEffect());
this.addAbility(ability);
@@ -56,7 +57,9 @@ public final class HaldanAvidArcanist extends CardImpl {
return false;
}
Card card = game.getCard(sourceId);
- return card != null && !card.isCreature() && card.getCounters(game).containsKey(CounterType.FETCH);
+ return card != null
+ && !card.isCreature()
+ && card.getCounters(game).containsKey(CounterType.FETCH);
}
}
@@ -110,11 +113,11 @@ class HaldanAvidArcanistSpendAnyManaEffect extends AsThoughEffectImpl implements
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- return HaldanAvidArcanist.checkCard(objectId, source, affectedControllerId, game);
+ return true;
}
@Override
public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
return mana.getFirstAvailable();
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/h/HallowedSpiritkeeper.java b/Mage.Sets/src/mage/cards/h/HallowedSpiritkeeper.java
index 99be8546da1..857fe640b90 100644
--- a/Mage.Sets/src/mage/cards/h/HallowedSpiritkeeper.java
+++ b/Mage.Sets/src/mage/cards/h/HallowedSpiritkeeper.java
@@ -3,7 +3,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -34,7 +34,7 @@ public final class HallowedSpiritkeeper extends CardImpl {
// When Hallowed Spiritkeeper dies, create X 1/1 white Spirit creature tokens with flying, where X is the number of creature cards in your graveyard.
Effect effect = new CreateTokenEffect(new SpiritWhiteToken(), new CardsInControllerGraveyardCount(new FilterCreatureCard("creature cards")));
effect.setText("create X 1/1 white Spirit creature tokens with flying, where X is the number of creature cards in your graveyard");
- this.addAbility(new DiesTriggeredAbility(effect, false));
+ this.addAbility(new DiesSourceTriggeredAbility(effect, false));
}
diff --git a/Mage.Sets/src/mage/cards/h/HammerOfNazahn.java b/Mage.Sets/src/mage/cards/h/HammerOfNazahn.java
index a973a49601e..44e9f58776f 100644
--- a/Mage.Sets/src/mage/cards/h/HammerOfNazahn.java
+++ b/Mage.Sets/src/mage/cards/h/HammerOfNazahn.java
@@ -1,9 +1,8 @@
package mage.cards.h;
-import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.Effect;
@@ -14,34 +13,29 @@ import mage.abilities.keyword.EquipAbility;
import mage.abilities.keyword.IndestructibleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AttachmentType;
-import mage.constants.CardType;
-import mage.constants.Outcome;
-import mage.constants.SetTargetPointer;
-import mage.constants.SubType;
-import mage.constants.SuperType;
-import mage.constants.Zone;
-import mage.filter.common.FilterEquipmentPermanent;
+import mage.constants.*;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author Saga
*/
public final class HammerOfNazahn extends CardImpl {
-
- private static final FilterEquipmentPermanent filter = new FilterEquipmentPermanent("{this} or another Equipment");
public HammerOfNazahn(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.EQUIPMENT);
-
+
// Whenever Hammer of Nazahn or another Equipment enters the battlefiend under your control, you may attach that Equipment to target creature you control.
- Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new HammerOfNazahnEffect(), filter, true, SetTargetPointer.PERMANENT, "");
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new HammerOfNazahnEffect(), StaticFilters.FILTER_PERMANENT_EQUIPMENT, true, SetTargetPointer.PERMANENT, true
+ );
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/h/HangarbackWalker.java b/Mage.Sets/src/mage/cards/h/HangarbackWalker.java
index 4570d903760..ce79708ffdd 100644
--- a/Mage.Sets/src/mage/cards/h/HangarbackWalker.java
+++ b/Mage.Sets/src/mage/cards/h/HangarbackWalker.java
@@ -4,7 +4,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@@ -37,7 +37,7 @@ public final class HangarbackWalker extends CardImpl {
this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance())));
// When Hangarback Walker dies, create a 1/1 colorless Thopter artifact creature token with flying for each +1/+1 counter on Hangarback Walker.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken(), new CountersSourceCount(CounterType.P1P1)), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken(), new CountersSourceCount(CounterType.P1P1)), false));
// {1}, {t}: Put a +1/+1 counter on Hangarback Walker.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new GenericManaCost(1));
diff --git a/Mage.Sets/src/mage/cards/h/HarmonicConvergence.java b/Mage.Sets/src/mage/cards/h/HarmonicConvergence.java
index 95dc56ddf90..5c33eb781a2 100644
--- a/Mage.Sets/src/mage/cards/h/HarmonicConvergence.java
+++ b/Mage.Sets/src/mage/cards/h/HarmonicConvergence.java
@@ -17,6 +17,9 @@ import mage.players.Player;
import mage.target.TargetCard;
import java.util.*;
+import mage.cards.Cards;
+import mage.filter.common.FilterEnchantmentPermanent;
+import mage.filter.predicate.other.OwnerIdPredicate;
/**
*
@@ -27,7 +30,6 @@ public final class HarmonicConvergence extends CardImpl {
public HarmonicConvergence(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{G}");
-
// Put all enchantments on top of their owners' libraries.
this.getSpellAbility().addEffect(new HarmonicConvergenceEffect());
}
@@ -60,44 +62,18 @@ class HarmonicConvergenceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- List enchantments = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_ENCHANTMENT_PERMANENT,
- source.getControllerId(),
- source.getSourceId(),
- game);
-
- Map> moveList = new HashMap<>();
- for (Permanent permanent : enchantments) {
- List list = moveList.computeIfAbsent(permanent.getControllerId(), k -> new ArrayList<>());
- list.add(permanent);
- }
-
- TargetCard target = new TargetCard(Zone.BATTLEFIELD, new FilterCard("card to put on top of your library"));
- for (UUID playerId : moveList.keySet()) {
+ for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
Player player = game.getPlayer(playerId);
- List list = moveList.get(playerId);
- if (player == null) {
- continue;
- }
-
- CardsImpl cards = new CardsImpl();
- for (Permanent permanent : list) {
- cards.add(permanent);
- }
- while (player.canRespond() && cards.size() > 1) {
- player.choose(Outcome.Neutral, cards, target, game);
- Permanent permanent = game.getPermanent(target.getFirstTarget());
- if (permanent != null) {
- cards.remove(permanent);
- permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
+ if (player != null) {
+ FilterEnchantmentPermanent filter = new FilterEnchantmentPermanent();
+ filter.add(new OwnerIdPredicate(player.getId()));
+ Cards toLib = new CardsImpl();
+ for(Permanent enchantment: game.getBattlefield().getActivePermanents(filter, playerId, source.getSourceId(), game)) {
+ toLib.add(enchantment);
}
- target.clearChosen();
- }
- if (cards.size() == 1) {
- Permanent permanent = game.getPermanent(cards.iterator().next());
- permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- }
-
+ player.putCardsOnTopOfLibrary(toLib, game, source, true);
+ }
+ }
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/h/HarvestHand.java b/Mage.Sets/src/mage/cards/h/HarvestHand.java
index 7661170773f..5a888543a5d 100644
--- a/Mage.Sets/src/mage/cards/h/HarvestHand.java
+++ b/Mage.Sets/src/mage/cards/h/HarvestHand.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
@@ -34,7 +34,7 @@ public final class HarvestHand extends CardImpl {
// When Harvest Hand dies, return it to the battlefield transformed under your control.
this.addAbility(new TransformAbility());
- this.addAbility(new DiesTriggeredAbility(new HarvestHandReturnTransformedEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new HarvestHandReturnTransformedEffect()));
}
public HarvestHand(final HarvestHand card) {
diff --git a/Mage.Sets/src/mage/cards/h/HauntedAngel.java b/Mage.Sets/src/mage/cards/h/HauntedAngel.java
index 7bdf24ead2a..ff9fe07823f 100644
--- a/Mage.Sets/src/mage/cards/h/HauntedAngel.java
+++ b/Mage.Sets/src/mage/cards/h/HauntedAngel.java
@@ -4,7 +4,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.keyword.FlyingAbility;
@@ -32,7 +32,7 @@ public final class HauntedAngel extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Haunted Angel dies, exile Haunted Angel and each other player creates a 3/3 black Angel creature token with flying.
- Ability ability = new DiesTriggeredAbility(new ExileSourceEffect());
+ Ability ability = new DiesSourceTriggeredAbility(new ExileSourceEffect());
ability.addEffect(new HauntedAngelEffect());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/h/HavocDemon.java b/Mage.Sets/src/mage/cards/h/HavocDemon.java
index aa285492e90..2be010eca2c 100644
--- a/Mage.Sets/src/mage/cards/h/HavocDemon.java
+++ b/Mage.Sets/src/mage/cards/h/HavocDemon.java
@@ -3,7 +3,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class HavocDemon extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Havoc Demon dies, all creatures get -5/-5 until end of turn.
- this.addAbility(new DiesTriggeredAbility(new BoostAllEffect(-5, -5, Duration.EndOfTurn), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new BoostAllEffect(-5, -5, Duration.EndOfTurn), false));
}
public HavocDemon(final HavocDemon card) {
diff --git a/Mage.Sets/src/mage/cards/h/HavocJester.java b/Mage.Sets/src/mage/cards/h/HavocJester.java
new file mode 100644
index 00000000000..ffa1ab353ec
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/HavocJester.java
@@ -0,0 +1,73 @@
+package mage.cards.h;
+
+import mage.MageInt;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.target.common.TargetAnyTarget;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class HavocJester extends CardImpl {
+
+ public HavocJester(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}");
+
+ this.subtype.add(SubType.DEVIL);
+ this.power = new MageInt(5);
+ this.toughness = new MageInt(5);
+
+ // Whenever you sacrifice a permanent, Havoc Jester deals 1 damage to any target.
+ this.addAbility(new HavocJesterTriggeredAbility());
+ }
+
+ private HavocJester(final HavocJester card) {
+ super(card);
+ }
+
+ @Override
+ public HavocJester copy() {
+ return new HavocJester(this);
+ }
+}
+
+class HavocJesterTriggeredAbility extends TriggeredAbilityImpl {
+
+ HavocJesterTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new DamageTargetEffect(1));
+ this.addTarget(new TargetAnyTarget());
+ }
+
+ private HavocJesterTriggeredAbility(final HavocJesterTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.SACRIFICED_PERMANENT;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ return event.getPlayerId().equals(getControllerId());
+ }
+
+ @Override
+ public HavocJesterTriggeredAbility copy() {
+ return new HavocJesterTriggeredAbility(this);
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever you sacrifice a permanent, {this} deals 1 damage to any target.";
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java b/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java
index ecf355dea2d..371e4e83e30 100644
--- a/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java
+++ b/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java
@@ -1,32 +1,29 @@
package mage.cards.h;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.abilities.keyword.EmbalmAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
-import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetAnyTarget;
+import mage.target.common.TargetControlledCreaturePermanent;
+
+import java.util.UUID;
/**
- *
* @author fireshoes
*/
public final class HeartPiercerManticore extends CardImpl {
@@ -39,16 +36,13 @@ public final class HeartPiercerManticore extends CardImpl {
this.toughness = new MageInt(3);
// When Heart-Piercer Manticore enters the battlefield, you may sacrifice another creature. When you do, Heart-Piercer Manticore deals damage equal to that creature's power to any target.
- this.addAbility(new EntersBattlefieldTriggeredAbility(
- new HeartPiercerManticoreSacrificeEffect(), true
- ));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new HeartPiercerManticoreSacrificeEffect(), true));
// Embalm {5}{R}
this.addAbility(new EmbalmAbility(new ManaCostsImpl("{5}{R}"), this));
-
}
- public HeartPiercerManticore(final HeartPiercerManticore card) {
+ private HeartPiercerManticore(final HeartPiercerManticore card) {
super(card);
}
@@ -60,13 +54,13 @@ public final class HeartPiercerManticore extends CardImpl {
class HeartPiercerManticoreSacrificeEffect extends OneShotEffect {
- public HeartPiercerManticoreSacrificeEffect() {
+ HeartPiercerManticoreSacrificeEffect() {
super(Outcome.Damage);
this.staticText = "sacrifice another creature. When you do, "
+ "{this} deals damage equal to that creature's power to any target";
}
- public HeartPiercerManticoreSacrificeEffect(final HeartPiercerManticoreSacrificeEffect effect) {
+ private HeartPiercerManticoreSacrificeEffect(final HeartPiercerManticoreSacrificeEffect effect) {
super(effect);
}
@@ -78,54 +72,29 @@ class HeartPiercerManticoreSacrificeEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Target target = new TargetControlledCreaturePermanent(1, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, true);
- if (controller.choose(outcome, target, source.getSourceId(), game)) {
- Permanent toSacrifice = game.getPermanent(target.getFirstTarget());
- if (toSacrifice != null) {
- DelayedTriggeredAbility trigger = new HeartPiercerManticoreReflexiveTriggeredAbility(toSacrifice.getPower().getValue());
- if (toSacrifice.sacrifice(source.getSourceId(), game)) {
- game.addDelayedTriggeredAbility(trigger, source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
- }
- }
- return true;
+ if (controller == null) {
+ return false;
}
- return false;
- }
-}
-
-class HeartPiercerManticoreReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- public HeartPiercerManticoreReflexiveTriggeredAbility(int damage) {
- super(new DamageTargetEffect(damage), Duration.OneUse, true);
- this.addTarget(new TargetAnyTarget());
- }
-
- public HeartPiercerManticoreReflexiveTriggeredAbility(final HeartPiercerManticoreReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public HeartPiercerManticoreReflexiveTriggeredAbility copy() {
- return new HeartPiercerManticoreReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When you sacrifice a creature to {this}'s ability, "
- + "{this} deals damage equal to that creature's power to any target";
+ Target target = new TargetControlledCreaturePermanent(
+ 1, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, true
+ );
+ if (!controller.choose(outcome, target, source.getSourceId(), game)) {
+ return false;
+ }
+ Permanent toSacrifice = game.getPermanent(target.getFirstTarget());
+ if (toSacrifice == null) {
+ return false;
+ }
+ int power = toSacrifice.getPower().getValue();
+ if (!toSacrifice.sacrifice(source.getSourceId(), game)) {
+ return false;
+ }
+ ReflexiveTriggeredAbility trigger = new ReflexiveTriggeredAbility(
+ new DamageTargetEffect(power), false,
+ "{this} deals damage equal to that creature's power to any target."
+ );
+ trigger.addTarget(new TargetAnyTarget());
+ game.fireReflexiveTriggeredAbility(trigger, source);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/h/HeartfireImmolator.java b/Mage.Sets/src/mage/cards/h/HeartfireImmolator.java
new file mode 100644
index 00000000000..89ca31facba
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/HeartfireImmolator.java
@@ -0,0 +1,55 @@
+package mage.cards.h;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.SacrificeSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.keyword.ProwessAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.target.common.TargetCreatureOrPlaneswalker;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class HeartfireImmolator extends CardImpl {
+
+ private static final DynamicValue xValue = new SourcePermanentPowerCount(false);
+
+ public HeartfireImmolator(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WIZARD);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Prowess
+ this.addAbility(new ProwessAbility());
+
+ // {R}, Sacrifice Heartfire Immolator: It deals damage equal to its power to target creature or planeswalker.
+ Ability ability = new SimpleActivatedAbility(
+ new DamageTargetEffect(xValue, "it"), new ManaCostsImpl("{R}")
+ );
+ ability.addCost(new SacrificeSourceCost());
+ ability.addTarget(new TargetCreatureOrPlaneswalker());
+ this.addAbility(ability);
+ }
+
+ private HeartfireImmolator(final HeartfireImmolator card) {
+ super(card);
+ }
+
+ @Override
+ public HeartfireImmolator copy() {
+ return new HeartfireImmolator(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/Heartstone.java b/Mage.Sets/src/mage/cards/h/Heartstone.java
index f2dabae26cd..9b65d308f3e 100644
--- a/Mage.Sets/src/mage/cards/h/Heartstone.java
+++ b/Mage.Sets/src/mage/cards/h/Heartstone.java
@@ -1,34 +1,27 @@
-
package mage.cards.h;
-import java.util.UUID;
-import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AbilityType;
-import mage.constants.CardType;
-import mage.constants.CostModificationType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
+import java.util.UUID;
+
/**
- *
* @author pcasaretto_at_gmail.com
*/
public final class Heartstone extends CardImpl {
public Heartstone(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// Activated abilities of creatures cost {1} less to activate. This effect can't reduce the amount of mana an ability costs to activate to less than one mana.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new HeartstoneEffect()));
@@ -62,10 +55,7 @@ class HeartstoneEffect extends CostModificationEffectImpl {
public boolean apply(Game game, Ability source, Ability abilityToModify) {
Player controller = game.getPlayer(abilityToModify.getControllerId());
if (controller != null) {
- Mana mana = abilityToModify.getManaCostsToPay().getMana();
- if (mana.count() > 1 && mana.getGeneric() > 0) {
- CardUtil.reduceCost(abilityToModify, 1);
- }
+ CardUtil.reduceCost(abilityToModify, 1);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/h/HedronBlade.java b/Mage.Sets/src/mage/cards/h/HedronBlade.java
index 463af05b0cd..41df7e6add5 100644
--- a/Mage.Sets/src/mage/cards/h/HedronBlade.java
+++ b/Mage.Sets/src/mage/cards/h/HedronBlade.java
@@ -100,6 +100,7 @@ class HedronBladeTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever equipped creature becomes blocked by one or more colorless creatures, " + super.getRule();
+ return "Whenever equipped creature becomes blocked by one or more colorless creatures, "
+ + "" + "it gains deathtouch until end of turn.";
}
}
diff --git a/Mage.Sets/src/mage/cards/h/HeedTheMists.java b/Mage.Sets/src/mage/cards/h/HeedTheMists.java
index 105251cecb2..bc92038248d 100644
--- a/Mage.Sets/src/mage/cards/h/HeedTheMists.java
+++ b/Mage.Sets/src/mage/cards/h/HeedTheMists.java
@@ -1,21 +1,20 @@
package mage.cards.h;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class HeedTheMists extends CardImpl {
@@ -41,7 +40,7 @@ public final class HeedTheMists extends CardImpl {
public HeedTheMistsEffect() {
super(Outcome.DrawCard);
- staticText = "Put the top card of your library into your graveyard, then draw cards equal to that card's converted mana cost";
+ staticText = "Mill a card, then draw cards equal to that card's converted mana cost";
}
public HeedTheMistsEffect(HeedTheMistsEffect effect) {
@@ -52,15 +51,14 @@ public final class HeedTheMists extends CardImpl {
public boolean apply(Game game, Ability source) {
boolean result = false;
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Card card = controller.getLibrary().getFromTop(game);
- if (card != null) {
- int cmc = card.getConvertedManaCost();
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- controller.drawCards(cmc, source.getSourceId(), game);
- }
- }
- return result;
+ int totalCMC = controller
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .mapToInt(MageObject::getConvertedManaCost)
+ .sum();
+ controller.millCards(totalCMC, source, game);
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/h/HellfireMongrel.java b/Mage.Sets/src/mage/cards/h/HellfireMongrel.java
index 125442d401c..da1da307dd9 100644
--- a/Mage.Sets/src/mage/cards/h/HellfireMongrel.java
+++ b/Mage.Sets/src/mage/cards/h/HellfireMongrel.java
@@ -25,7 +25,7 @@ public final class HellfireMongrel extends CardImpl {
public HellfireMongrel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}");
this.subtype.add(SubType.ELEMENTAL);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/h/HellkitePunisher.java b/Mage.Sets/src/mage/cards/h/HellkitePunisher.java
new file mode 100644
index 00000000000..f6509448db9
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/HellkitePunisher.java
@@ -0,0 +1,45 @@
+package mage.cards.h;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class HellkitePunisher extends CardImpl {
+
+ public HellkitePunisher(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}");
+
+ this.subtype.add(SubType.DRAGON);
+ this.power = new MageInt(6);
+ this.toughness = new MageInt(6);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // {R}: Hellkite Punisher gets +1/+0 until end of turn.
+ this.addAbility(new SimpleActivatedAbility(
+ new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}")
+ ));
+ }
+
+ private HellkitePunisher(final HellkitePunisher card) {
+ super(card);
+ }
+
+ @Override
+ public HellkitePunisher copy() {
+ return new HellkitePunisher(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HelmOfObedience.java b/Mage.Sets/src/mage/cards/h/HelmOfObedience.java
index bad8be25926..cfa04ab0036 100644
--- a/Mage.Sets/src/mage/cards/h/HelmOfObedience.java
+++ b/Mage.Sets/src/mage/cards/h/HelmOfObedience.java
@@ -1,7 +1,6 @@
-
package mage.cards.h;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@@ -11,6 +10,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -19,8 +19,12 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
/**
- *
* @author Plopman
*/
public final class HelmOfObedience extends CardImpl {
@@ -31,13 +35,13 @@ public final class HelmOfObedience extends CardImpl {
// {X}, {T}: Target opponent puts cards from the top of their library into their graveyard until a creature card or X cards are put into that graveyard this way, whichever comes first. If a creature card is put into that graveyard this way, sacrifice Helm of Obedience and put that card onto the battlefield under your control. X can't be 0.
VariableManaCost xCosts = new VariableManaCost();
xCosts.setMinX(1);
- SimpleActivatedAbility abilitiy = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HelmOfObedienceEffect(), xCosts);
+ SimpleActivatedAbility abilitiy = new SimpleActivatedAbility(new HelmOfObedienceEffect(), xCosts);
abilitiy.addCost(new TapSourceCost());
abilitiy.addTarget(new TargetOpponent());
this.addAbility(abilitiy);
}
- public HelmOfObedience(final HelmOfObedience card) {
+ private HelmOfObedience(final HelmOfObedience card) {
super(card);
}
@@ -51,12 +55,15 @@ class HelmOfObedienceEffect extends OneShotEffect {
private static final ManacostVariableValue amount = ManacostVariableValue.instance;
- public HelmOfObedienceEffect() {
+ HelmOfObedienceEffect() {
super(Outcome.Detriment);
- staticText = "Target opponent puts cards from the top of their library into their graveyard until a creature card or X cards are put into that graveyard this way, whichever comes first. If a creature card is put into that graveyard this way, sacrifice {this} and put that card onto the battlefield under your control. X can't be 0";
+ staticText = "Target opponent mills a card, then repeats this process until a creature card " +
+ "or X cards have been put into their graveyard this way, whichever comes first. " +
+ "If one or more creature cards were put into that graveyard this way, " +
+ "sacrifice {this} and put one of them onto the battlefield under your control. X can't be 0";
}
- public HelmOfObedienceEffect(final HelmOfObedienceEffect effect) {
+ private HelmOfObedienceEffect(final HelmOfObedienceEffect effect) {
super(effect);
}
@@ -70,32 +77,32 @@ class HelmOfObedienceEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player targetOpponent = game.getPlayer(targetPointer.getFirst(game, source));
int max = amount.calculate(game, source, this);
- if (targetOpponent != null && controller != null && max > 0) {
- int numberOfCard = 0;
- for (Card card : targetOpponent.getLibrary().getCards(game)) {
- if (card != null) {
- if (targetOpponent.moveCards(card, Zone.GRAVEYARD, source, game)) {
- if (card.isCreature()) {
- // If a creature card is put into that graveyard this way, sacrifice Helm of Obedience
- // and put that card onto the battlefield under your control.
- Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
- if (sourcePermanent != null) {
- sourcePermanent.sacrifice(source.getSourceId(), game);
- }
- controller.moveCards(card, Zone.BATTLEFIELD, source, game);
- break;
- } else {
- numberOfCard++;
- if (numberOfCard >= max) {
- break;
- }
- }
- }
- }
- }
- return true;
+ if (targetOpponent == null || controller == null || max <= 0) {
+ return false;
}
- return false;
+ int numberOfCard = 0;
+ while (targetOpponent.getLibrary().hasCards()) {
+ Cards cards = targetOpponent.millCards(1, source, game);
+ cards.removeIf(uuid -> game.getState().getZone(uuid) != Zone.GRAVEYARD);
+ numberOfCard += cards.size();
+ Set creatures = cards
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(MageObject::isCreature)
+ .collect(Collectors.toSet());
+ if (!creatures.isEmpty()) {
+ controller.moveCards(creatures, Zone.BATTLEFIELD, source, game);
+ }
+ if (!creatures.isEmpty() || numberOfCard >= max) {
+ Permanent permanent = game.getPermanent(source.getSourceId());
+ if (permanent != null) {
+ permanent.sacrifice(source.getSourceId(), game);
+ }
+ break;
+ }
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/h/Helvault.java b/Mage.Sets/src/mage/cards/h/Helvault.java
index 3a02b95c3ae..325e1aadad3 100644
--- a/Mage.Sets/src/mage/cards/h/Helvault.java
+++ b/Mage.Sets/src/mage/cards/h/Helvault.java
@@ -1,6 +1,6 @@
package mage.cards.h;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
@@ -39,7 +39,7 @@ public final class Helvault extends CardImpl {
this.addAbility(ability);
// When Helvault is put into a graveyard from the battlefield, return all cards exiled with it to the battlefield under their owners' control.
- this.addAbility(new DiesTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD)));
+ this.addAbility(new DiesSourceTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD)));
}
private Helvault(final Helvault card) {
diff --git a/Mage.Sets/src/mage/cards/h/HeraldOfLeshrac.java b/Mage.Sets/src/mage/cards/h/HeraldOfLeshrac.java
index 1ae97254ffe..ec94e92c5ee 100644
--- a/Mage.Sets/src/mage/cards/h/HeraldOfLeshrac.java
+++ b/Mage.Sets/src/mage/cards/h/HeraldOfLeshrac.java
@@ -97,7 +97,7 @@ class HeraldOfLeshracCumulativeCost extends CostImpl {
ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfGame);
effect.setTargetPointer(new FixedTarget(target.getFirstTarget()));
game.addEffect(effect, ability);
- game.applyEffects();
+ game.getState().processAction(game);
paid = true;
}
return paid;
diff --git a/Mage.Sets/src/mage/cards/h/HeraldOfTheDreadhorde.java b/Mage.Sets/src/mage/cards/h/HeraldOfTheDreadhorde.java
index ef383f86e43..0538dfcd8b1 100644
--- a/Mage.Sets/src/mage/cards/h/HeraldOfTheDreadhorde.java
+++ b/Mage.Sets/src/mage/cards/h/HeraldOfTheDreadhorde.java
@@ -1,7 +1,7 @@
package mage.cards.h;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.keyword.AmassEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class HeraldOfTheDreadhorde extends CardImpl {
this.toughness = new MageInt(2);
// When Herald of the Dreadhorde dies, amass 2.
- this.addAbility(new DiesTriggeredAbility(new AmassEffect(2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new AmassEffect(2)));
}
private HeraldOfTheDreadhorde(final HeraldOfTheDreadhorde card) {
diff --git a/Mage.Sets/src/mage/cards/h/HereticsPunishment.java b/Mage.Sets/src/mage/cards/h/HereticsPunishment.java
index 71c4bbe179f..87439fa4df6 100644
--- a/Mage.Sets/src/mage/cards/h/HereticsPunishment.java
+++ b/Mage.Sets/src/mage/cards/h/HereticsPunishment.java
@@ -1,21 +1,20 @@
package mage.cards.h;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
-import java.util.Set;
+import java.util.Objects;
import java.util.UUID;
/**
@@ -27,7 +26,7 @@ public final class HereticsPunishment extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{R}");
// {3}{R}: Choose any target, then put the top three cards of your library into your graveyard. Heretic's Punishment deals damage to that creature or player equal to the highest converted mana cost among those cards.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HereticsPunishmentEffect(), new ManaCostsImpl("{3}{R}"));
+ Ability ability = new SimpleActivatedAbility(new HereticsPunishmentEffect(), new ManaCostsImpl("{3}{R}"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
@@ -46,7 +45,7 @@ class HereticsPunishmentEffect extends OneShotEffect {
public HereticsPunishmentEffect() {
super(Outcome.Damage);
- staticText = "Choose any target, then put the top three cards of your library into your graveyard. {this} deals damage to that permanent or player equal to the highest converted mana cost among those cards";
+ staticText = "Choose any target, then mill three cards. {this} deals damage to that permanent or player equal to the highest converted mana cost among the milled cards";
}
public HereticsPunishmentEffect(final HereticsPunishmentEffect effect) {
@@ -56,26 +55,26 @@ class HereticsPunishmentEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- int maxCost = 0;
- Set cardList = controller.getLibrary().getTopCards(game, 3);
- for (Card card : cardList) {
- int test = card.getConvertedManaCost();
- if (test > maxCost) {
- maxCost = test;
- }
- }
- controller.moveCards(cardList, Zone.GRAVEYARD, source, game);
- Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
- if (permanent != null) {
- permanent.damage(maxCost, source.getSourceId(), game, false, true);
- return true;
- }
- Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
- if (targetPlayer != null) {
- targetPlayer.damage(maxCost, source.getSourceId(), game);
- return true;
- }
+ if (controller == null) {
+ return false;
+ }
+ int maxCost = controller
+ .millCards(3, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .mapToInt(MageObject::getConvertedManaCost)
+ .max()
+ .orElse(0);
+ Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
+ if (permanent != null) {
+ permanent.damage(maxCost, source.getSourceId(), game, false, true);
+ return true;
+ }
+ Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
+ if (targetPlayer != null) {
+ targetPlayer.damage(maxCost, source.getSourceId(), game);
+ return true;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/h/HeroOfIroas.java b/Mage.Sets/src/mage/cards/h/HeroOfIroas.java
index 21855980f9d..f00ae978c61 100644
--- a/Mage.Sets/src/mage/cards/h/HeroOfIroas.java
+++ b/Mage.Sets/src/mage/cards/h/HeroOfIroas.java
@@ -1,7 +1,5 @@
-
package mage.cards.h;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
@@ -15,19 +13,21 @@ import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.FilterCard;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class HeroOfIroas extends CardImpl {
private static final FilterCard filter = new FilterCard("Aura spells");
+
static {
filter.add(SubType.AURA.getPredicate());
}
public HeroOfIroas(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SOLDIER);
@@ -36,6 +36,7 @@ public final class HeroOfIroas extends CardImpl {
// Aura spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
+
// Heroic — Whenever you cast a spell that targets Hero of Iroas, put a +1/+1 counter on Hero of Iroas.
this.addAbility(new HeroicAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())));
}
diff --git a/Mage.Sets/src/mage/cards/h/HierophantsChalice.java b/Mage.Sets/src/mage/cards/h/HierophantsChalice.java
index d803d89a9b2..8fa3f4a8b89 100644
--- a/Mage.Sets/src/mage/cards/h/HierophantsChalice.java
+++ b/Mage.Sets/src/mage/cards/h/HierophantsChalice.java
@@ -1,7 +1,5 @@
-
package mage.cards.h;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
@@ -13,8 +11,9 @@ import mage.constants.CardType;
import mage.target.Target;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class HierophantsChalice extends CardImpl {
@@ -24,7 +23,7 @@ public final class HierophantsChalice extends CardImpl {
// When Hierophant's Chalice enters the battlefield, target opponent loses 1 life and you gain 1 life.
Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(1), false);
- ability.addEffect(new GainLifeEffect(1).setText("and you gain one life."));
+ ability.addEffect(new GainLifeEffect(1).concatBy("and"));
Target target = new TargetOpponent();
ability.addTarget(target);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/h/HighSeas.java b/Mage.Sets/src/mage/cards/h/HighSeas.java
index 412c56ce64c..652a5c6f17b 100644
--- a/Mage.Sets/src/mage/cards/h/HighSeas.java
+++ b/Mage.Sets/src/mage/cards/h/HighSeas.java
@@ -1,35 +1,36 @@
-
package mage.cards.h;
-import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class HighSeas extends CardImpl {
-
+
private static final FilterCreatureCard filter = new FilterCreatureCard("Red creature spells and green creature spells");
+
static {
filter.add(Predicates.or(new ColorPredicate(ObjectColor.RED),
(new ColorPredicate(ObjectColor.GREEN))));
}
public HighSeas(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
// Red creature spells and green creature spells cost {1} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasementAllEffect(filter, 1)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(1, filter, TargetController.ANY)));
}
public HighSeas(final HighSeas card) {
diff --git a/Mage.Sets/src/mage/cards/h/HighlandGame.java b/Mage.Sets/src/mage/cards/h/HighlandGame.java
index 27d939079ec..65f04583c0e 100644
--- a/Mage.Sets/src/mage/cards/h/HighlandGame.java
+++ b/Mage.Sets/src/mage/cards/h/HighlandGame.java
@@ -3,7 +3,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class HighlandGame extends CardImpl {
this.toughness = new MageInt(1);
// When Highland Game dies, you gain 2 life.
- this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(2)));
}
public HighlandGame(final HighlandGame card) {
diff --git a/Mage.Sets/src/mage/cards/h/HintOfInsanity.java b/Mage.Sets/src/mage/cards/h/HintOfInsanity.java
index 1d299587214..d41189a633a 100644
--- a/Mage.Sets/src/mage/cards/h/HintOfInsanity.java
+++ b/Mage.Sets/src/mage/cards/h/HintOfInsanity.java
@@ -1,21 +1,26 @@
package mage.cards.h;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.*;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
-import mage.target.common.TargetCardInHand;
-import mage.util.CardUtil;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
import java.util.UUID;
+import java.util.stream.Collectors;
/**
- * @author jeffwadsworth
+ * @author TheElk801
*/
public final class HintOfInsanity extends CardImpl {
@@ -25,10 +30,9 @@ public final class HintOfInsanity extends CardImpl {
// Target player reveals their hand. That player discards all nonland cards with the same name as another card in their hand.
this.getSpellAbility().addEffect(new HintOfInsanityEffect());
this.getSpellAbility().addTarget(new TargetPlayer());
-
}
- public HintOfInsanity(final HintOfInsanity card) {
+ private HintOfInsanity(final HintOfInsanity card) {
super(card);
}
@@ -40,12 +44,13 @@ public final class HintOfInsanity extends CardImpl {
class HintOfInsanityEffect extends OneShotEffect {
- public HintOfInsanityEffect() {
+ HintOfInsanityEffect() {
super(Outcome.Discard);
- this.staticText = "Target player reveals their hand. That player discards all nonland cards with the same name as another card in their hand";
+ this.staticText = "Target player reveals their hand. " +
+ "That player discards all nonland cards with the same name as another card in their hand";
}
- public HintOfInsanityEffect(final HintOfInsanityEffect effect) {
+ private HintOfInsanityEffect(final HintOfInsanityEffect effect) {
super(effect);
}
@@ -56,26 +61,26 @@ class HintOfInsanityEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- FilterCard filter = new FilterCard("card from your hand");
- Player targetPlayer = game.getPlayer(source.getFirstTarget());
- Card chosenCard;
- if (targetPlayer != null) {
- TargetCardInHand targetCard = new TargetCardInHand(filter);
- targetCard.setNotTarget(true);
- Cards cardsInHand = new CardsImpl();
- cardsInHand.addAll(targetPlayer.getHand());
- targetPlayer.revealCards("Hint of Insanity Reveal", cardsInHand, game);
- if (!cardsInHand.isEmpty()
- && targetPlayer.choose(Outcome.Discard, targetCard, source.getSourceId(), game)) {
- chosenCard = game.getCard(targetCard.getFirstTarget());
- for (Card card : cardsInHand.getCards(game)) {
- if (CardUtil.haveSameNames(card, chosenCard) && !card.isLand()) {
- targetPlayer.discard(card, source, game);
- }
- }
- return true;
- }
+ Player player = game.getPlayer(source.getFirstTarget());
+ if (player == null) {
+ return false;
}
- return false;
+ Map nameCounts = new HashMap<>();
+ player.getHand()
+ .getCards(game)
+ .stream()
+ .map(MageObject::getName)
+ .forEach(s -> nameCounts.compute(s, (u, i) -> i == null ? 1 : Integer.sum(i, 1)));
+ Cards cards = new CardsImpl(
+ player.getHand()
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(card -> !card.isLand())
+ .filter(card -> nameCounts.getOrDefault(card.getName(), 0) > 1)
+ .collect(Collectors.toSet())
+ );
+ player.discard(cards, source, game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/h/HisokasGuard.java b/Mage.Sets/src/mage/cards/h/HisokasGuard.java
index 0d11887e2aa..886b4aea6d9 100644
--- a/Mage.Sets/src/mage/cards/h/HisokasGuard.java
+++ b/Mage.Sets/src/mage/cards/h/HisokasGuard.java
@@ -100,7 +100,7 @@ class HisokasGuardGainAbilityTargetEffect extends ContinuousEffectImpl {
if (hisokasGuard != null && !hisokasGuard.getConnectedCards("HisokasGuard").isEmpty()) {
Permanent guardedCreature = game.getPermanent(hisokasGuard.getConnectedCards("HisokasGuard").get(0));
if (guardedCreature != null && hisokasGuard.isTapped()) {
- guardedCreature.addAbility(ability, game);
+ guardedCreature.addAbility(ability, source.getSourceId(), game);
return true;
} else {
// if guard isn't tapped, the effect is no more valid
diff --git a/Mage.Sets/src/mage/cards/h/HistorianOfZhalfir.java b/Mage.Sets/src/mage/cards/h/HistorianOfZhalfir.java
new file mode 100644
index 00000000000..4bbe30d4f37
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/HistorianOfZhalfir.java
@@ -0,0 +1,49 @@
+package mage.cards.h;
+
+import mage.MageInt;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPlaneswalkerPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class HistorianOfZhalfir extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledPlaneswalkerPermanent(SubType.TEFERI);
+ private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
+
+ public HistorianOfZhalfir(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WIZARD);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Whenever Historian of Zhalfir attacks, if you control a Teferi planeswalker, draw a card.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new AttacksTriggeredAbility(new DrawCardSourceControllerEffect(1), false),
+ condition, "Whenever {this} attacks, if you control a Teferi planeswalker, draw a card")
+ );
+ }
+
+ private HistorianOfZhalfir(final HistorianOfZhalfir card) {
+ super(card);
+ }
+
+ @Override
+ public HistorianOfZhalfir copy() {
+ return new HistorianOfZhalfir(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HoardingDragon.java b/Mage.Sets/src/mage/cards/h/HoardingDragon.java
index a5a5b394b64..1a42bc8d5fa 100644
--- a/Mage.Sets/src/mage/cards/h/HoardingDragon.java
+++ b/Mage.Sets/src/mage/cards/h/HoardingDragon.java
@@ -6,7 +6,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromExileEffect;
@@ -44,7 +44,7 @@ public final class HoardingDragon extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new HoardingDragonEffect(this.getId()), true));
// When Hoarding Dragon dies, you may put the exiled card into its owner's hand.
- this.addAbility(new DiesTriggeredAbility(new ReturnFromExileEffect(this.getId(), Zone.HAND), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new ReturnFromExileEffect(this.getId(), Zone.HAND), false));
}
public HoardingDragon(final HoardingDragon card) {
diff --git a/Mage.Sets/src/mage/cards/h/Hobblefiend.java b/Mage.Sets/src/mage/cards/h/Hobblefiend.java
new file mode 100644
index 00000000000..7f81332b250
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/Hobblefiend.java
@@ -0,0 +1,53 @@
+package mage.cards.h;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.SacrificeTargetCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.common.counter.AddCountersSourceEffect;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+import mage.filter.StaticFilters;
+import mage.target.common.TargetControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class Hobblefiend extends CardImpl {
+
+ public Hobblefiend(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
+
+ this.subtype.add(SubType.DEVIL);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // Trample
+ this.addAbility(TrampleAbility.getInstance());
+
+ // {1}, Sacrifice another creature: Put a +1/+1 counter on Hobblefiend.
+ Ability ability = new SimpleActivatedAbility(
+ new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new GenericManaCost(1)
+ );
+ ability.addCost(new SacrificeTargetCost(
+ new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)
+ ));
+ this.addAbility(ability);
+ }
+
+ private Hobblefiend(final Hobblefiend card) {
+ super(card);
+ }
+
+ @Override
+ public Hobblefiend copy() {
+ return new Hobblefiend(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HoldTheGates.java b/Mage.Sets/src/mage/cards/h/HoldTheGates.java
index e8b5b306757..1cdda2a3b14 100644
--- a/Mage.Sets/src/mage/cards/h/HoldTheGates.java
+++ b/Mage.Sets/src/mage/cards/h/HoldTheGates.java
@@ -13,7 +13,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
-import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.StaticFilters;
import java.util.UUID;
@@ -25,12 +25,14 @@ public final class HoldTheGates extends CardImpl {
public HoldTheGates(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
-
// Creatures you control get +0/+1 for each Gate you control and have vigilance.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD,
- new BoostControlledEffect(StaticValue.get(0), GateYouControlCount.instance, Duration.WhileOnBattlefield));
- ability.addEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, new FilterControlledCreaturePermanent("Creatures"))
- .setText("Creatures you control get +0/+1 for each Gate you control and have vigilance"));
+ new BoostControlledEffect(StaticValue.get(0), GateYouControlCount.instance, Duration.WhileOnBattlefield)
+ );
+ ability.addEffect(
+ new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED)
+ .setText("and have vigilance")
+ );
ability.addHint(GateYouControlHint.instance);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/h/HollowDogs.java b/Mage.Sets/src/mage/cards/h/HollowDogs.java
index 16f4eaa5e77..b2daa9ed901 100644
--- a/Mage.Sets/src/mage/cards/h/HollowDogs.java
+++ b/Mage.Sets/src/mage/cards/h/HollowDogs.java
@@ -20,7 +20,7 @@ public final class HollowDogs extends CardImpl {
public HollowDogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}");
this.subtype.add(SubType.ZOMBIE);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java b/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java
index 21a5fe789f7..3e8991c95ee 100644
--- a/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java
+++ b/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java
@@ -36,7 +36,7 @@ public final class HollowbornBarghest extends CardImpl {
public HollowbornBarghest(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}");
this.subtype.add(SubType.DEMON);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(7);
this.toughness = new MageInt(6);
diff --git a/Mage.Sets/src/mage/cards/h/Hollowsage.java b/Mage.Sets/src/mage/cards/h/Hollowsage.java
index d8d2aa755e8..5ccc5a6d99b 100644
--- a/Mage.Sets/src/mage/cards/h/Hollowsage.java
+++ b/Mage.Sets/src/mage/cards/h/Hollowsage.java
@@ -1,84 +1,42 @@
-
package mage.cards.h;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.TriggeredAbility;
-import mage.abilities.TriggeredAbilityImpl;
-import mage.abilities.effects.Effect;
+import mage.abilities.Ability;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
+import mage.abilities.keyword.InspiredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.game.events.GameEvent;
-import mage.game.events.GameEvent.EventType;
import mage.target.TargetPlayer;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
*/
public final class Hollowsage extends CardImpl {
-
+
public Hollowsage(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
this.subtype.add(SubType.MERFOLK);
this.subtype.add(SubType.WIZARD);
-
+
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Whenever Hollowsage becomes untapped, you may have target player discard a card.
- TriggeredAbility ability = new BecomesUntappedTriggeredAbility(new DiscardTargetEffect(1), true);
+ Ability ability = new InspiredAbility(new DiscardTargetEffect(1), true, false);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
-
}
-
+
public Hollowsage(final Hollowsage card) {
super(card);
}
-
+
@Override
public Hollowsage copy() {
return new Hollowsage(this);
}
}
-
-class BecomesUntappedTriggeredAbility extends TriggeredAbilityImpl {
-
- public BecomesUntappedTriggeredAbility(Effect effect, boolean isOptional) {
- super(Zone.BATTLEFIELD, effect, isOptional);
- }
-
- public BecomesUntappedTriggeredAbility(Effect effect) {
- super(Zone.BATTLEFIELD, effect);
- }
-
- public BecomesUntappedTriggeredAbility(final BecomesUntappedTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public BecomesUntappedTriggeredAbility copy() {
- return new BecomesUntappedTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == EventType.UNTAPPED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getTargetId().equals(sourceId);
- }
-
- @Override
- public String getRule() {
- return "When {this} becomes untapped, " + super.getRule();
- }
-}
diff --git a/Mage.Sets/src/mage/cards/h/HomuraHumanAscendant.java b/Mage.Sets/src/mage/cards/h/HomuraHumanAscendant.java
index 6a06beb23d3..6b9715e047c 100644
--- a/Mage.Sets/src/mage/cards/h/HomuraHumanAscendant.java
+++ b/Mage.Sets/src/mage/cards/h/HomuraHumanAscendant.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.CantBlockAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.FlippedCondition;
@@ -50,7 +50,7 @@ public final class HomuraHumanAscendant extends CardImpl {
// Homura, Human Ascendant can't block.
this.addAbility(new CantBlockAbility());
// When Homura dies, return it to the battlefield flipped.
- this.addAbility(new DiesTriggeredAbility(new HomuraReturnFlippedSourceEffect(new HomurasEssence2())));
+ this.addAbility(new DiesSourceTriggeredAbility(new HomuraReturnFlippedSourceEffect(new HomurasEssence2())));
}
public HomuraHumanAscendant(final HomuraHumanAscendant card) {
diff --git a/Mage.Sets/src/mage/cards/h/HoodedBlightfang.java b/Mage.Sets/src/mage/cards/h/HoodedBlightfang.java
new file mode 100644
index 00000000000..f3eb71472d1
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/HoodedBlightfang.java
@@ -0,0 +1,58 @@
+package mage.cards.h;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility;
+import mage.abilities.common.DestroyPlaneswalkerWhenDamagedTriggeredAbility;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.common.LoseLifeOpponentsEffect;
+import mage.abilities.keyword.DeathtouchAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class HoodedBlightfang extends CardImpl {
+
+ private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a creature you control with deathtouch");
+
+ static {
+ filter.add(new AbilityPredicate(DeathtouchAbility.class));
+ }
+
+ public HoodedBlightfang(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
+
+ this.subtype.add(SubType.SNAKE);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(4);
+
+ // Deathtouch
+ this.addAbility(DeathtouchAbility.getInstance());
+
+ // Whenever a creature you control with deathtouch attacks, each opponent loses 1 life and you gain 1 life.
+ Ability ability = new AttacksCreatureYouControlTriggeredAbility(new LoseLifeOpponentsEffect(1), false, filter);
+ ability.addEffect(new GainLifeEffect(1).setText("and you gain 1 life"));
+ this.addAbility(ability);
+
+ // Whenever a creature you control with deathtouch deals damage to a planeswalker, destroy that planeswalker.
+ this.addAbility(new DestroyPlaneswalkerWhenDamagedTriggeredAbility(filter));
+ }
+
+ private HoodedBlightfang(final HoodedBlightfang card) {
+ super(card);
+ }
+
+ @Override
+ public HoodedBlightfang copy() {
+ return new HoodedBlightfang(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HoodedHydra.java b/Mage.Sets/src/mage/cards/h/HoodedHydra.java
index 379d8270aaa..38c59f42d3e 100644
--- a/Mage.Sets/src/mage/cards/h/HoodedHydra.java
+++ b/Mage.Sets/src/mage/cards/h/HoodedHydra.java
@@ -4,7 +4,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -41,7 +41,7 @@ public final class HoodedHydra extends CardImpl {
this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance())));
// When Hooded Hydra dies, create a 1/1 green Snake creature token for each +1/+1 counter on it.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SnakeToken("KTK"), new CountersSourceCount(CounterType.P1P1)), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new SnakeToken("KTK"), new CountersSourceCount(CounterType.P1P1)), false));
// Morph {3}{G}{G}
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{3}{G}{G}")));
diff --git a/Mage.Sets/src/mage/cards/h/HorizonSpellbomb.java b/Mage.Sets/src/mage/cards/h/HorizonSpellbomb.java
index 5a2246cb104..d2b560305d7 100644
--- a/Mage.Sets/src/mage/cards/h/HorizonSpellbomb.java
+++ b/Mage.Sets/src/mage/cards/h/HorizonSpellbomb.java
@@ -1,7 +1,7 @@
package mage.cards.h;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
@@ -35,7 +35,7 @@ public final class HorizonSpellbomb extends CardImpl {
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
// When Horizon Spellbomb is put into a graveyard from the battlefield, you may pay {G}. If you do, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{G}"))));
+ this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{G}"))));
}
public HorizonSpellbomb(final HorizonSpellbomb card) {
diff --git a/Mage.Sets/src/mage/cards/h/HornetHarasser.java b/Mage.Sets/src/mage/cards/h/HornetHarasser.java
index b6aa781c473..7cd503d8aff 100644
--- a/Mage.Sets/src/mage/cards/h/HornetHarasser.java
+++ b/Mage.Sets/src/mage/cards/h/HornetHarasser.java
@@ -4,7 +4,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class HornetHarasser extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
- Ability ability = new DiesTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn), false);
+ Ability ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn), false);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/h/HoundOfGriselbrand.java b/Mage.Sets/src/mage/cards/h/HoundOfGriselbrand.java
index 938d4821645..50a3b66a2a2 100644
--- a/Mage.Sets/src/mage/cards/h/HoundOfGriselbrand.java
+++ b/Mage.Sets/src/mage/cards/h/HoundOfGriselbrand.java
@@ -19,7 +19,7 @@ public final class HoundOfGriselbrand extends CardImpl {
public HoundOfGriselbrand(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}");
this.subtype.add(SubType.ELEMENTAL);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/h/HoundOfTheFarbogs.java b/Mage.Sets/src/mage/cards/h/HoundOfTheFarbogs.java
index 9206adf00fc..3af2670f038 100644
--- a/Mage.Sets/src/mage/cards/h/HoundOfTheFarbogs.java
+++ b/Mage.Sets/src/mage/cards/h/HoundOfTheFarbogs.java
@@ -28,7 +28,7 @@ public final class HoundOfTheFarbogs extends CardImpl {
public HoundOfTheFarbogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
this.subtype.add(SubType.ZOMBIE);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(5);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/h/HourOfGlory.java b/Mage.Sets/src/mage/cards/h/HourOfGlory.java
index 5be4f80dcbf..4f4dfb27378 100644
--- a/Mage.Sets/src/mage/cards/h/HourOfGlory.java
+++ b/Mage.Sets/src/mage/cards/h/HourOfGlory.java
@@ -69,7 +69,7 @@ class HourOfGloryEffect extends OneShotEffect {
if (targetCreature != null) {
controller.moveCards(targetCreature, Zone.EXILED, source, game);
if (targetCreature.hasSubtype(SubType.GOD, game)) {
- game.applyEffects();
+ game.getState().processAction(game);
Player targetController = game.getPlayer(targetCreature.getControllerId());
if (targetController != null) {
targetController.revealCards(sourceObject.getIdName(), targetController.getHand(), game);
diff --git a/Mage.Sets/src/mage/cards/h/HourOfRevelation.java b/Mage.Sets/src/mage/cards/h/HourOfRevelation.java
index 15eb45648a6..8ba5adb7638 100644
--- a/Mage.Sets/src/mage/cards/h/HourOfRevelation.java
+++ b/Mage.Sets/src/mage/cards/h/HourOfRevelation.java
@@ -1,11 +1,11 @@
-
package mage.cards.h;
-import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -13,8 +13,9 @@ import mage.constants.ComparisonType;
import mage.constants.Zone;
import mage.filter.common.FilterNonlandPermanent;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class HourOfRevelation extends CardImpl {
@@ -23,10 +24,12 @@ public final class HourOfRevelation extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}{W}{W}");
// Hour of Revelation costs {3} less to cast if there are ten or more nonland permanents on the battlefield.
- SimpleStaticAbility ability = new SimpleStaticAbility(Zone.STACK,
+ SimpleStaticAbility ability = new SimpleStaticAbility(Zone.ALL,
new SpellCostReductionSourceEffect(3, new PermanentsOnTheBattlefieldCondition(
- new FilterNonlandPermanent("there are ten or more nonland permanents on the battlefield"), ComparisonType.MORE_THAN, 9, false)));
+ new FilterNonlandPermanent("there are ten or more nonland permanents on the battlefield"),
+ ComparisonType.MORE_THAN, 9, false)));
ability.setRuleAtTheTop(true);
+ ability.addHint(new ValueHint("Nonland permanents on the battlefield", new PermanentsOnBattlefieldCount(new FilterNonlandPermanent())));
this.addAbility(ability);
// Destroy all nonland permanents.
diff --git a/Mage.Sets/src/mage/cards/h/HumOfTheRadix.java b/Mage.Sets/src/mage/cards/h/HumOfTheRadix.java
index 3eafa3ed173..7e806c12c61 100644
--- a/Mage.Sets/src/mage/cards/h/HumOfTheRadix.java
+++ b/Mage.Sets/src/mage/cards/h/HumOfTheRadix.java
@@ -1,7 +1,5 @@
-
package mage.cards.h;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
@@ -9,17 +7,14 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.CostModificationType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.common.FilterArtifactPermanent;
import mage.game.Game;
import mage.util.CardUtil;
+import java.util.UUID;
+
/**
- *
* @author Pete Rossi
*/
public final class HumOfTheRadix extends CardImpl {
@@ -56,9 +51,7 @@ class HumOfTheRadixCostIncreaseEffect extends CostModificationEffectImpl {
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
int additionalCost = game.getBattlefield().getAllActivePermanents(new FilterArtifactPermanent(), abilityToModify.getControllerId(), game).size();
- if (additionalCost > 0) {
- CardUtil.increaseCost(abilityToModify, additionalCost);
- }
+ CardUtil.increaseCost(abilityToModify, additionalCost);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/h/HungerOfTheNim.java b/Mage.Sets/src/mage/cards/h/HungerOfTheNim.java
index 657891ee47e..28dfd0b529a 100644
--- a/Mage.Sets/src/mage/cards/h/HungerOfTheNim.java
+++ b/Mage.Sets/src/mage/cards/h/HungerOfTheNim.java
@@ -1,38 +1,31 @@
-
package mage.cards.h;
-import java.util.UUID;
-import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
-import mage.filter.common.FilterControlledPermanent;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class HungerOfTheNim extends CardImpl {
- private static final FilterControlledPermanent filter = new FilterControlledPermanent("artifact you control");
-
- static {
- filter.add(CardType.ARTIFACT.getPredicate());
- }
-
public HungerOfTheNim(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
// Target creature gets +1/+0 until end of turn for each artifact you control.
- Effect effect = new BoostTargetEffect(new PermanentsOnBattlefieldCount(filter), StaticValue.get(0), Duration.EndOfTurn, true);
- effect.setText("Target creature gets +1/+0 until end of turn for each artifact you control");
+ Effect effect = new BoostTargetEffect(ArtifactYouControlCount.instance, StaticValue.get(0), Duration.EndOfTurn, true);
getSpellAbility().addEffect(effect);
getSpellAbility().addTarget(new TargetCreaturePermanent());
+ getSpellAbility().addHint(ArtifactYouControlHint.instance);
}
public HungerOfTheNim(final HungerOfTheNim card) {
diff --git a/Mage.Sets/src/mage/cards/h/HuntedWitness.java b/Mage.Sets/src/mage/cards/h/HuntedWitness.java
index 33c60a31772..436b98c9b31 100644
--- a/Mage.Sets/src/mage/cards/h/HuntedWitness.java
+++ b/Mage.Sets/src/mage/cards/h/HuntedWitness.java
@@ -2,7 +2,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
@@ -24,7 +24,7 @@ public final class HuntedWitness extends CardImpl {
this.toughness = new MageInt(1);
// When Hunted Witness dies, create a 1/1 white Soldier creature token with lifelink.
- this.addAbility(new DiesTriggeredAbility(
+ this.addAbility(new DiesSourceTriggeredAbility(
new CreateTokenEffect(new SoldierLifelinkToken())
));
}
diff --git a/Mage.Sets/src/mage/cards/h/HuntersEdge.java b/Mage.Sets/src/mage/cards/h/HuntersEdge.java
new file mode 100644
index 00000000000..919602bf5cf
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/h/HuntersEdge.java
@@ -0,0 +1,38 @@
+package mage.cards.h;
+
+import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect;
+import mage.abilities.effects.common.counter.AddCountersTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.counters.CounterType;
+import mage.filter.StaticFilters;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetControlledCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class HuntersEdge extends CardImpl {
+
+ public HuntersEdge(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}");
+
+ // Put a +1/+1 counter on target creature you control. Then that creature deals damage equal to its power to target creature you don't control.
+ this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
+ this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
+ this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("that creature").concatBy("Then"));
+ this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL));
+ }
+
+ private HuntersEdge(final HuntersEdge card) {
+ super(card);
+ }
+
+ @Override
+ public HuntersEdge copy() {
+ return new HuntersEdge(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/h/HurloonShaman.java b/Mage.Sets/src/mage/cards/h/HurloonShaman.java
index c14aee9699a..0347659da20 100644
--- a/Mage.Sets/src/mage/cards/h/HurloonShaman.java
+++ b/Mage.Sets/src/mage/cards/h/HurloonShaman.java
@@ -3,7 +3,7 @@ package mage.cards.h;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.SacrificeAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class HurloonShaman extends CardImpl {
this.toughness = new MageInt(3);
// When Hurloon Shaman dies, each player sacrifices a land.
- this.addAbility(new DiesTriggeredAbility(new SacrificeAllEffect(new FilterControlledLandPermanent("land"))));
+ this.addAbility(new DiesSourceTriggeredAbility(new SacrificeAllEffect(new FilterControlledLandPermanent("land"))));
}
public HurloonShaman(final HurloonShaman card) {
diff --git a/Mage.Sets/src/mage/cards/h/Hydradoodle.java b/Mage.Sets/src/mage/cards/h/Hydradoodle.java
index 75fc85bff8c..9ab48ab269b 100644
--- a/Mage.Sets/src/mage/cards/h/Hydradoodle.java
+++ b/Mage.Sets/src/mage/cards/h/Hydradoodle.java
@@ -32,7 +32,7 @@ public final class Hydradoodle extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{X}{G}{G}");
this.subtype.add(SubType.HYDRA);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
diff --git a/Mage.Sets/src/mage/cards/h/Hypnox.java b/Mage.Sets/src/mage/cards/h/Hypnox.java
index 41e0be205ec..a9fd9855655 100644
--- a/Mage.Sets/src/mage/cards/h/Hypnox.java
+++ b/Mage.Sets/src/mage/cards/h/Hypnox.java
@@ -7,7 +7,7 @@ import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
@@ -43,7 +43,7 @@ public final class Hypnox extends CardImpl {
// When Hypnox enters the battlefield, if you cast it from your hand, exile all cards from target opponent's hand.
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new HypnoxExileEffect());
ability.addTarget(new TargetOpponent());
- this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourceCondition.instance,
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourcePermanentCondition.instance,
"When {this} enters the battlefield, if you cast it from your hand, exile all cards from target opponent's hand."), new CastFromHandWatcher());
// When Hypnox leaves the battlefield, return the exiled cards to their owner's hand.
diff --git a/Mage.Sets/src/mage/cards/h/Hypothesizzle.java b/Mage.Sets/src/mage/cards/h/Hypothesizzle.java
index f866ac8f025..82681c07c58 100644
--- a/Mage.Sets/src/mage/cards/h/Hypothesizzle.java
+++ b/Mage.Sets/src/mage/cards/h/Hypothesizzle.java
@@ -1,26 +1,19 @@
package mage.cards.h;
-import java.util.UUID;
-import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.common.DiscardCardCost;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
-import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
import mage.filter.StaticFilters;
-import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class Hypothesizzle extends CardImpl {
@@ -30,15 +23,19 @@ public final class Hypothesizzle extends CardImpl {
// Draw two cards. Then you may discard a nonland card. When you do, Hypothesizzle deals 4 damage to target creature.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2));
- this.getSpellAbility().addEffect(new DoIfCostPaid(
- new HypothesizzleCreateReflexiveTriggerEffect(),
- new DiscardCardCost(StaticFilters.FILTER_CARD_A_NON_LAND),
- "Discard a nonland card to deal 4 damage?"
- ).setText("Then you may discard a nonland card. "
- + "When you do, {this} deals 4 damage to target creature."));
+
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new DamageTargetEffect(4), false,
+ "{this} deals 4 damage to target creature"
+ );
+ ability.addTarget(new TargetCreaturePermanent());
+ this.getSpellAbility().addEffect(new DoWhenCostPaid(
+ ability, new DiscardCardCost(StaticFilters.FILTER_CARD_A_NON_LAND),
+ "Discard a nonland card?"
+ ).concatBy("Then"));
}
- public Hypothesizzle(final Hypothesizzle card) {
+ private Hypothesizzle(final Hypothesizzle card) {
super(card);
}
@@ -47,60 +44,3 @@ public final class Hypothesizzle extends CardImpl {
return new Hypothesizzle(this);
}
}
-
-class HypothesizzleCreateReflexiveTriggerEffect extends OneShotEffect {
-
- public HypothesizzleCreateReflexiveTriggerEffect() {
- super(Outcome.Benefit);
- this.staticText = "When you do, it deals 4 damage to target creature";
- }
-
- public HypothesizzleCreateReflexiveTriggerEffect(final HypothesizzleCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public HypothesizzleCreateReflexiveTriggerEffect copy() {
- return new HypothesizzleCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new HypothesizzleReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class HypothesizzleReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- public HypothesizzleReflexiveTriggeredAbility() {
- super(new DamageTargetEffect(4), Duration.OneUse, true);
- this.addTarget(new TargetCreaturePermanent());
- }
-
- public HypothesizzleReflexiveTriggeredAbility(final HypothesizzleReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public HypothesizzleReflexiveTriggeredAbility copy() {
- return new HypothesizzleReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When you discard a nonland card, "
- + "{this} deals 4 damage to target creature";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/i/IcebergCancrix.java b/Mage.Sets/src/mage/cards/i/IcebergCancrix.java
index c0a59ad7b72..0f2cb53c504 100644
--- a/Mage.Sets/src/mage/cards/i/IcebergCancrix.java
+++ b/Mage.Sets/src/mage/cards/i/IcebergCancrix.java
@@ -40,7 +40,7 @@ public final class IcebergCancrix extends CardImpl {
Ability ability = new EntersBattlefieldControlledTriggeredAbility(
Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(2), filter,
true, "Whenever another snow permanent enters the battlefield under your control, " +
- "you may have target player put the top two cards of their library into their graveyard."
+ "you may have target player mill two cards."
);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/i/IcefallRegent.java b/Mage.Sets/src/mage/cards/i/IcefallRegent.java
index 71e5d8e2670..582882559a8 100644
--- a/Mage.Sets/src/mage/cards/i/IcefallRegent.java
+++ b/Mage.Sets/src/mage/cards/i/IcefallRegent.java
@@ -2,17 +2,16 @@ package mage.cards.i;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.SpellAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.common.TapTargetEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
+import mage.filter.FilterCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -20,7 +19,6 @@ import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanent;
-import mage.util.CardUtil;
import mage.watchers.Watcher;
import java.util.UUID;
@@ -53,8 +51,9 @@ public final class IcefallRegent extends CardImpl {
this.addAbility(ability, new IcefallRegentWatcher());
// Spells your opponents cast that target Icefall Regent cost {2} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new IcefallRegentCostIncreaseEffect()));
-
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(2, new FilterCard("Spells"), TargetController.OPPONENT))
+ );
}
public IcefallRegent(final IcefallRegent card) {
@@ -157,48 +156,3 @@ class IcefallRegentWatcher extends Watcher {
//don't reset condition each turn - only when this leaves the battlefield
}
}
-
-class IcefallRegentCostIncreaseEffect extends CostModificationEffectImpl {
-
-
- IcefallRegentCostIncreaseEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Spells your opponents cast that target {this} cost {2} more to cast";
- }
-
- private IcefallRegentCostIncreaseEffect(IcefallRegentCostIncreaseEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
- Mode mode = abilityToModify.getModes().get(modeId);
- for (Target target : mode.getTargets()) {
- for (UUID targetUUID : target.getTargets()) {
- if (targetUUID.equals(source.getSourceId())) {
- return true;
- }
- }
- }
- }
- }
- }
- return false;
- }
-
- @Override
- public IcefallRegentCostIncreaseEffect copy() {
- return new IcefallRegentCostIncreaseEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/i/IchorclawMyr.java b/Mage.Sets/src/mage/cards/i/IchorclawMyr.java
index 51e0308bf3b..388a5e989ea 100644
--- a/Mage.Sets/src/mage/cards/i/IchorclawMyr.java
+++ b/Mage.Sets/src/mage/cards/i/IchorclawMyr.java
@@ -3,7 +3,7 @@ package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.InfectAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class IchorclawMyr extends CardImpl {
this.addAbility(InfectAbility.getInstance());
// Whenever Ichorclaw Myr becomes blocked, it gets +2/+2 until end of turn.
- this.addAbility(new BecomesBlockedTriggeredAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn), false));
}
public IchorclawMyr(final IchorclawMyr card) {
diff --git a/Mage.Sets/src/mage/cards/i/IconOfAncestry.java b/Mage.Sets/src/mage/cards/i/IconOfAncestry.java
index a04801cda9d..a65420d527b 100644
--- a/Mage.Sets/src/mage/cards/i/IconOfAncestry.java
+++ b/Mage.Sets/src/mage/cards/i/IconOfAncestry.java
@@ -1,12 +1,15 @@
package mage.cards.i;
-import java.util.Set;
+import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
+import mage.abilities.effects.common.LookLibraryAndPickControllerEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -14,16 +17,7 @@ import mage.constants.*;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ChosenSubtypePredicate;
-
-import java.util.UUID;
-import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
import mage.game.Game;
-import mage.players.Player;
-import mage.target.TargetCard;
/**
* @author TheElk801
@@ -49,9 +43,10 @@ public final class IconOfAncestry extends CardImpl {
new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filter, false)
));
- // {3}, {T}: Look at the top three cards of your library. You may reveal a creature card of the
+ // {3}, {T}: Look at the top three cards of your library. You may reveal a creature card of the
// chosen type from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
- Ability ability = new SimpleActivatedAbility(new IconOfAncestryEffect(), new ManaCostsImpl("{3}"));
+ FilterCreatureCard filter2 = new FilterCreatureCard("creature card that matches the chosen subtype");
+ Ability ability = new SimpleActivatedAbility(new IconOfAncestryEffect(filter2), new GenericManaCost(3));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
@@ -66,14 +61,25 @@ public final class IconOfAncestry extends CardImpl {
}
}
-class IconOfAncestryEffect extends OneShotEffect {
+class IconOfAncestryEffect extends LookLibraryAndPickControllerEffect {
- public IconOfAncestryEffect() {
- super(Outcome.AIDontUseIt);
- this.staticText = "Look at the top three cards of your library. "
- + "You may reveal a creature card of the "
- + "chosen type from among them and put it into your hand. "
- + "Put the rest on the bottom of your library in a random order";
+ public IconOfAncestryEffect(FilterCreatureCard filter) {
+ super(StaticValue.get(3), false, StaticValue.get(1), filter, Zone.LIBRARY, false,
+ true, false, Zone.HAND, true, false, false);
+ this.setOutcome(Outcome.AIDontUseIt);
+ this.setBackInRandomOrder(true);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ SubType subtype = (SubType) game.getState().getValue(source.getSourceId() + "_type");
+ if (subtype != null) {
+ filter.add(subtype.getPredicate());
+ filter.setMessage("creature card of subtype " + subtype.toString());
+ } else {
+ return false;
+ }
+ return super.apply(game, source);
}
public IconOfAncestryEffect(final IconOfAncestryEffect effect) {
@@ -84,39 +90,4 @@ class IconOfAncestryEffect extends OneShotEffect {
public IconOfAncestryEffect copy() {
return new IconOfAncestryEffect(this);
}
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller == null
- || !controller.getLibrary().hasCards()) {
- return false;
- }
- Set cardsFromTopOfLibrary = controller.getLibrary().getTopCards(game, 3);
- Cards cardsFromLibrary = new CardsImpl();
- Cards revealedCard = new CardsImpl();
- cardsFromLibrary.addAll(cardsFromTopOfLibrary);
- if (cardsFromTopOfLibrary.isEmpty()) {
- return false;
- }
- FilterCreatureCard filter = new FilterCreatureCard("creature card that matches the chosen subtype");
- SubType subtype = (SubType) game.getState().getValue(source.getSourceId() + "_type");
- if (subtype != null) {
- filter.add(subtype.getPredicate());
- }
- TargetCard target = new TargetCard(Zone.LIBRARY, filter);
- if (target.canChoose(controller.getId(), game)
- && controller.chooseUse(outcome, "Do you wish to use Icon of Ancestry's effect?", source, game)
- && controller.choose(Outcome.Benefit, cardsFromLibrary, target, game)) {
- Card chosenCard = game.getCard(target.getFirstTarget());
- if (chosenCard != null) {
- revealedCard.add(chosenCard);
- controller.revealCards(source, revealedCard, game);
- controller.putInHand(chosenCard, game);
- cardsFromLibrary.remove(chosenCard);
- }
- }
- controller.putCardsOnBottomOfLibrary(cardsFromLibrary, game, source, true);
- return true;
- }
}
diff --git a/Mage.Sets/src/mage/cards/i/IdolOfEndurance.java b/Mage.Sets/src/mage/cards/i/IdolOfEndurance.java
new file mode 100644
index 00000000000..7c6b09e686d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/i/IdolOfEndurance.java
@@ -0,0 +1,280 @@
+package mage.cards.i;
+
+import mage.MageObjectReference;
+import mage.abilities.Ability;
+import mage.abilities.DelayedTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.AsThoughEffectImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.*;
+import mage.constants.*;
+import mage.filter.FilterCard;
+import mage.filter.common.FilterCreatureCard;
+import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.ZoneChangeEvent;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.watchers.Watcher;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author TheElk801
+ */
+public final class IdolOfEndurance extends CardImpl {
+
+ public IdolOfEndurance(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{W}");
+
+ // When Idol of Endurance enters the battlefield, exile all creature cards with converted mana cost 3 or less from your graveyard until Idol of Endurance leaves the battlefield.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new IdolOfEnduranceExileEffect()));
+
+ // {1}{W}, {T}: Until end of turn, you may cast a creature spell from among the cards exiled with Idol of Endurance without paying its mana cost.
+ Ability ability = new SimpleActivatedAbility(
+ new IdolOfEnduranceCastFromExileEffect(), new ManaCostsImpl<>("{1}{W}")
+ );
+ ability.addCost(new TapSourceCost());
+ this.addAbility(ability, new IdolOfEnduranceWatcher());
+ }
+
+ private IdolOfEndurance(final IdolOfEndurance card) {
+ super(card);
+ }
+
+ @Override
+ public IdolOfEndurance copy() {
+ return new IdolOfEndurance(this);
+ }
+}
+
+class IdolOfEnduranceExileEffect extends OneShotEffect {
+
+ private static final FilterCard filter = new FilterCreatureCard();
+
+ static {
+ filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4));
+ }
+
+ IdolOfEnduranceExileEffect() {
+ super(Outcome.Benefit);
+ staticText = "exile all creature cards with converted mana cost 3 or less from your graveyard until {this} leaves the battlefield";
+ }
+
+ private IdolOfEnduranceExileEffect(final IdolOfEnduranceExileEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public IdolOfEnduranceExileEffect copy() {
+ return new IdolOfEnduranceExileEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ Permanent permanent = source.getSourcePermanentIfItStillExists(game);
+ if (player == null || permanent == null) {
+ return false;
+ }
+ Cards cards = new CardsImpl(player.getGraveyard().getCards(filter, game));
+ MageObjectReference mor = new MageObjectReference(permanent, game);
+ player.moveCards(cards, Zone.EXILED, source, game);
+ Set morSet = cards
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .map(card -> new MageObjectReference(card, game))
+ .collect(Collectors.toSet());
+ String exileId = "idolOfEndurance_" + mor.getSourceId() + mor.getZoneChangeCounter();
+ if (game.getState().getValue(exileId) == null) {
+ game.getState().setValue(exileId, new HashSet());
+ }
+ ((Set) game.getState().getValue(exileId)).addAll(morSet);
+ game.addDelayedTriggeredAbility(new IdolOfEnduranceDelayedTrigger(exileId), source);
+ return true;
+ }
+}
+
+class IdolOfEnduranceDelayedTrigger extends DelayedTriggeredAbility {
+
+ IdolOfEnduranceDelayedTrigger(String exileId) {
+ super(new IdolOfEnduranceLeaveEffect(exileId), Duration.Custom, true, false);
+ this.usesStack = false;
+ this.setRuleVisible(false);
+ }
+
+ private IdolOfEnduranceDelayedTrigger(final IdolOfEnduranceDelayedTrigger ability) {
+ super(ability);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ZONE_CHANGE;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (event.getTargetId().equals(this.getSourceId())) {
+ ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
+ if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public IdolOfEnduranceDelayedTrigger copy() {
+ return new IdolOfEnduranceDelayedTrigger(this);
+ }
+}
+
+class IdolOfEnduranceLeaveEffect extends OneShotEffect {
+
+ private final String exileId;
+
+ IdolOfEnduranceLeaveEffect(String exileId) {
+ super(Outcome.Benefit);
+ this.exileId = exileId;
+ }
+
+ private IdolOfEnduranceLeaveEffect(final IdolOfEnduranceLeaveEffect effect) {
+ super(effect);
+ this.exileId = effect.exileId;
+ }
+
+ @Override
+ public IdolOfEnduranceLeaveEffect copy() {
+ return new IdolOfEnduranceLeaveEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null) {
+ return false;
+ }
+ Object object = game.getState().getValue(exileId);
+ if (!(object instanceof Set)) {
+ return false;
+ }
+ Set morSet = (Set) object;
+ return player != null && player.moveCards(
+ morSet.stream()
+ .map(mor -> mor.getCard(game))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet()),
+ Zone.GRAVEYARD, source, game
+ );
+ }
+}
+
+class IdolOfEnduranceCastFromExileEffect extends AsThoughEffectImpl {
+
+ IdolOfEnduranceCastFromExileEffect() {
+ super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
+ staticText = "until end of turn, you may cast a creature spell from among the cards exiled with {this} without paying its mana cost";
+ }
+
+ private IdolOfEnduranceCastFromExileEffect(final IdolOfEnduranceCastFromExileEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public IdolOfEnduranceCastFromExileEffect copy() {
+ return new IdolOfEnduranceCastFromExileEffect(this);
+ }
+
+ @Override
+ public void init(Ability source, Game game) {
+ super.init(source, game);
+ IdolOfEnduranceWatcher watcher = game.getState().getWatcher(IdolOfEnduranceWatcher.class);
+ if (watcher != null) {
+ watcher.addPlayable(source, game);
+ }
+ }
+
+ @Override
+ public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
+ IdolOfEnduranceWatcher watcher = game.getState().getWatcher(IdolOfEnduranceWatcher.class);
+ if (watcher == null || !watcher.checkPermission(affectedControllerId, source, game)) {
+ return false;
+ }
+ Object value = game.getState().getValue(
+ "idolOfEndurance_" + source.getSourceId() + source.getSourceObjectZoneChangeCounter()
+ );
+ if (!(value instanceof Set)) {
+ discard();
+ return false;
+ }
+ Set morSet = (Set) value;
+ if (game.getState().getZone(sourceId) != Zone.EXILED
+ || morSet.stream().noneMatch(mor -> mor.refersTo(sourceId, game))) {
+ return false;
+ }
+ Card card = game.getCard(sourceId);
+ if (card == null || !card.isCreature() || card.isLand()) {
+ return false;
+ }
+ return allowCardToPlayWithoutMana(sourceId, source, affectedControllerId, game);
+ }
+}
+
+class IdolOfEnduranceWatcher extends Watcher {
+
+ private final Map> morMap = new HashMap<>();
+
+ IdolOfEnduranceWatcher() {
+ super(WatcherScope.GAME);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() == GameEvent.EventType.SPELL_CAST) {
+ if (event.getAdditionalReference() == null) {
+ return;
+ }
+ morMap.computeIfAbsent(event.getAdditionalReference(), m -> new HashMap<>())
+ .compute(event.getPlayerId(), (u, i) -> i == null ? 0 : Integer.sum(i, -1));
+ return;
+ }
+ }
+
+ @Override
+ public void reset() {
+ morMap.clear();
+ super.reset();
+ }
+
+ boolean checkPermission(UUID playerId, Ability source, Game game) {
+ if (!playerId.equals(source.getControllerId())) {
+ return false;
+ }
+ MageObjectReference mor = new MageObjectReference(
+ source.getSourceId(), source.getSourceObjectZoneChangeCounter(), game
+ );
+ if (!morMap.containsKey(mor)) {
+ return false;
+ }
+ return morMap.get(mor).getOrDefault(playerId, 0) > 0;
+ }
+
+ void addPlayable(Ability source, Game game) {
+ MageObjectReference mor = new MageObjectReference(
+ source.getSourceId(), source.getSourceObjectZoneChangeCounter(), game
+ );
+ morMap.computeIfAbsent(mor, m -> new HashMap<>())
+ .compute(source.getControllerId(), (u, i) -> i == null ? 1 : Integer.sum(i, 1));
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/i/IgneousCur.java b/Mage.Sets/src/mage/cards/i/IgneousCur.java
new file mode 100644
index 00000000000..941413c9c41
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/i/IgneousCur.java
@@ -0,0 +1,42 @@
+package mage.cards.i;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class IgneousCur extends CardImpl {
+
+ public IgneousCur(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
+
+ this.subtype.add(SubType.ELEMENTAL);
+ this.subtype.add(SubType.DOG);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(2);
+
+ // {1}{R}: Igneous Cur gets +2/+0 until end of turn.
+ this.addAbility(new SimpleActivatedAbility(
+ new BoostSourceEffect(2, 0, Duration.EndOfTurn), new ManaCostsImpl("{1}{R}")
+ ));
+ }
+
+ private IgneousCur(final IgneousCur card) {
+ super(card);
+ }
+
+ @Override
+ public IgneousCur copy() {
+ return new IgneousCur(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/i/IgneousElemental.java b/Mage.Sets/src/mage/cards/i/IgneousElemental.java
index aba782659fa..5d750cea5b8 100644
--- a/Mage.Sets/src/mage/cards/i/IgneousElemental.java
+++ b/Mage.Sets/src/mage/cards/i/IgneousElemental.java
@@ -4,9 +4,11 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
import mage.abilities.condition.common.CardsInControllerGraveCondition;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -30,10 +32,11 @@ public final class IgneousElemental extends CardImpl {
this.toughness = new MageInt(3);
// This spell costs {2} less to cast if there is a land card in your graveyard.
- Ability ability = new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(
- 2, new CardsInControllerGraveCondition(1, StaticFilters.FILTER_CARD_LAND)
- ).setText("This spell costs {2} less to cast if there is a land card in your graveyard."));
+ Condition condition = new CardsInControllerGraveCondition(1, StaticFilters.FILTER_CARD_LAND);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(2, condition)
+ .setText("This spell costs {2} less to cast if there is a land card in your graveyard."));
ability.setRuleAtTheTop(true);
+ ability.addHint(new ConditionHint(condition, "There is a land card in your graveyard"));
this.addAbility(ability);
// When Igneous Elemental enters the battlefield, you may have it deal 2 damage to target creature.
diff --git a/Mage.Sets/src/mage/cards/i/IgniteTheFuture.java b/Mage.Sets/src/mage/cards/i/IgniteTheFuture.java
index 14cd2b90b27..926b3ca7068 100644
--- a/Mage.Sets/src/mage/cards/i/IgniteTheFuture.java
+++ b/Mage.Sets/src/mage/cards/i/IgniteTheFuture.java
@@ -2,7 +2,6 @@ package mage.cards.i;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlashbackAbility;
@@ -13,10 +12,11 @@ import mage.constants.*;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
-import mage.target.targetpointer.FixedTarget;
import java.util.Set;
import java.util.UUID;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
+import mage.target.targetpointer.FixedTargets;
/**
* @author TheElk801
@@ -69,81 +69,8 @@ class IgniteTheFutureEffect extends OneShotEffect {
if (controller == null || spell == null) {
return false;
}
- boolean forFree = spell.getFromZone() == Zone.GRAVEYARD;
Set cards = controller.getLibrary().getTopCards(game, 3);
- controller.moveCards(cards, Zone.EXILED, source, game);
-
- cards.stream().forEach(card -> {
- ContinuousEffect effect = new IgniteTheFutureMayPlayEffect(forFree);
- effect.setTargetPointer(new FixedTarget(card.getId(), game));
- game.addEffect(effect, source);
- });
-
- return true;
- }
-}
-
-class IgniteTheFutureMayPlayEffect extends AsThoughEffectImpl {
-
- private int castOnTurn = 0;
- private final boolean forFree;
-
- IgniteTheFutureMayPlayEffect(boolean forFree) {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
- this.forFree = forFree;
- if (forFree) {
- this.staticText = "Until the end of your next turn, you may play that card without playing its mana cost.";
- } else {
- this.staticText = "Until the end of your next turn, you may play that card.";
- }
- }
-
- private IgniteTheFutureMayPlayEffect(final IgniteTheFutureMayPlayEffect effect) {
- super(effect);
- castOnTurn = effect.castOnTurn;
- this.forFree = effect.forFree;
- }
-
- @Override
- public IgniteTheFutureMayPlayEffect copy() {
- return new IgniteTheFutureMayPlayEffect(this);
- }
-
- @Override
- public void init(Ability source, Game game) {
- super.init(source, game);
- castOnTurn = game.getTurnNum();
- }
-
- @Override
- public boolean isInactive(Ability source, Game game) {
- return castOnTurn != game.getTurnNum()
- && game.getPhase().getStep().getType() == PhaseStep.END_TURN
- && game.isActivePlayer(source.getControllerId());
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- if (!source.isControlledBy(affectedControllerId)
- || !getTargetPointer().getTargets(game, source).contains(objectId)) {
- return false;
- }
- if (!forFree) {
- return true;
- }
- Card card = game.getCard(objectId);
- if (card == null || card.isLand() || card.getSpellAbility().getCosts() == null) {
- return true;
- }
- Player player = game.getPlayer(affectedControllerId);
- if (player != null) {
- player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
- }
- return true;
+ return PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(game, source, cards,
+ TargetController.YOU, Duration.UntilEndOfYourNextTurn, Zone.GRAVEYARD.equals(spell.getFromZone()));
}
}
diff --git a/Mage.Sets/src/mage/cards/i/IgnobleSoldier.java b/Mage.Sets/src/mage/cards/i/IgnobleSoldier.java
index 26e90533fbf..859bc1abaf4 100644
--- a/Mage.Sets/src/mage/cards/i/IgnobleSoldier.java
+++ b/Mage.Sets/src/mage/cards/i/IgnobleSoldier.java
@@ -3,7 +3,7 @@ package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PreventCombatDamageBySourceEffect;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class IgnobleSoldier extends CardImpl {
// Whenever Ignoble Soldier becomes blocked, prevent all combat damage that would be dealt by it this turn.
Effect effect = new PreventCombatDamageBySourceEffect(Duration.EndOfTurn);
effect.setText("prevent all combat damage that would be dealt by it this turn");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public IgnobleSoldier(final IgnobleSoldier card) {
diff --git a/Mage.Sets/src/mage/cards/i/IlhargTheRazeBoar.java b/Mage.Sets/src/mage/cards/i/IlhargTheRazeBoar.java
index b17883fd8ac..25a75accab5 100644
--- a/Mage.Sets/src/mage/cards/i/IlhargTheRazeBoar.java
+++ b/Mage.Sets/src/mage/cards/i/IlhargTheRazeBoar.java
@@ -95,7 +95,7 @@ class IlhargTheRazeBoarEffect extends OneShotEffect {
}
game.getCombat().addAttackingCreature(permanent.getId(), game);
Effect effect = new ReturnToHandTargetEffect();
- effect.setText("return {this} to its owner's hand");
+ effect.setText("return " + permanent.getName() + " to its owner's hand");
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source);
return true;
diff --git a/Mage.Sets/src/mage/cards/i/IllusionistsBracers.java b/Mage.Sets/src/mage/cards/i/IllusionistsBracers.java
index 257ca55ff20..6b98993ed81 100644
--- a/Mage.Sets/src/mage/cards/i/IllusionistsBracers.java
+++ b/Mage.Sets/src/mage/cards/i/IllusionistsBracers.java
@@ -1,7 +1,5 @@
-
package mage.cards.i;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.mana.GenericManaCost;
@@ -12,8 +10,8 @@ import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -22,18 +20,19 @@ import mage.game.permanent.Permanent;
import mage.game.stack.StackAbility;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class IllusionistsBracers extends CardImpl {
public IllusionistsBracers(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
this.subtype.add(SubType.EQUIPMENT);
// Whenever an ability of equipped creature is activated, if it isn't a mana ability, copy that ability. You may choose new targets for the copy.
- this.addAbility(new AbilityActivatedTriggeredAbility());
+ this.addAbility(new IllusionistsBracersTriggeredAbility());
// Equip 3
this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(3)));
@@ -49,19 +48,19 @@ public final class IllusionistsBracers extends CardImpl {
}
}
-class AbilityActivatedTriggeredAbility extends TriggeredAbilityImpl {
+class IllusionistsBracersTriggeredAbility extends TriggeredAbilityImpl {
- AbilityActivatedTriggeredAbility() {
+ IllusionistsBracersTriggeredAbility() {
super(Zone.BATTLEFIELD, new CopyActivatedAbilityEffect());
}
- AbilityActivatedTriggeredAbility(final AbilityActivatedTriggeredAbility ability) {
+ IllusionistsBracersTriggeredAbility(final IllusionistsBracersTriggeredAbility ability) {
super(ability);
}
@Override
- public AbilityActivatedTriggeredAbility copy() {
- return new AbilityActivatedTriggeredAbility(this);
+ public IllusionistsBracersTriggeredAbility copy() {
+ return new IllusionistsBracersTriggeredAbility(this);
}
@Override
@@ -72,7 +71,7 @@ class AbilityActivatedTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent equipment = game.getPermanent(this.getSourceId());
- if (equipment != null && equipment.isAttachedTo(event.getSourceId())) {
+ if (equipment != null && equipment.isAttachedTo(event.getSourceId())) {
StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
if (!(stackAbility.getStackAbility() instanceof ActivatedManaAbilityImpl)) {
Effect effect = this.getEffects().get(0);
diff --git a/Mage.Sets/src/mage/cards/i/ImmolatingGyre.java b/Mage.Sets/src/mage/cards/i/ImmolatingGyre.java
new file mode 100644
index 00000000000..eaccc74c364
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/i/ImmolatingGyre.java
@@ -0,0 +1,46 @@
+package mage.cards.i;
+
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
+import mage.abilities.effects.common.DamageAllEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.TargetController;
+import mage.filter.FilterPermanent;
+import mage.filter.StaticFilters;
+import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ImmolatingGyre extends CardImpl {
+
+ private static final DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY);
+ private static final FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent();
+
+ static {
+ filter.add(TargetController.NOT_YOU.getControllerPredicate());
+ }
+
+ public ImmolatingGyre(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}");
+
+ // Immolating Gyre deals X damage to each creature and planeswalker you don't control, where X is the number of instant and sorcery cards in your graveyard.
+ this.getSpellAbility().addEffect(new DamageAllEffect(xValue, filter).setText(
+ "{this} deals X damage to each creature and planeswalker you don't control, " +
+ "where X is the number of instant and sorcery cards in your graveyard"
+ ));
+ }
+
+ private ImmolatingGyre(final ImmolatingGyre card) {
+ super(card);
+ }
+
+ @Override
+ public ImmolatingGyre copy() {
+ return new ImmolatingGyre(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/i/ImmolatingSouleater.java b/Mage.Sets/src/mage/cards/i/ImmolatingSouleater.java
index bbeb3026099..02445eb06b2 100644
--- a/Mage.Sets/src/mage/cards/i/ImmolatingSouleater.java
+++ b/Mage.Sets/src/mage/cards/i/ImmolatingSouleater.java
@@ -22,7 +22,7 @@ public final class ImmolatingSouleater extends CardImpl {
public ImmolatingSouleater(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/i/ImmortalPhoenix.java b/Mage.Sets/src/mage/cards/i/ImmortalPhoenix.java
index e43b33376c6..076ea534f27 100644
--- a/Mage.Sets/src/mage/cards/i/ImmortalPhoenix.java
+++ b/Mage.Sets/src/mage/cards/i/ImmortalPhoenix.java
@@ -1,7 +1,7 @@
package mage.cards.i;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -26,7 +26,7 @@ public final class ImmortalPhoenix extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Immortal Phoenix dies, return it to its owner’s hand.
- this.addAbility(new DiesTriggeredAbility(new ReturnToHandSourceEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new ReturnToHandSourceEffect()));
}
public ImmortalPhoenix(final ImmortalPhoenix card) {
diff --git a/Mage.Sets/src/mage/cards/i/InameAsOne.java b/Mage.Sets/src/mage/cards/i/InameAsOne.java
index ba36e99e3c9..9d81ec065f4 100644
--- a/Mage.Sets/src/mage/cards/i/InameAsOne.java
+++ b/Mage.Sets/src/mage/cards/i/InameAsOne.java
@@ -5,9 +5,9 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@@ -51,12 +51,12 @@ public final class InameAsOne extends CardImpl {
// When Iname as One enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, filter)), true),
- CastFromHandSourceCondition.instance,
+ CastFromHandSourcePermanentCondition.instance,
"When {this} enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library."),
new CastFromHandWatcher());
// When Iname as One dies, you may exile it. If you do, return target Spirit permanent card from your graveyard to the battlefield.
- Ability ability = new DiesTriggeredAbility(new InameAsOneEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new InameAsOneEffect(), false);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/i/InameLifeAspect.java b/Mage.Sets/src/mage/cards/i/InameLifeAspect.java
index 91489ac7b02..4ba6cc586d7 100644
--- a/Mage.Sets/src/mage/cards/i/InameLifeAspect.java
+++ b/Mage.Sets/src/mage/cards/i/InameLifeAspect.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect;
@@ -42,7 +42,7 @@ public final class InameLifeAspect extends CardImpl {
this.toughness = new MageInt(4);
// When Iname, Life Aspect dies, you may exile it. If you do, return any number of target Spirit cards from your graveyard to your hand.
- Ability ability = new DiesTriggeredAbility(new InameLifeAspectEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new InameLifeAspectEffect(), false);
ability.addTarget(new TargetCardInYourGraveyard(0, Integer.MAX_VALUE, filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java b/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java
index 909f4ec7c0c..3e9ca55f5fb 100644
--- a/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java
+++ b/Mage.Sets/src/mage/cards/i/IncreasingConfusion.java
@@ -46,7 +46,7 @@ class IncreasingConfusionEffect extends OneShotEffect {
public IncreasingConfusionEffect() {
super(Outcome.Detriment);
- staticText = "Target player puts the top X cards of their library into their graveyard. If this spell was cast from a graveyard, that player puts twice that many cards into their graveyard instead";
+ staticText = "Target player mills X cards. If this spell was cast from a graveyard, that player mills twice that many cards";
}
public IncreasingConfusionEffect(final IncreasingConfusionEffect effect) {
@@ -63,7 +63,7 @@ class IncreasingConfusionEffect extends OneShotEffect {
if (spell.getFromZone() == Zone.GRAVEYARD) {
amount *= 2;
}
- player.moveCards(player.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ player.millCards(amount, source, game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/i/InduceParanoia.java b/Mage.Sets/src/mage/cards/i/InduceParanoia.java
index d8862fa168b..eb699cc84e0 100644
--- a/Mage.Sets/src/mage/cards/i/InduceParanoia.java
+++ b/Mage.Sets/src/mage/cards/i/InduceParanoia.java
@@ -51,7 +51,7 @@ class InduceParanoiaEffect extends OneShotEffect {
InduceParanoiaEffect() {
super(Outcome.Detriment);
- this.staticText = "Counter target spell. If {B} was spent to cast this spell, that spell's controller puts the top X cards of their library into their graveyard, where X is the spell's converted mana cost.";
+ this.staticText = "Counter target spell. If {B} was spent to cast this spell, that spell's controller mills X cards, where X is the spell's converted mana cost.";
}
InduceParanoiaEffect(final InduceParanoiaEffect effect) {
@@ -71,7 +71,7 @@ class InduceParanoiaEffect extends OneShotEffect {
int spellCMC = spell.getConvertedManaCost();
Player player = game.getPlayer(spell.getControllerId());
if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, spellCMC), Zone.GRAVEYARD, source, game);
+ player.millCards(spellCMC, source, game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/i/InducedAmnesia.java b/Mage.Sets/src/mage/cards/i/InducedAmnesia.java
index dbdac63fb78..9f2e5d158b0 100644
--- a/Mage.Sets/src/mage/cards/i/InducedAmnesia.java
+++ b/Mage.Sets/src/mage/cards/i/InducedAmnesia.java
@@ -76,7 +76,7 @@ class InducedAmnesiaExileEffect extends OneShotEffect {
card.setFaceDown(true, game);
}
game.informPlayers(sourcePermanent.getLogName() + ": " + targetPlayer.getLogName() + " exiles their hand face down (" + numberOfCards + "card" + (numberOfCards > 1 ? "s" : "") + ')');
- game.applyEffects();
+ game.getState().processAction(game);
targetPlayer.drawCards(numberOfCards, source.getSourceId(), game);
}
return true;
diff --git a/Mage.Sets/src/mage/cards/i/IndulgingPatrician.java b/Mage.Sets/src/mage/cards/i/IndulgingPatrician.java
new file mode 100644
index 00000000000..4ddb3b7ad8a
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/i/IndulgingPatrician.java
@@ -0,0 +1,62 @@
+package mage.cards.i;
+
+import mage.MageInt;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.YouGainedLifeCondition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.LoseLifeOpponentsEffect;
+import mage.abilities.hint.ConditionHint;
+import mage.abilities.hint.Hint;
+import mage.abilities.keyword.FlyingAbility;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.ComparisonType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.watchers.common.PlayerGainedLifeWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class IndulgingPatrician extends CardImpl {
+
+ private static final Condition condition = new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2);
+ private static final Hint hint = new ConditionHint(condition, "You gained 3 or more life this turn");
+
+ public IndulgingPatrician(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{B}");
+
+ this.subtype.add(SubType.VAMPIRE);
+ this.subtype.add(SubType.NOBLE);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(4);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Lifelink
+ this.addAbility(LifelinkAbility.getInstance());
+
+ // At the beginning of your end step, if you gained 3 or more life this turn, each opponent loses 3 life.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfEndStepTriggeredAbility(
+ new LoseLifeOpponentsEffect(3), TargetController.YOU, false
+ ), condition, "At the beginning of your end step, " +
+ "if you gained 3 or more life this turn, each opponent loses 3 life."
+ ).addHint(hint), new PlayerGainedLifeWatcher());
+ }
+
+ private IndulgingPatrician(final IndulgingPatrician card) {
+ super(card);
+ }
+
+ @Override
+ public IndulgingPatrician copy() {
+ return new IndulgingPatrician(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/i/InescapableBlaze.java b/Mage.Sets/src/mage/cards/i/InescapableBlaze.java
index 2aa756c1baf..ba670d533c7 100644
--- a/Mage.Sets/src/mage/cards/i/InescapableBlaze.java
+++ b/Mage.Sets/src/mage/cards/i/InescapableBlaze.java
@@ -1,7 +1,7 @@
package mage.cards.i;
import java.util.UUID;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -18,7 +18,7 @@ public final class InescapableBlaze extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}{R}");
// This spell can't be countered.
- this.addAbility(new CantBeCounteredAbility().setRuleAtTheTop(true));
+ this.addAbility(new CantBeCounteredSourceAbility().setRuleAtTheTop(true));
// Inescapable Flame deals 6 damage to any target.
this.getSpellAbility().addEffect(new DamageTargetEffect(6));
diff --git a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java
index 555dc866bd6..ab6ebe36e52 100644
--- a/Mage.Sets/src/mage/cards/i/InfectiousCurse.java
+++ b/Mage.Sets/src/mage/cards/i/InfectiousCurse.java
@@ -106,7 +106,7 @@ class InfectiousCurseCostReductionEffect extends CostModificationEffectImpl {
public InfectiousCurseCostReductionEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
- this.staticText = "Spells you cast that target enchanted player cost {1} less to cast.";
+ this.staticText = "Spells you cast that target enchanted player cost {1} less to cast";
}
protected InfectiousCurseCostReductionEffect(InfectiousCurseCostReductionEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/i/InfectiousHost.java b/Mage.Sets/src/mage/cards/i/InfectiousHost.java
index 8e352d12875..b8740b2a612 100644
--- a/Mage.Sets/src/mage/cards/i/InfectiousHost.java
+++ b/Mage.Sets/src/mage/cards/i/InfectiousHost.java
@@ -4,7 +4,7 @@ package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class InfectiousHost extends CardImpl {
this.toughness = new MageInt(1);
// When Infectious Host dies, target player loses 2 life.
- Ability ability = new DiesTriggeredAbility(new LoseLifeTargetEffect(2), false);
+ Ability ability = new DiesSourceTriggeredAbility(new LoseLifeTargetEffect(2), false);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/i/InfernalDenizen.java b/Mage.Sets/src/mage/cards/i/InfernalDenizen.java
index 7b162869c35..d5005c10b5c 100644
--- a/Mage.Sets/src/mage/cards/i/InfernalDenizen.java
+++ b/Mage.Sets/src/mage/cards/i/InfernalDenizen.java
@@ -7,6 +7,7 @@ import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.common.SourceOnBattlefieldCondition;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.dynamicvalue.DynamicValue;
@@ -52,7 +53,7 @@ public final class InfernalDenizen extends CardImpl {
// {tap}: Gain control of target creature for as long as Infernal Denizen remains on the battlefield.
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(
new GainControlTargetEffect(Duration.Custom, true),
- SourceOnBattlefieldCondition.instance,
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD),
"gain control of target creature for as long as {this} remains on the battlefield");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
diff --git a/Mage.Sets/src/mage/cards/i/InfernalGenesis.java b/Mage.Sets/src/mage/cards/i/InfernalGenesis.java
index daa9e51bfd3..2fac7913476 100644
--- a/Mage.Sets/src/mage/cards/i/InfernalGenesis.java
+++ b/Mage.Sets/src/mage/cards/i/InfernalGenesis.java
@@ -1,20 +1,23 @@
-
package mage.cards.i;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.game.Game;
import mage.game.permanent.token.MinionToken2;
+import mage.game.permanent.token.Token;
import mage.players.Player;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
*/
public final class InfernalGenesis extends CardImpl {
@@ -39,28 +42,30 @@ public final class InfernalGenesis extends CardImpl {
class InfernalGenesisEffect extends OneShotEffect {
+ private static final Token token = new MinionToken2();
+
InfernalGenesisEffect() {
super(Outcome.PutCreatureInPlay);
- staticText = "that player puts the top card of their library into their graveyard. " +
- "Then they create X 1/1 black Minion creature tokens, where X is that card's converted mana cost";
+ staticText = "that player mills a card. Then they create X 1/1 black Minion creature tokens, " +
+ "where X is the milled card's converted mana cost.";
}
- InfernalGenesisEffect(final InfernalGenesisEffect effect) {
+ private InfernalGenesisEffect(final InfernalGenesisEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
- if (player != null) {
- Card card = player.getLibrary().getFromTop(game);
- if (card != null) {
- if (player.moveCards(card, Zone.GRAVEYARD, source, game)) {
- int cmc = card.getConvertedManaCost();
- MinionToken2 token = new MinionToken2();
- token.putOntoBattlefield(cmc, game, source.getSourceId(), player.getId());
- }
- }
+ int totalCMC = player
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .mapToInt(MageObject::getConvertedManaCost)
+ .sum();
+ if (totalCMC > 0) {
+ token.putOntoBattlefield(totalCMC, game, source.getSourceId(), player.getId());
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/i/InfernalKirin.java b/Mage.Sets/src/mage/cards/i/InfernalKirin.java
index 38cdc8b4a79..eedc3483ba4 100644
--- a/Mage.Sets/src/mage/cards/i/InfernalKirin.java
+++ b/Mage.Sets/src/mage/cards/i/InfernalKirin.java
@@ -1,20 +1,14 @@
-
package mage.cards.i;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Outcome;
-import mage.constants.SuperType;
-import mage.constants.Zone;
+import mage.cards.Cards;
+import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.stack.Spell;
@@ -22,8 +16,9 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPlayer;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class InfernalKirin extends CardImpl {
@@ -39,14 +34,14 @@ public final class InfernalKirin extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
+
// Whenever you cast a Spirit or Arcane spell, target player reveals their hand and discards all cards with that spell's converted mana cost.
Ability ability = new SpellCastControllerTriggeredAbility(Zone.BATTLEFIELD, new InfernalKirinEffect(), StaticFilters.SPIRIT_OR_ARCANE_CARD, false, true);
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
-
}
- public InfernalKirin(final InfernalKirin card) {
+ private InfernalKirin(final InfernalKirin card) {
super(card);
}
@@ -58,12 +53,12 @@ public final class InfernalKirin extends CardImpl {
class InfernalKirinEffect extends OneShotEffect {
- public InfernalKirinEffect() {
+ InfernalKirinEffect() {
super(Outcome.Detriment);
this.staticText = "target player reveals their hand and discards all cards with that spell's converted mana cost";
}
- public InfernalKirinEffect(final InfernalKirinEffect effect) {
+ private InfernalKirinEffect(final InfernalKirinEffect effect) {
super(effect);
}
@@ -75,27 +70,26 @@ class InfernalKirinEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
- if (spell != null) {
- int cmc = spell.getConvertedManaCost();
- Player targetPlayer = null;
- for (Target target : source.getTargets()) {
- if (target instanceof TargetPlayer) {
- targetPlayer = game.getPlayer(target.getFirstTarget());
- }
- }
- if (targetPlayer != null) {
- if (!targetPlayer.getHand().isEmpty()) {
- targetPlayer.revealCards("Infernal Kirin", targetPlayer.getHand(), game);
- for (UUID uuid : targetPlayer.getHand().copy()) {
- Card card = game.getCard(uuid);
- if (card != null && card.getConvertedManaCost() == cmc) {
- targetPlayer.discard(card, source, game);
- }
- }
- }
- return true;
+ if (spell == null) {
+ return false;
+ }
+ int cmc = spell.getConvertedManaCost();
+ Player targetPlayer = null;
+ for (Target target : source.getTargets()) {
+ if (target instanceof TargetPlayer) {
+ targetPlayer = game.getPlayer(target.getFirstTarget());
}
}
- return false;
+ if (targetPlayer == null) {
+ return false;
+ }
+ if (targetPlayer.getHand().isEmpty()) {
+ return true;
+ }
+ targetPlayer.revealCards(source, targetPlayer.getHand(), game);
+ Cards cards = targetPlayer.getHand().copy();
+ cards.removeIf(uuid -> game.getCard(uuid).getConvertedManaCost() != cmc);
+ targetPlayer.discard(cards, source, game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/i/InfernalReckoning.java b/Mage.Sets/src/mage/cards/i/InfernalReckoning.java
index 1d1cc6ded2e..de48593fe5b 100644
--- a/Mage.Sets/src/mage/cards/i/InfernalReckoning.java
+++ b/Mage.Sets/src/mage/cards/i/InfernalReckoning.java
@@ -69,7 +69,7 @@ class InfernalJudgmentEffect extends OneShotEffect {
}
int creaturePower = permanent.getPower().getValue();
permanent.moveToExile(null, null, source.getSourceId(), game);
- game.applyEffects();
+ game.getState().processAction(game);
player.gainLife(creaturePower, game, source);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/i/InfernalScarring.java b/Mage.Sets/src/mage/cards/i/InfernalScarring.java
index 10cccb69b0c..95d47bd72e6 100644
--- a/Mage.Sets/src/mage/cards/i/InfernalScarring.java
+++ b/Mage.Sets/src/mage/cards/i/InfernalScarring.java
@@ -3,7 +3,7 @@ package mage.cards.i;
import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.AttachEffect;
@@ -43,7 +43,7 @@ public final class InfernalScarring extends CardImpl {
Effect effect = new BoostEnchantedEffect(2, 0, Duration.WhileOnBattlefield);
effect.setText("Enchanted creature gets +2/+0");
ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
- effect = new GainAbilityAttachedEffect(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1)), AttachmentType.AURA, Duration.WhileOnBattlefield);
+ effect = new GainAbilityAttachedEffect(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)), AttachmentType.AURA, Duration.WhileOnBattlefield);
effect.setText("and has \"When this creature dies, draw a card.\"");
ability.addEffect(effect);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/i/InfernoElemental.java b/Mage.Sets/src/mage/cards/i/InfernoElemental.java
index 6815e8a26a2..1e3b74c9a41 100644
--- a/Mage.Sets/src/mage/cards/i/InfernoElemental.java
+++ b/Mage.Sets/src/mage/cards/i/InfernoElemental.java
@@ -3,7 +3,7 @@ package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class InfernoElemental extends CardImpl {
this.toughness = new MageInt(4);
// Whenever Inferno Elemental blocks or becomes blocked by a creature, Inferno Elemental deals 3 damage to that creature.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new DamageTargetEffect(3, true, "that creature"), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new DamageTargetEffect(3, true, "that creature"), false));
}
public InfernoElemental(final InfernoElemental card) {
diff --git a/Mage.Sets/src/mage/cards/i/InnerFlameIgniter.java b/Mage.Sets/src/mage/cards/i/InnerFlameIgniter.java
index 86ff0ed941c..19b6a685f46 100644
--- a/Mage.Sets/src/mage/cards/i/InnerFlameIgniter.java
+++ b/Mage.Sets/src/mage/cards/i/InnerFlameIgniter.java
@@ -4,9 +4,11 @@ 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.ContinuousEffect;
+import mage.abilities.effects.common.IfAbilityHasResolvedXTimesEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
+import mage.abilities.hint.common.AbilityResolutionCountHint;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -15,8 +17,6 @@ import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.StaticFilters;
-import mage.game.Game;
-import mage.players.Player;
import mage.watchers.common.AbilityResolvedWatcher;
import java.util.UUID;
@@ -37,7 +37,9 @@ public final class InnerFlameIgniter extends CardImpl {
Ability ability = new SimpleActivatedAbility(
new BoostControlledEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{2}{R}")
);
- ability.addEffect(new InnerFlameIgniterEffect());
+ ContinuousEffect effectIf3rdResolution = new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURES);
+ ability.addEffect(new IfAbilityHasResolvedXTimesEffect(Outcome.AddAbility, 3, effectIf3rdResolution));
+ ability.addHint(AbilityResolutionCountHint.instance);
this.addAbility(ability, new AbilityResolvedWatcher());
}
@@ -49,38 +51,4 @@ public final class InnerFlameIgniter extends CardImpl {
public InnerFlameIgniter copy() {
return new InnerFlameIgniter(this);
}
-}
-
-class InnerFlameIgniterEffect extends OneShotEffect {
-
- InnerFlameIgniterEffect() {
- super(Outcome.AddAbility);
- this.staticText = "If this is the third time this ability has resolved this turn, " +
- "creatures you control gain first strike until end of turn";
- }
-
- private InnerFlameIgniterEffect(final InnerFlameIgniterEffect effect) {
- super(effect);
- }
-
- @Override
- public InnerFlameIgniterEffect copy() {
- return new InnerFlameIgniterEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- AbilityResolvedWatcher watcher = game.getState().getWatcher(AbilityResolvedWatcher.class);
- if (controller == null
- || watcher == null
- || !watcher.checkActivations(source, game)) {
- return false;
- }
- game.addEffect(new GainAbilityControlledEffect(
- FirstStrikeAbility.getInstance(), Duration.EndOfTurn,
- StaticFilters.FILTER_PERMANENT_CREATURE
- ), source);
- return true;
- }
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/i/InniazTheGaleForce.java b/Mage.Sets/src/mage/cards/i/InniazTheGaleForce.java
new file mode 100644
index 00000000000..dcd62665a2c
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/i/InniazTheGaleForce.java
@@ -0,0 +1,164 @@
+package mage.cards.i;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.BoostAllEffect;
+import mage.abilities.effects.common.continuous.GainControlTargetEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.common.FilterNonlandPermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+import mage.filter.predicate.permanent.AttackingPredicate;
+import mage.filter.predicate.permanent.ControllerIdPredicate;
+import mage.game.Game;
+import mage.players.Player;
+import mage.players.PlayerList;
+import mage.target.TargetPermanent;
+import mage.target.targetpointer.FixedTarget;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class InniazTheGaleForce extends CardImpl {
+
+ private static final FilterCreaturePermanent filter
+ = new FilterCreaturePermanent("Attacking creatures with flying");
+ private static final FilterCreaturePermanent filter2
+ = new FilterCreaturePermanent("creatures you control with flying");
+
+ static {
+ filter.add(AttackingPredicate.instance);
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ filter2.add(new AbilityPredicate(FlyingAbility.class));
+ }
+
+ public InniazTheGaleForce(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.DJINN);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(4);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // {2}{W/U}: Attacking creatures with flying get +1/+1 until end of turn.
+ this.addAbility(new SimpleActivatedAbility(new BoostAllEffect(
+ 1, 1, Duration.EndOfTurn, filter, false
+ ), new ManaCostsImpl("{2}{W/U}")));
+
+ // Whenever three or more creatures you control with flying attack, each player gains control
+ // of a nonland permanent of your choice controlled by the player to their right.
+ this.addAbility(new AttacksWithCreaturesTriggeredAbility(
+ new InniazTheGaleForceEffect(), 3, filter2
+ ));
+ }
+
+ private InniazTheGaleForce(final InniazTheGaleForce card) {
+ super(card);
+ }
+
+ @Override
+ public InniazTheGaleForce copy() {
+ return new InniazTheGaleForce(this);
+ }
+}
+
+class InniazTheGaleForceEffect extends OneShotEffect {
+
+ private static final class PlayerPair {
+
+ private final Player leftPlayer;
+ private final Player rightPlayer;
+ private final FilterPermanent filter;
+ private final TargetPermanent target;
+
+ private PlayerPair(Player rightPlayer, Player leftPlayer) {
+ this.leftPlayer = leftPlayer;
+ this.rightPlayer = rightPlayer;
+ this.filter = this.makeFilter();
+ this.target = this.makeTarget();
+ }
+
+ private FilterPermanent makeFilter() {
+ FilterPermanent filter = new FilterNonlandPermanent(
+ "nonland permanent controlled by " + rightPlayer.getName()
+ + " to give to " + leftPlayer.getName()
+ );
+ filter.add(new ControllerIdPredicate(rightPlayer.getId()));
+ return filter;
+ }
+
+ private TargetPermanent makeTarget() {
+ return new TargetPermanent(1, 1, this.filter, true);
+ }
+
+ private void chooseTargets(Player controller, Game game, Ability source) {
+ if (game.getBattlefield().count(this.filter, source.getSourceId(), source.getControllerId(), game) > 0) {
+ controller.choose(Outcome.Neutral, this.target, source.getSourceId(), game);
+ }
+ }
+
+ private void createEffect(Game game, Ability source) {
+ if (this.target.getFirstTarget() == null) {
+ return;
+ }
+ game.addEffect(new GainControlTargetEffect(
+ Duration.Custom, true, leftPlayer.getId()
+ ).setTargetPointer(new FixedTarget(target.getFirstTarget(), game)), source);
+ }
+ }
+
+ InniazTheGaleForceEffect() {
+ super(Outcome.Benefit);
+ staticText = "each player gains control of a nonland permanent of your choice controlled by the player to their right.";
+ }
+
+ private InniazTheGaleForceEffect(final InniazTheGaleForceEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public InniazTheGaleForceEffect copy() {
+ return new InniazTheGaleForceEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller == null) {
+ return false;
+ }
+ PlayerList playerList = game.getState().getPlayersInRange(source.getControllerId(), game);
+ List playerPairList = new ArrayList<>();
+ for (int i = 0; i < playerList.size() - 1; i++) {
+ playerPairList.add(new PlayerPair(
+ game.getPlayer(playerList.get(i)),
+ game.getPlayer(playerList.get(i + 1))
+ ));
+ }
+ playerPairList.add(new PlayerPair(
+ game.getPlayer(playerList.get(playerPairList.size() - 1)),
+ game.getPlayer(playerList.get(0))
+ ));
+ for (PlayerPair playerPair : playerPairList) {
+ playerPair.chooseTargets(controller, game, source);
+ }
+ for (PlayerPair playerPair : playerPairList) {
+ playerPair.createEffect(game, source);
+ }
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/i/InsidiousBookworms.java b/Mage.Sets/src/mage/cards/i/InsidiousBookworms.java
index 4f6e4b83bec..09e327fa681 100644
--- a/Mage.Sets/src/mage/cards/i/InsidiousBookworms.java
+++ b/Mage.Sets/src/mage/cards/i/InsidiousBookworms.java
@@ -4,7 +4,7 @@ package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
@@ -27,7 +27,7 @@ public final class InsidiousBookworms extends CardImpl {
this.toughness = new MageInt(1);
// When Insidious Bookworms dies, you may pay {1}{B}. If you do, target player discards a card at random.
- Ability ability = new DiesTriggeredAbility(new DoIfCostPaid(new DiscardTargetEffect(1, true), new ManaCostsImpl("{1}{B}")));
+ Ability ability = new DiesSourceTriggeredAbility(new DoIfCostPaid(new DiscardTargetEffect(1, true), new ManaCostsImpl("{1}{B}")));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/i/InsidiousDreams.java b/Mage.Sets/src/mage/cards/i/InsidiousDreams.java
index fecfde77a63..bdd0e664000 100644
--- a/Mage.Sets/src/mage/cards/i/InsidiousDreams.java
+++ b/Mage.Sets/src/mage/cards/i/InsidiousDreams.java
@@ -113,7 +113,7 @@ class InsidiousDreamsAdditionalCost extends VariableCostImpl {
InsidiousDreamsAdditionalCost() {
super("cards to discard");
- this.text = "as an additional cost to cast this spell, discard X cards";
+ this.text = "discard X cards";
}
InsidiousDreamsAdditionalCost(final InsidiousDreamsAdditionalCost cost) {
diff --git a/Mage.Sets/src/mage/cards/i/IntetTheDreamer.java b/Mage.Sets/src/mage/cards/i/IntetTheDreamer.java
index 5bf1a68777d..c93e56b1394 100644
--- a/Mage.Sets/src/mage/cards/i/IntetTheDreamer.java
+++ b/Mage.Sets/src/mage/cards/i/IntetTheDreamer.java
@@ -14,12 +14,16 @@ import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
-import mage.game.ExileZone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
+import mage.abilities.decorator.ConditionalAsThoughEffect;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
+import mage.target.targetpointer.FixedTarget;
/**
* @author fireshoes
@@ -39,15 +43,13 @@ public final class IntetTheDreamer extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever Intet, the Dreamer deals combat damage to a player, you may pay {2}{U}. If you do, exile the top card of your library face down.
+ // You may play that card without paying its mana cost for as long as Intet remains on the battlefield.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
new DoIfCostPaid(new IntetTheDreamerExileEffect(), new ManaCostsImpl("{2}{U}")), false, true));
// You may look at that card for as long as it remains exiled.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new IntetTheDreamerLookEffect()));
- // You may play that card without paying its mana cost for as long as Intet remains on the battlefield.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new IntetTheDreamerCastEffect()));
-
}
public IntetTheDreamer(final IntetTheDreamer card) {
@@ -64,7 +66,7 @@ class IntetTheDreamerExileEffect extends OneShotEffect {
public IntetTheDreamerExileEffect() {
super(Outcome.Discard);
- staticText = "exile the top card of your library face down";
+ staticText = "exile the top card of your library face down. You may play that card without paying its mana cost for as long as Intet remains on the battlefield";
}
public IntetTheDreamerExileEffect(final IntetTheDreamerExileEffect effect) {
@@ -77,20 +79,18 @@ class IntetTheDreamerExileEffect extends OneShotEffect {
if (controller != null) {
Card card = controller.getLibrary().getFromTop(game);
MageObject sourceObject = source.getSourceObject(game);
- if (card != null
- && sourceObject != null) {
+ if (card != null && sourceObject != null) {
card.setFaceDown(true, game);
- controller.moveCardsToExile(
- card,
- source,
- game,
- false,
- CardUtil.getExileZoneId(game,
- source.getSourceId(),
- sourceObject.getZoneChangeCounter(game)), // sourceObject must be used due to source not working correctly
- sourceObject.getIdName());
+ controller.moveCardsToExile(card, source, game, false,
+ CardUtil.getExileZoneId(game, source.getSourceId(), sourceObject.getZoneChangeCounter(game)), // sourceObject must be used due to source not working correctly
+ sourceObject.getIdName() + " (" + sourceObject.getZoneChangeCounter(game) + ")");
card.setFaceDown(true, game);
- game.getState().setValue("Exiled_IntetTheDreamer" + card.getId(), Boolean.TRUE);
+ ContinuousEffect effect = new ConditionalAsThoughEffect(
+ new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, TargetController.YOU, Duration.Custom, true),
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD));
+ effect.setTargetPointer(new FixedTarget(card, game));
+ game.getState().addEffect(effect, source);
+ game.getState().setValue("Exiled_IntetTheDreamer" + card.getId(), Boolean.TRUE); // TODO This value will never be removed
return true;
}
}
@@ -103,63 +103,6 @@ class IntetTheDreamerExileEffect extends OneShotEffect {
}
}
-class IntetTheDreamerCastEffect extends AsThoughEffectImpl {
-
- public IntetTheDreamerCastEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
- staticText = "You may play the card from exile without paying its mana cost for as long as {this} remains on the battlefield";
- }
-
- public IntetTheDreamerCastEffect(final IntetTheDreamerCastEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public IntetTheDreamerCastEffect copy() {
- return new IntetTheDreamerCastEffect(this);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- if (affectedControllerId.equals(source.getControllerId())) {
- Player controller = game.getPlayer(source.getControllerId());
- MageObject sourceObject = source.getSourceObject(game);
- if (controller != null
- && sourceObject != null) {
- Card card = game.getCard(objectId);
- if (card != null
- && card.isFaceDown(game)) {
- ExileZone zone = game.getExile().getExileZone(
- CardUtil.getExileZoneId(game,
- source.getSourceId(),
- sourceObject.getZoneChangeCounter(game))); // sourceObject must be used due to source not working correctly
- if (zone != null
- && zone.contains(card.getId())) {
- if (card.isLand()) {
- if (game.canPlaySorcery(controller.getId())
- && game.getPlayer(controller.getId()).canPlayLand()) {
- return controller.chooseUse(outcome, "Play " + card.getIdName() + '?', source, game);
- }
- } else {
- controller.setCastSourceIdWithAlternateMana(objectId,
- null,
- card.getSpellAbility().getCosts());
- return true;
- }
- }
- }
- }
- }
- return false;
-
- }
-}
-
class IntetTheDreamerLookEffect extends AsThoughEffectImpl {
public IntetTheDreamerLookEffect() {
@@ -187,10 +130,16 @@ class IntetTheDreamerLookEffect extends AsThoughEffectImpl {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card card = game.getCard(objectId);
- return (card != null
- && card.isFaceDown(game)
- && game.getExile().containsId(card.getId(), game)
- && Boolean.TRUE.equals(game.getState().getValue("Exiled_IntetTheDreamer" + card.getId())));
+ if (card != null) {
+ if (card.isFaceDown(game)
+ && game.getExile().containsId(card.getId(), game)
+ && Boolean.TRUE.equals(game.getState().getValue("Exiled_IntetTheDreamer" + card.getId()))) {
+ return true;
+ } else {
+ this.discard();
+ game.getState().setValue("Exiled_IntetTheDreamer" + card.getId(), null);
+ }
+ }
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/i/IntoTheStory.java b/Mage.Sets/src/mage/cards/i/IntoTheStory.java
index e48ef7bf07e..02d5dfded45 100644
--- a/Mage.Sets/src/mage/cards/i/IntoTheStory.java
+++ b/Mage.Sets/src/mage/cards/i/IntoTheStory.java
@@ -5,6 +5,7 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -25,8 +26,8 @@ public final class IntoTheStory extends CardImpl {
// This spell costs {3} less to cast if an opponent has seven or more cards in their graveyard.
this.addAbility(new SimpleStaticAbility(
- Zone.STACK, new SpellCostReductionSourceEffect(3, IntoTheStoryCondition.instance)
- ).setRuleAtTheTop(true));
+ Zone.ALL, new SpellCostReductionSourceEffect(3, IntoTheStoryCondition.instance)
+ ).setRuleAtTheTop(true).addHint(new ConditionHint(IntoTheStoryCondition.instance, "Opponent has seven or more cards in their graveyard")));
// Draw four cards.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4));
diff --git a/Mage.Sets/src/mage/cards/i/Invigorate.java b/Mage.Sets/src/mage/cards/i/Invigorate.java
index ad4e2d3ab99..dddb5418107 100644
--- a/Mage.Sets/src/mage/cards/i/Invigorate.java
+++ b/Mage.Sets/src/mage/cards/i/Invigorate.java
@@ -1,4 +1,3 @@
-
package mage.cards.i;
import java.util.UUID;
@@ -9,7 +8,7 @@ import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Duration;
+import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.target.common.TargetCreaturePermanent;
@@ -29,9 +28,9 @@ public final class Invigorate extends CardImpl {
public Invigorate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{G}");
-
// If you control a Forest, rather than pay Invigorate's mana cost, you may have an opponent gain 3 life.
this.addAbility(new AlternativeCostSourceAbility(new GainLifeOpponentCost(3), new PermanentsOnTheBattlefieldCondition(filter)));
+
// Target creature gets +4/+4 until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(4,4,Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
diff --git a/Mage.Sets/src/mage/cards/i/InvigoratingSurge.java b/Mage.Sets/src/mage/cards/i/InvigoratingSurge.java
new file mode 100644
index 00000000000..dfaae8a0e3d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/i/InvigoratingSurge.java
@@ -0,0 +1,66 @@
+package mage.cards.i;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.counter.AddCountersTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.counters.CounterType;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.target.common.TargetControlledCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class InvigoratingSurge extends CardImpl {
+
+ public InvigoratingSurge(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}");
+
+ // Put a +1/+1 counter on target creature you control, then double the number of +1/+1 counters on that creature.
+ this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
+ this.getSpellAbility().addEffect(new InvigoratingSurgeEffect());
+ this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
+ }
+
+ private InvigoratingSurge(final InvigoratingSurge card) {
+ super(card);
+ }
+
+ @Override
+ public InvigoratingSurge copy() {
+ return new InvigoratingSurge(this);
+ }
+}
+
+class InvigoratingSurgeEffect extends OneShotEffect {
+
+ InvigoratingSurgeEffect() {
+ super(Outcome.Benefit);
+ staticText = ", then double the number of +1/+1 counters on that creature";
+ }
+
+ private InvigoratingSurgeEffect(final InvigoratingSurgeEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public InvigoratingSurgeEffect copy() {
+ return new InvigoratingSurgeEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanent(source.getFirstTarget());
+ if (permanent == null) {
+ return false;
+ }
+ int counterCount = permanent.getCounters(game).getCount(CounterType.P1P1);
+ return counterCount > 0 && permanent.addCounters(CounterType.P1P1.createInstance(counterCount), source, game);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/i/IriniSengir.java b/Mage.Sets/src/mage/cards/i/IriniSengir.java
index 9ba91444fd3..8d485f939f2 100644
--- a/Mage.Sets/src/mage/cards/i/IriniSengir.java
+++ b/Mage.Sets/src/mage/cards/i/IriniSengir.java
@@ -1,35 +1,32 @@
-
package mage.cards.i;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.SuperType;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.common.FilterEnchantmentCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class IriniSengir extends CardImpl {
-
+
private static final FilterEnchantmentCard filter = new FilterEnchantmentCard("Green enchantment spells and white enchantment spells");
+
static {
filter.add(Predicates.or(new ColorPredicate(ObjectColor.GREEN),
(new ColorPredicate(ObjectColor.WHITE))));
}
public IriniSengir(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.VAMPIRE);
this.subtype.add(SubType.DWARF);
@@ -37,7 +34,9 @@ public final class IriniSengir extends CardImpl {
this.toughness = new MageInt(2);
// Green enchantment spells and white enchantment spells cost {2} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasementAllEffect(filter, 2)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostIncreasingAllEffect(2, filter, TargetController.ANY))
+ );
}
public IriniSengir(final IriniSengir card) {
diff --git a/Mage.Sets/src/mage/cards/i/Irradiate.java b/Mage.Sets/src/mage/cards/i/Irradiate.java
index 2e19012e7c7..7208209f31d 100644
--- a/Mage.Sets/src/mage/cards/i/Irradiate.java
+++ b/Mage.Sets/src/mage/cards/i/Irradiate.java
@@ -1,9 +1,8 @@
-
package mage.cards.i;
-import java.util.UUID;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -11,19 +10,21 @@ import mage.constants.Duration;
import mage.filter.common.FilterControlledArtifactPermanent;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author LoneFox
*/
public final class Irradiate extends CardImpl {
public Irradiate(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}");
// Target creature gets -1/-1 until end of turn for each artifact you control.
PermanentsOnBattlefieldCount count = new PermanentsOnBattlefieldCount(new FilterControlledArtifactPermanent(), -1);
this.getSpellAbility().addEffect(new BoostTargetEffect(count, count, Duration.EndOfTurn, true));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
+ this.getSpellAbility().addHint(ArtifactYouControlHint.instance);
}
public Irradiate(final Irradiate card) {
diff --git a/Mage.Sets/src/mage/cards/i/IsamaruHoundOfKonda.java b/Mage.Sets/src/mage/cards/i/IsamaruHoundOfKonda.java
index 35296f3e40e..4c7eb1b336d 100644
--- a/Mage.Sets/src/mage/cards/i/IsamaruHoundOfKonda.java
+++ b/Mage.Sets/src/mage/cards/i/IsamaruHoundOfKonda.java
@@ -19,7 +19,7 @@ public final class IsamaruHoundOfKonda extends CardImpl {
public IsamaruHoundOfKonda(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.addSuperType(SuperType.LEGENDARY);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/i/IsaoEnlightenedBushi.java b/Mage.Sets/src/mage/cards/i/IsaoEnlightenedBushi.java
index 7f69d6bb9f5..d0f044d1ed8 100644
--- a/Mage.Sets/src/mage/cards/i/IsaoEnlightenedBushi.java
+++ b/Mage.Sets/src/mage/cards/i/IsaoEnlightenedBushi.java
@@ -4,7 +4,7 @@ package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.RegenerateTargetEffect;
@@ -40,7 +40,7 @@ public final class IsaoEnlightenedBushi extends CardImpl {
this.toughness = new MageInt(1);
// Isao, Enlightened Bushi can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
this.addAbility(new BushidoAbility(2));
// {2}: Regenerate target Samurai.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateTargetEffect(), new GenericManaCost(2));
diff --git a/Mage.Sets/src/mage/cards/i/IsarethTheAwakener.java b/Mage.Sets/src/mage/cards/i/IsarethTheAwakener.java
index 62cf6c7eff7..ced07404f12 100644
--- a/Mage.Sets/src/mage/cards/i/IsarethTheAwakener.java
+++ b/Mage.Sets/src/mage/cards/i/IsarethTheAwakener.java
@@ -1,27 +1,19 @@
package mage.cards.i;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
-import mage.constants.SubType;
-import mage.constants.SuperType;
import mage.abilities.keyword.DeathtouchAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.ComparisonType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.counters.CounterType;
import mage.counters.Counters;
import mage.filter.FilterCard;
@@ -33,8 +25,9 @@ import mage.game.events.ZoneChangeEvent;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class IsarethTheAwakener extends CardImpl {
@@ -55,7 +48,7 @@ public final class IsarethTheAwakener extends CardImpl {
this.addAbility(new AttacksTriggeredAbility(new IsarethTheAwakenerCreateReflexiveTriggerEffect(), false));
}
- public IsarethTheAwakener(final IsarethTheAwakener card) {
+ private IsarethTheAwakener(final IsarethTheAwakener card) {
super(card);
}
@@ -67,15 +60,17 @@ public final class IsarethTheAwakener extends CardImpl {
class IsarethTheAwakenerCreateReflexiveTriggerEffect extends OneShotEffect {
- public IsarethTheAwakenerCreateReflexiveTriggerEffect() {
+ private static final String rule = "return target creature card "
+ + "with converted mana cost X from your graveyard to the battlefield "
+ + "with a corpse counter on it. If that creature would leave the battlefield, "
+ + "exile it instead of putting it anywhere else.";
+
+ IsarethTheAwakenerCreateReflexiveTriggerEffect() {
super(Outcome.Benefit);
- this.staticText = "you may pay {X}. When you do, return target creature card "
- + "with converted mana cost X from your graveyard to the battlefield "
- + "with a corpse counter on it. If that creature would leave the battlefield, "
- + "exile it instead of putting it anywhere else.";
+ this.staticText = "you may pay {X}. When you do, " + rule;
}
- public IsarethTheAwakenerCreateReflexiveTriggerEffect(final IsarethTheAwakenerCreateReflexiveTriggerEffect effect) {
+ private IsarethTheAwakenerCreateReflexiveTriggerEffect(final IsarethTheAwakenerCreateReflexiveTriggerEffect effect) {
super(effect);
}
@@ -97,67 +92,34 @@ class IsarethTheAwakenerCreateReflexiveTriggerEffect extends OneShotEffect {
if (!cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) {
return false;
}
- game.addDelayedTriggeredAbility(new IsarethTheAwakenerReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect(costX).apply(game, source);
- }
-}
-
-class IsarethTheAwakenerReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- public IsarethTheAwakenerReflexiveTriggeredAbility() {
- super(new IsarethTheAwakenerEffect(), Duration.OneUse, true);
- this.addEffect(new IsarethTheAwakenerReplacementEffect());
- }
-
- public IsarethTheAwakenerReflexiveTriggeredAbility(final IsarethTheAwakenerReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public IsarethTheAwakenerReflexiveTriggeredAbility copy() {
- return new IsarethTheAwakenerReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- if (!event.getPlayerId().equals(this.getControllerId())
- || !event.getSourceId().equals(this.getSourceId())) {
- return false;
- }
- FilterCard filter = new FilterCreatureCard(
- "creature card with converted mana cost "
- + event.getAmount()
- + " or less from your graveyard"
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new IsarethTheAwakenerEffect(), false, rule
);
- filter.add(new ConvertedManaCostPredicate(
- ComparisonType.FEWER_THAN, event.getAmount() + 1
- ));
- this.getTargets().clear();
- this.addTarget(new TargetCardInYourGraveyard(filter));
+ ability.addEffect(new IsarethTheAwakenerReplacementEffect());
+ ability.addTarget(new TargetCardInYourGraveyard(makeFilter(costX)));
+ game.fireReflexiveTriggeredAbility(ability, source);
return true;
}
- @Override
- public String getRule() {
- return "When you pay {X}, return target creature card "
- + "with converted mana cost X from your graveyard to the battlefield "
- + "with a corpse counter on it. If that creature would leave the battlefield, "
- + "exile it instead of putting it anywhere else.";
+ private static FilterCard makeFilter(int xValue) {
+ FilterCard filter = new FilterCreatureCard(
+ "creature card with converted mana cost " +
+ xValue + " or less from your graveyard"
+ );
+ filter.add(new ConvertedManaCostPredicate(
+ ComparisonType.EQUAL_TO, xValue
+ ));
+ return filter;
}
}
class IsarethTheAwakenerEffect extends OneShotEffect {
- public IsarethTheAwakenerEffect() {
+ IsarethTheAwakenerEffect() {
super(Outcome.PutCreatureInPlay);
}
- public IsarethTheAwakenerEffect(final IsarethTheAwakenerEffect effect) {
+ private IsarethTheAwakenerEffect(final IsarethTheAwakenerEffect effect) {
super(effect);
}
@@ -182,11 +144,11 @@ class IsarethTheAwakenerEffect extends OneShotEffect {
class IsarethTheAwakenerReplacementEffect extends ReplacementEffectImpl {
- public IsarethTheAwakenerReplacementEffect() {
+ IsarethTheAwakenerReplacementEffect() {
super(Duration.Custom, Outcome.Exile);
}
- public IsarethTheAwakenerReplacementEffect(final IsarethTheAwakenerReplacementEffect effect) {
+ private IsarethTheAwakenerReplacementEffect(final IsarethTheAwakenerReplacementEffect effect) {
super(effect);
}
diff --git a/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java b/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java
index 7a6a663c2d3..ade3ddfe383 100644
--- a/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java
+++ b/Mage.Sets/src/mage/cards/i/IsperiaTheInscrutable.java
@@ -1,7 +1,5 @@
-
package mage.cards.i;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
@@ -14,23 +12,25 @@ import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
+import mage.util.CardUtil;
+
+import java.util.UUID;
/**
- *
* @author lunaskyrise
*/
public final class IsperiaTheInscrutable extends CardImpl {
public IsperiaTheInscrutable(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{W}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}{U}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.SPHINX);
this.power = new MageInt(3);
@@ -38,7 +38,7 @@ public final class IsperiaTheInscrutable extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
-
+
// Whenever Isperia the Inscrutable deals combat damage to a player, name a card. That player reveals their hand. If they reveal the named card, search your library for a creature card with flying, reveal it, put it into your hand, then shuffle your library.
Effect effect1 = new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL);
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(effect1, false, true);
@@ -78,12 +78,11 @@ class IsperiaTheInscrutableEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
- Object object = game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (player != null && object instanceof String) {
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ if (player != null && cardName != null) {
player.revealCards(player.getLogName() + " hand", player.getHand(), game, true);
- String namedCard = (String) object;
for (Card card : player.getHand().getCards(game)) {
- if (card != null && card.getName().equals(namedCard)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true, true).apply(game, source);
}
}
diff --git a/Mage.Sets/src/mage/cards/i/IvoryGargoyle.java b/Mage.Sets/src/mage/cards/i/IvoryGargoyle.java
index 0cd6c5e37d4..98dcfe26522 100644
--- a/Mage.Sets/src/mage/cards/i/IvoryGargoyle.java
+++ b/Mage.Sets/src/mage/cards/i/IvoryGargoyle.java
@@ -3,7 +3,7 @@ package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -34,7 +34,7 @@ public final class IvoryGargoyle extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Ivory Gargoyle dies, return it to the battlefield under its owner's control at the beginning of the next end step and you skip your next draw step.
- Ability ability = new DiesTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(
+ Ability ability = new DiesSourceTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect())));
ability.addEffect(new SkipNextDrawStepControllerEffect());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java
index e9504663f37..cb756e91504 100644
--- a/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java
+++ b/Mage.Sets/src/mage/cards/j/JaceTelepathUnbound.java
@@ -5,32 +5,19 @@ import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
-import mage.abilities.effects.AsThoughEffectImpl;
-import mage.abilities.effects.ContinuousEffect;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.effects.*;
import mage.abilities.effects.common.GetEmblemEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
-import mage.constants.Outcome;
import mage.constants.SuperType;
-import mage.constants.Zone;
import mage.filter.common.FilterInstantOrSorceryCard;
-import mage.game.Game;
import mage.game.command.emblems.JaceTelepathUnboundEmblem;
-import mage.game.events.GameEvent;
-import mage.game.events.ZoneChangeEvent;
-import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetCreaturePermanent;
-import mage.target.targetpointer.FixedTarget;
/**
*
@@ -57,7 +44,9 @@ public final class JaceTelepathUnbound extends CardImpl {
this.addAbility(ability);
// -3: You may cast target instant or sorcery card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead.
- ability = new LoyaltyAbility(new JaceTelepathUnboundEffect(), -3);
+ CastCardFromGraveyardThenExileItEffect minusEffect = new CastCardFromGraveyardThenExileItEffect();
+ minusEffect.setText("You may cast target instant or sorcery card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead");
+ ability = new LoyaltyAbility(minusEffect, -3);
ability.addTarget(new TargetCardInYourGraveyard(new FilterInstantOrSorceryCard()));
this.addAbility(ability);
@@ -74,104 +63,3 @@ public final class JaceTelepathUnbound extends CardImpl {
return new JaceTelepathUnbound(this);
}
}
-
-class JaceTelepathUnboundEffect extends OneShotEffect {
-
- JaceTelepathUnboundEffect() {
- super(Outcome.Benefit);
- this.staticText = "You may cast target instant or sorcery card from your graveyard this turn. If that card would be put into your graveyard this turn, exile it instead";
- }
-
- JaceTelepathUnboundEffect(final JaceTelepathUnboundEffect effect) {
- super(effect);
- }
-
- @Override
- public JaceTelepathUnboundEffect copy() {
- return new JaceTelepathUnboundEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Card card = game.getCard(this.getTargetPointer().getFirst(game, source));
- if (card != null) {
- ContinuousEffect effect = new JaceTelepathUnboundCastFromGraveyardEffect();
- effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
- game.addEffect(effect, source);
- effect = new JaceTelepathUnboundReplacementEffect(card.getId());
- game.addEffect(effect, source);
- return true;
- }
- return false;
- }
-}
-
-class JaceTelepathUnboundCastFromGraveyardEffect extends AsThoughEffectImpl {
-
- JaceTelepathUnboundCastFromGraveyardEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
- }
-
- JaceTelepathUnboundCastFromGraveyardEffect(final JaceTelepathUnboundCastFromGraveyardEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public JaceTelepathUnboundCastFromGraveyardEffect copy() {
- return new JaceTelepathUnboundCastFromGraveyardEffect(this);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- return objectId.equals(this.getTargetPointer().getFirst(game, source)) && affectedControllerId.equals(source.getControllerId());
- }
-}
-
-class JaceTelepathUnboundReplacementEffect extends ReplacementEffectImpl {
-
- private final UUID cardId;
-
- JaceTelepathUnboundReplacementEffect(UUID cardId) {
- super(Duration.EndOfTurn, Outcome.Exile);
- this.cardId = cardId;
- staticText = "If that card would be put into your graveyard this turn, exile it instead";
- }
-
- JaceTelepathUnboundReplacementEffect(final JaceTelepathUnboundReplacementEffect effect) {
- super(effect);
- this.cardId = effect.cardId;
- }
-
- @Override
- public JaceTelepathUnboundReplacementEffect copy() {
- return new JaceTelepathUnboundReplacementEffect(this);
- }
-
- @Override
- public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- Player controller = game.getPlayer(source.getControllerId());
- Card card = game.getCard(this.cardId);
- if (controller != null && card != null) {
- controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.STACK, true);
- return true;
- }
- return false;
- }
-
- @Override
- public boolean checksEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.ZONE_CHANGE;
- }
-
- @Override
- public boolean applies(GameEvent event, Ability source, Game game) {
- ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
- return zEvent.getToZone() == Zone.GRAVEYARD
- && zEvent.getTargetId().equals(this.cardId);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/j/JaceWielderOfMysteries.java b/Mage.Sets/src/mage/cards/j/JaceWielderOfMysteries.java
index 2332417ac97..ddfcc1a16eb 100644
--- a/Mage.Sets/src/mage/cards/j/JaceWielderOfMysteries.java
+++ b/Mage.Sets/src/mage/cards/j/JaceWielderOfMysteries.java
@@ -90,14 +90,14 @@ class JaceWielderOfMysteriesContinuousEffect extends ReplacementEffectImpl {
@Override
public boolean checksEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.EMPTY_DRAW;
+ return event.getType() == GameEvent.EventType.DRAW_CARD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getPlayerId().equals(source.getControllerId())) {
Player player = game.getPlayer(event.getPlayerId());
- if (player != null && !player.hasLost() && player.isEmptyDraw()) {
+ if (player != null && !player.hasLost() && !player.getLibrary().hasCards()) {
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/j/JacesMindseeker.java b/Mage.Sets/src/mage/cards/j/JacesMindseeker.java
index dd0f2354fe6..cc4e59d68f7 100644
--- a/Mage.Sets/src/mage/cards/j/JacesMindseeker.java
+++ b/Mage.Sets/src/mage/cards/j/JacesMindseeker.java
@@ -1,19 +1,12 @@
package mage.cards.j;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
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.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
+import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
@@ -25,8 +18,10 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetOpponent;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class JacesMindseeker extends CardImpl {
@@ -65,9 +60,8 @@ class JaceMindseekerEffect extends OneShotEffect {
public JaceMindseekerEffect() {
super(Outcome.PlayForFree);
- this.staticText = "target opponent puts the top five cards of their "
- + "library into their graveyard. You may cast an instant or "
- + "sorcery card from among them without paying its mana cost";
+ this.staticText = "target opponent mills five cards. You may cast an instant or sorcery spell " +
+ "from among them without paying its mana cost.";
}
public JaceMindseekerEffect(final JaceMindseekerEffect effect) {
@@ -84,10 +78,7 @@ class JaceMindseekerEffect extends OneShotEffect {
Cards cardsToCast = new CardsImpl();
Player targetOpponent = game.getPlayer(targetPointer.getFirst(game, source));
if (targetOpponent != null) {
- Set allCards = targetOpponent.getLibrary().getTopCards(game, 5);
- Set toMove = new HashSet<>();
- toMove.addAll(allCards);
- targetOpponent.moveCards(toMove, Zone.GRAVEYARD, source, game);
+ Set allCards = targetOpponent.millCards(5, source, game).getCards(game);
for (Card card : allCards) {
if (filter.match(card, game)) {
Zone zone = game.getState().getZone(card.getId());
diff --git a/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java b/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java
index 802a648f8b5..6c38cd8e8c6 100644
--- a/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java
+++ b/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java
@@ -1,7 +1,5 @@
-
package mage.cards.j;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -9,24 +7,26 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
+import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
*/
public final class JaddiLifestrider extends CardImpl {
public JaddiLifestrider(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}");
this.subtype.add(SubType.ELEMENTAL);
this.power = new MageInt(2);
@@ -47,9 +47,9 @@ public final class JaddiLifestrider extends CardImpl {
}
class JaddiLifestriderEffect extends OneShotEffect {
-
+
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creatures you control");
-
+
static {
filter.add(TargetController.YOU.getControllerPredicate());
filter.add(Predicates.not(TappedPredicate.instance));
@@ -70,9 +70,10 @@ class JaddiLifestriderEffect extends OneShotEffect {
Player you = game.getPlayer(source.getControllerId());
TargetCreaturePermanent target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true);
if (target.canChoose(source.getControllerId(), game) && target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), game)) {
- for (UUID creature : target.getTargets()) {
+ for (UUID creatureId : target.getTargets()) {
+ Permanent creature = game.getPermanent(creatureId);
if (creature != null) {
- game.getPermanent(creature).tap(game);
+ creature.tap(game);
tappedAmount++;
}
}
diff --git a/Mage.Sets/src/mage/cards/j/JadeLeech.java b/Mage.Sets/src/mage/cards/j/JadeLeech.java
index 80bfff6d4c3..d5a8a6dab35 100644
--- a/Mage.Sets/src/mage/cards/j/JadeLeech.java
+++ b/Mage.Sets/src/mage/cards/j/JadeLeech.java
@@ -1,22 +1,22 @@
-
package mage.cards.j;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementControllerEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author LoneFox
*/
public final class JadeLeech extends CardImpl {
@@ -28,14 +28,14 @@ public final class JadeLeech extends CardImpl {
}
public JadeLeech(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
this.subtype.add(SubType.LEECH);
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Green spells you cast cost {G} more to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
- new SpellsCostIncreasementControllerEffect(filter, new ManaCostsImpl("{G}"))));
+ new SpellsCostIncreasingAllEffect(new ManaCostsImpl("{G}"), filter, TargetController.YOU)));
}
public JadeLeech(final JadeLeech card) {
diff --git a/Mage.Sets/src/mage/cards/j/JanglingAutomaton.java b/Mage.Sets/src/mage/cards/j/JanglingAutomaton.java
new file mode 100644
index 00000000000..ce649f66910
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/j/JanglingAutomaton.java
@@ -0,0 +1,72 @@
+package mage.cards.j;
+
+import java.util.UUID;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Outcome;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.permanent.ControllerIdPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+
+/**
+ * @author arcox
+ */
+public final class JanglingAutomaton extends CardImpl {
+ public JanglingAutomaton(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
+ this.subtype.add(SubType.CONSTRUCT);
+
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(2);
+
+ // Whenever Jangling Automaton attacks, untap all creatures defending player controls.
+ this.addAbility(new AttacksTriggeredAbility(new JanglingAutomatonEffect(), false));
+ }
+
+ public JanglingAutomaton(final JanglingAutomaton card) {
+ super(card);
+ }
+
+ @Override
+ public JanglingAutomaton copy() {
+ return new JanglingAutomaton(this);
+ }
+}
+
+class JanglingAutomatonEffect extends OneShotEffect {
+ public JanglingAutomatonEffect() {
+ super(Outcome.Untap);
+ this.staticText = "untap all creatures defending player controls";
+ }
+
+ public JanglingAutomatonEffect(final JanglingAutomatonEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public JanglingAutomatonEffect copy() {
+ return new JanglingAutomatonEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ UUID defenderId = game.getCombat().getDefendingPlayerId(source.getSourceId(), game);
+ if (defenderId != null) {
+ FilterCreaturePermanent filter = new FilterCreaturePermanent();
+ filter.add(new ControllerIdPredicate(defenderId));
+ for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
+ permanent.untap(game);
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/j/JayaBallard.java b/Mage.Sets/src/mage/cards/j/JayaBallard.java
index 8af23864bfc..6b0e37e0755 100644
--- a/Mage.Sets/src/mage/cards/j/JayaBallard.java
+++ b/Mage.Sets/src/mage/cards/j/JayaBallard.java
@@ -1,18 +1,16 @@
-
package mage.cards.j;
-import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.mana.AddConditionalManaEffect;
import mage.abilities.effects.common.GetEmblemEffect;
+import mage.abilities.effects.mana.AddConditionalManaEffect;
import mage.abilities.mana.builder.common.InstantOrSorcerySpellManaBuilder;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
@@ -24,8 +22,9 @@ import mage.players.Player;
import mage.target.common.TargetDiscard;
import mage.watchers.common.CastFromGraveyardWatcher;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class JayaBallard extends CardImpl {
@@ -76,20 +75,13 @@ class JayaBallardDiscardDrawEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- TargetDiscard target = new TargetDiscard(0, 3, new FilterCard(), controller.getId());
- target.choose(outcome, controller.getId(), source.getSourceId(), game);
- int count = 0;
- for (UUID cardId : target.getTargets()) {
- Card card = game.getCard(cardId);
- if (card != null) {
- controller.discard(card, source, game);
- count++;
- }
- }
- controller.drawCards(count, source.getSourceId(), game);
- return true;
+ if (controller == null) {
+ return false;
}
- return false;
+ TargetDiscard target = new TargetDiscard(0, 3, new FilterCard(), controller.getId());
+ target.choose(outcome, controller.getId(), source.getSourceId(), game);
+ int count = controller.discard(new CardsImpl(target.getTargets()), source, game).size();
+ controller.drawCards(count, source.getSourceId(), game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/j/JeganthaTheWellspring.java b/Mage.Sets/src/mage/cards/j/JeganthaTheWellspring.java
index f8e6648a202..f173e108161 100644
--- a/Mage.Sets/src/mage/cards/j/JeganthaTheWellspring.java
+++ b/Mage.Sets/src/mage/cards/j/JeganthaTheWellspring.java
@@ -67,7 +67,7 @@ enum JeganthaTheWellspringCompanionCondition implements CompanionCondition {
return deck.stream().noneMatch(JeganthaTheWellspringCompanionCondition::checkCard);
}
- private static final boolean checkCard(Card card) {
+ private static boolean checkCard(Card card) {
Map symbolMap = new HashMap();
return card.getManaCost()
.getSymbols()
diff --git a/Mage.Sets/src/mage/cards/j/JeskaiSage.java b/Mage.Sets/src/mage/cards/j/JeskaiSage.java
index f5b2c24b155..645dc0bf294 100644
--- a/Mage.Sets/src/mage/cards/j/JeskaiSage.java
+++ b/Mage.Sets/src/mage/cards/j/JeskaiSage.java
@@ -3,7 +3,7 @@ package mage.cards.j;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.ProwessAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class JeskaiSage extends CardImpl {
// Prowess
this.addAbility(new ProwessAbility());
// When Jeskai Sage dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
diff --git a/Mage.Sets/src/mage/cards/j/JohtullWurm.java b/Mage.Sets/src/mage/cards/j/JohtullWurm.java
index 5b0bb8b2f0f..42c171fcced 100644
--- a/Mage.Sets/src/mage/cards/j/JohtullWurm.java
+++ b/Mage.Sets/src/mage/cards/j/JohtullWurm.java
@@ -3,7 +3,7 @@ package mage.cards.j;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.MultipliedValue;
import mage.abilities.dynamicvalue.common.BlockedCreatureCount;
@@ -31,7 +31,7 @@ public final class JohtullWurm extends CardImpl {
DynamicValue blockedCreatureCount = new BlockedCreatureCount("each creature blocking it beyond the first", true);
Effect effect = new BoostSourceEffect(new MultipliedValue(blockedCreatureCount, -2), new MultipliedValue(blockedCreatureCount, -1), Duration.EndOfTurn, true);
effect.setText("it gets -2/-1 until end of turn for each creature blocking it beyond the first");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public JohtullWurm(final JohtullWurm card) {
diff --git a/Mage.Sets/src/mage/cards/j/JolraelMwonvuliRecluse.java b/Mage.Sets/src/mage/cards/j/JolraelMwonvuliRecluse.java
new file mode 100644
index 00000000000..49e20864a8e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/j/JolraelMwonvuliRecluse.java
@@ -0,0 +1,54 @@
+package mage.cards.j;
+
+import mage.MageInt;
+import mage.abilities.common.DrawSecondCardTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.common.CardsInControllerHandCount;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.continuous.SetPowerToughnessAllEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.filter.StaticFilters;
+import mage.game.permanent.token.GreenCatToken2;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class JolraelMwonvuliRecluse extends CardImpl {
+
+ public JolraelMwonvuliRecluse(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.DRUID);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(2);
+
+ // Whenever you draw your second card each turn, create a 2/2 green Cat creature token.
+ this.addAbility(new DrawSecondCardTriggeredAbility(new CreateTokenEffect(new GreenCatToken2()), false));
+
+ // {4}{G}{G}: Until end of turn, creatures you control have base power and toughness X/X, where X is the number of cards in your hand.
+ this.addAbility(new SimpleActivatedAbility(new SetPowerToughnessAllEffect(
+ CardsInControllerHandCount.instance, CardsInControllerHandCount.instance,
+ Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES, true
+ ).setText("until end of turn, creatures you control have base power and toughness X/X, " +
+ "where X is the number of cards in your hand"), new ManaCostsImpl("{4}{G}{G}")));
+ }
+
+ private JolraelMwonvuliRecluse(final JolraelMwonvuliRecluse card) {
+ super(card);
+ }
+
+ @Override
+ public JolraelMwonvuliRecluse copy() {
+ return new JolraelMwonvuliRecluse(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java b/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java
index 3fa5faf6fd4..0107825f922 100644
--- a/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java
+++ b/Mage.Sets/src/mage/cards/j/JotunOwlKeeper.java
@@ -3,7 +3,7 @@ package mage.cards.j;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.OrCost;
import mage.constants.SubType;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -37,7 +37,7 @@ public final class JotunOwlKeeper extends CardImpl {
)));
// When Jötun Owl Keeper dies, put a 1/1 white Bird creature token with flying onto the battlefield for each age counter on it.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new BirdToken(), new CountersSourceCount(CounterType.AGE))));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new BirdToken(), new CountersSourceCount(CounterType.AGE))));
}
public JotunOwlKeeper(final JotunOwlKeeper card) {
diff --git a/Mage.Sets/src/mage/cards/j/Joust.java b/Mage.Sets/src/mage/cards/j/Joust.java
index cddf0ea93ac..77b8d33df29 100644
--- a/Mage.Sets/src/mage/cards/j/Joust.java
+++ b/Mage.Sets/src/mage/cards/j/Joust.java
@@ -76,7 +76,7 @@ class JoustEffect extends OneShotEffect {
if (creature2 == null) {
return true;
}
- game.applyEffects();
+ game.getState().processAction(game);
return creature1.fight(creature2, source, game);
}
}
diff --git a/Mage.Sets/src/mage/cards/j/JubilantSkybonder.java b/Mage.Sets/src/mage/cards/j/JubilantSkybonder.java
index 3c82fe7b3eb..ee0d7622b27 100644
--- a/Mage.Sets/src/mage/cards/j/JubilantSkybonder.java
+++ b/Mage.Sets/src/mage/cards/j/JubilantSkybonder.java
@@ -2,24 +2,19 @@ package mage.cards.j;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
+import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.AbilityPredicate;
-import mage.game.Game;
-import mage.target.Target;
-import mage.util.CardUtil;
-import java.util.Collection;
import java.util.UUID;
/**
@@ -46,10 +41,12 @@ public final class JubilantSkybonder extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Creatures you control with flying have "Spells your opponents cast that target this creature cost {2} more to cast."
- ContinuousEffect effect = new GainAbilityAllEffect(
- new SimpleStaticAbility(new JubilantSkybonderEffect()),
- Duration.WhileOnBattlefield, filter
- ).withForceQuotes();
+ Ability gainAbility = new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(2, new FilterCard("Spells"), TargetController.OPPONENT)
+ .withTargetName("this creature")
+ );
+
+ ContinuousEffect effect = new GainAbilityAllEffect(gainAbility, Duration.WhileOnBattlefield, filter).withForceQuotes();
effect.setDependedToType(DependencyType.AddingAbility);
this.addAbility(new SimpleStaticAbility(effect));
}
@@ -63,45 +60,3 @@ public final class JubilantSkybonder extends CardImpl {
return new JubilantSkybonder(this);
}
}
-
-class JubilantSkybonderEffect extends CostModificationEffectImpl {
-
- JubilantSkybonderEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Spells your opponents cast that target this creature cost {2} more to cast";
- }
-
- private JubilantSkybonderEffect(JubilantSkybonderEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (!(abilityToModify instanceof SpellAbility)
- || !game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- return false;
- }
- return abilityToModify
- .getModes()
- .getSelectedModes()
- .stream()
- .map(abilityToModify.getModes()::get)
- .map(Mode::getTargets)
- .flatMap(Collection::stream)
- .map(Target::getTargets)
- .flatMap(Collection::stream)
- .anyMatch(source.getSourceId()::equals);
- }
-
- @Override
- public JubilantSkybonderEffect copy() {
- return new JubilantSkybonderEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/j/JuganTheRisingStar.java b/Mage.Sets/src/mage/cards/j/JuganTheRisingStar.java
index e51b970247a..5e5531682b9 100644
--- a/Mage.Sets/src/mage/cards/j/JuganTheRisingStar.java
+++ b/Mage.Sets/src/mage/cards/j/JuganTheRisingStar.java
@@ -5,7 +5,7 @@ package mage.cards.j;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.DistributeCountersEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -33,7 +33,7 @@ public final class JuganTheRisingStar extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Jugan, the Rising Star dies, you may distribute five +1/+1 counters among any number of target creatures.
- Ability ability = new DiesTriggeredAbility(new DistributeCountersEffect(CounterType.P1P1, 5, false, "any number of target creatures"), true);
+ Ability ability = new DiesSourceTriggeredAbility(new DistributeCountersEffect(CounterType.P1P1, 5, false, "any number of target creatures"), true);
ability.addTarget(new TargetCreaturePermanentAmount(5));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/j/JundSojourners.java b/Mage.Sets/src/mage/cards/j/JundSojourners.java
index 8a57e5939fb..6c7964133e3 100644
--- a/Mage.Sets/src/mage/cards/j/JundSojourners.java
+++ b/Mage.Sets/src/mage/cards/j/JundSojourners.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.CycleTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.CyclingAbility;
@@ -34,7 +34,7 @@ public final class JundSojourners extends CardImpl {
// When you cycle Jund Sojourners or it dies, you may have it deal 1 damage to any target.
Ability ability1 = new CycleTriggeredAbility(new DamageTargetEffect(1));
- Ability ability2 = new DiesTriggeredAbility(new DamageTargetEffect(1));
+ Ability ability2 = new DiesSourceTriggeredAbility(new DamageTargetEffect(1));
ability1.addTarget(new TargetAnyTarget());
ability2.addTarget(new TargetAnyTarget());
this.addAbility(ability1);
diff --git a/Mage.Sets/src/mage/cards/j/JungleWurm.java b/Mage.Sets/src/mage/cards/j/JungleWurm.java
index abb6b248d6b..5d885826e73 100644
--- a/Mage.Sets/src/mage/cards/j/JungleWurm.java
+++ b/Mage.Sets/src/mage/cards/j/JungleWurm.java
@@ -3,7 +3,7 @@ package mage.cards.j;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.MultipliedValue;
import mage.abilities.dynamicvalue.common.BlockedCreatureCount;
@@ -32,7 +32,7 @@ public final class JungleWurm extends CardImpl {
DynamicValue value = new MultipliedValue(blockedCreatureCount, -1);
Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn, true);
effect.setText("it gets -1/-1 until end of turn for each creature blocking it beyond the first");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public JungleWurm(final JungleWurm card) {
diff --git a/Mage.Sets/src/mage/cards/j/JunkDiver.java b/Mage.Sets/src/mage/cards/j/JunkDiver.java
index f7b14942e34..9d5d731f6c7 100644
--- a/Mage.Sets/src/mage/cards/j/JunkDiver.java
+++ b/Mage.Sets/src/mage/cards/j/JunkDiver.java
@@ -4,7 +4,7 @@ package mage.cards.j;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.abilities.keyword.FlyingAbility;
@@ -40,7 +40,7 @@ public final class JunkDiver extends CardImpl {
// When Junk Diver dies, return another target artifact card from your graveyard to your hand.
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
effect.setText("return another target artifact card from your graveyard to your hand");
- Ability ability = new DiesTriggeredAbility(effect);
+ Ability ability = new DiesSourceTriggeredAbility(effect);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/k/KaervekTheSpiteful.java b/Mage.Sets/src/mage/cards/k/KaervekTheSpiteful.java
new file mode 100644
index 00000000000..493dd68b223
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/k/KaervekTheSpiteful.java
@@ -0,0 +1,43 @@
+package mage.cards.k;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.continuous.BoostAllEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class KaervekTheSpiteful extends CardImpl {
+
+ public KaervekTheSpiteful(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WARLOCK);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(2);
+
+ // Other creatures get -1/-1.
+ this.addAbility(new SimpleStaticAbility(new BoostAllEffect(
+ -1, -1, Duration.WhileOnBattlefield, true
+ )));
+ }
+
+ private KaervekTheSpiteful(final KaervekTheSpiteful card) {
+ super(card);
+ }
+
+ @Override
+ public KaervekTheSpiteful copy() {
+ return new KaervekTheSpiteful(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/k/KaerveksPurge.java b/Mage.Sets/src/mage/cards/k/KaerveksPurge.java
index 19b5c69c3ec..4eabe29bd99 100644
--- a/Mage.Sets/src/mage/cards/k/KaerveksPurge.java
+++ b/Mage.Sets/src/mage/cards/k/KaerveksPurge.java
@@ -78,7 +78,7 @@ class KaerveksPurgeEffect extends OneShotEffect {
// Destroy target creature with converted mana cost X.
Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
if (targetCreature != null && targetCreature.destroy(source.getSourceId(), game, false)) {
- game.applyEffects();
+ game.getState().processAction(game);
if (targetCreature.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(targetCreature.getId())
&& game.getState().getZone(targetCreature.getId()) != Zone.GRAVEYARD) {
// A replacement effect has moved the card to another zone as graveyard
diff --git a/Mage.Sets/src/mage/cards/k/KaerveksSpite.java b/Mage.Sets/src/mage/cards/k/KaerveksSpite.java
index f38414c79f4..fe2406d23e9 100644
--- a/Mage.Sets/src/mage/cards/k/KaerveksSpite.java
+++ b/Mage.Sets/src/mage/cards/k/KaerveksSpite.java
@@ -1,30 +1,34 @@
package mage.cards.k;
-import java.util.UUID;
import mage.abilities.costs.common.DiscardHandCost;
import mage.abilities.costs.common.SacrificeAllCost;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
+import mage.target.TargetPlayer;
+
+import java.util.UUID;
public final class KaerveksSpite extends CardImpl {
+ private static final FilterPermanent filter = new FilterControlledPermanent("permanents you control");
+
public KaerveksSpite(UUID ownerId, CardSetInfo cardSetInfo) {
super(ownerId, cardSetInfo, new CardType[]{CardType.INSTANT}, "{B}{B}{B}");
// As an additional cost to cast Kaervek's Spite, sacrifice all permanents you control and discard your hand.
- this.getSpellAbility().addCost(new SacrificeAllCost(new FilterControlledPermanent("permanents you control")));
+ this.getSpellAbility().addCost(new SacrificeAllCost(filter));
this.getSpellAbility().addCost(new DiscardHandCost());
- // Target player loses 5 life.
- Effect effect = new LoseLifeTargetEffect(5);
- this.getSpellAbility().addEffect(effect);
+ // Target player loses 5 life.=
+ this.getSpellAbility().addEffect(new LoseLifeTargetEffect(5));
+ this.getSpellAbility().addTarget(new TargetPlayer());
}
- public KaerveksSpite(final KaerveksSpite other) {
+ private KaerveksSpite(final KaerveksSpite other) {
super(other);
}
diff --git a/Mage.Sets/src/mage/cards/k/KaheeraTheOrphanguard.java b/Mage.Sets/src/mage/cards/k/KaheeraTheOrphanguard.java
index b43acab4f86..6f9386979ff 100644
--- a/Mage.Sets/src/mage/cards/k/KaheeraTheOrphanguard.java
+++ b/Mage.Sets/src/mage/cards/k/KaheeraTheOrphanguard.java
@@ -91,8 +91,8 @@ enum KaheeraTheOrphanguardCompanionCondition implements CompanionCondition {
SubType.BEAST
);
- private static final boolean checkTypes(Card card) {
- return subtypes.stream().anyMatch(card.getSubtype(null)::contains);
+ private static boolean checkTypes(Card card) {
+ return subtypes.stream().anyMatch(subtype -> card.hasSubtype(subtype, null));
}
@Override
diff --git a/Mage.Sets/src/mage/cards/k/KapshoKitefins.java b/Mage.Sets/src/mage/cards/k/KapshoKitefins.java
index db6aa7c954b..da025e429c2 100644
--- a/Mage.Sets/src/mage/cards/k/KapshoKitefins.java
+++ b/Mage.Sets/src/mage/cards/k/KapshoKitefins.java
@@ -1,37 +1,26 @@
-
package mage.cards.k;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.TargetController;
-import mage.constants.Zone;
-import mage.filter.common.FilterCreaturePermanent;
-import mage.target.common.TargetCreaturePermanent;
+import mage.filter.StaticFilters;
+import mage.target.common.TargetOpponentsCreaturePermanent;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class KapshoKitefins extends CardImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("{this} or another creature");
- private static final FilterCreaturePermanent filterTarget = new FilterCreaturePermanent("creature an opponent controls");
-
- static {
- filter.add(TargetController.YOU.getControllerPredicate());
- filterTarget.add(TargetController.OPPONENT.getControllerPredicate());
- }
-
public KapshoKitefins(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
this.subtype.add(SubType.FISH);
this.color.setBlue(true);
@@ -40,14 +29,16 @@ public final class KapshoKitefins extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
- // Whenever Kapsho Kitefins or another creature enters the battlefield under your control, tap target creature an opponent controls.
- Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new TapTargetEffect(), filter, false);
- ability.addTarget(new TargetCreaturePermanent(filterTarget));
- this.addAbility(ability);
+ // Whenever Kapsho Kitefins or another creature enters the battlefield under your control, tap target creature an opponent controls.
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new TapTargetEffect(), StaticFilters.FILTER_PERMANENT_CREATURE, false, true
+ );
+ ability.addTarget(new TargetOpponentsCreaturePermanent());
+ this.addAbility(ability);
}
- public KapshoKitefins(final KapshoKitefins card) {
+ private KapshoKitefins(final KapshoKitefins card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java b/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java
index b5ac0e5a96d..f5345fe00d1 100644
--- a/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java
+++ b/Mage.Sets/src/mage/cards/k/KaradorGhostChieftain.java
@@ -38,7 +38,7 @@ public final class KaradorGhostChieftain extends CardImpl {
this.toughness = new MageInt(4);
// Karador, Ghost Chieftain costs {1} less to cast for each creature card in your graveyard.
- this.addAbility(new SimpleStaticAbility(Zone.STACK,
+ this.addAbility(new SimpleStaticAbility(Zone.ALL,
new KaradorGhostChieftainCostReductionEffect()));
// During each of your turns, you may cast one creature card from your graveyard.
diff --git a/Mage.Sets/src/mage/cards/k/KarnScionOfUrza.java b/Mage.Sets/src/mage/cards/k/KarnScionOfUrza.java
index b42cf9d6049..db1fcbb798e 100644
--- a/Mage.Sets/src/mage/cards/k/KarnScionOfUrza.java
+++ b/Mage.Sets/src/mage/cards/k/KarnScionOfUrza.java
@@ -6,6 +6,7 @@ import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.*;
import mage.constants.*;
import mage.counters.CounterType;
@@ -19,7 +20,6 @@ import mage.target.Target;
import mage.target.TargetCard;
import mage.target.common.TargetOpponent;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@@ -46,6 +46,7 @@ public final class KarnScionOfUrza extends CardImpl {
// -2: Create a 0/0 colorless Construct artifact creature token with "This creature gets +1/+1 for each artifact you control."
LoyaltyAbility ability3 = new LoyaltyAbility(new KarnConstructEffect(), -2);
+ ability3.addHint(ArtifactYouControlHint.instance);
this.addAbility(ability3);
}
diff --git a/Mage.Sets/src/mage/cards/k/KarnSilverGolem.java b/Mage.Sets/src/mage/cards/k/KarnSilverGolem.java
index 57e69f971b7..141991d4e4f 100644
--- a/Mage.Sets/src/mage/cards/k/KarnSilverGolem.java
+++ b/Mage.Sets/src/mage/cards/k/KarnSilverGolem.java
@@ -4,7 +4,7 @@ package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffectImpl;
@@ -38,7 +38,7 @@ public final class KarnSilverGolem extends CardImpl {
this.toughness = new MageInt(4);
// Whenever Karn, Silver Golem blocks or becomes blocked, it gets -4/+4 until end of turn.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(-4, +4, Duration.EndOfTurn), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(-4, +4, Duration.EndOfTurn), false));
// {1}: Target noncreature artifact becomes an artifact creature with power and toughness each equal to its converted mana cost until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new KarnSilverGolemEffect(), new ManaCostsImpl("{1"));
diff --git a/Mage.Sets/src/mage/cards/k/KarplusanHound.java b/Mage.Sets/src/mage/cards/k/KarplusanHound.java
index 1d0077baa7b..62149c4f00b 100644
--- a/Mage.Sets/src/mage/cards/k/KarplusanHound.java
+++ b/Mage.Sets/src/mage/cards/k/KarplusanHound.java
@@ -24,7 +24,7 @@ public final class KarplusanHound extends CardImpl {
public KarplusanHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent("a Chandra planeswalker");
diff --git a/Mage.Sets/src/mage/cards/k/KarplusanWolverine.java b/Mage.Sets/src/mage/cards/k/KarplusanWolverine.java
index daa070e71a0..d6e8cec8d39 100644
--- a/Mage.Sets/src/mage/cards/k/KarplusanWolverine.java
+++ b/Mage.Sets/src/mage/cards/k/KarplusanWolverine.java
@@ -4,7 +4,7 @@ package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -28,7 +28,7 @@ public final class KarplusanWolverine extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Karplusan Wolverine becomes blocked, you may have it deal 1 damage to any target.
- Ability ability = new BecomesBlockedTriggeredAbility(new DamageTargetEffect(1), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new DamageTargetEffect(1), true);
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/k/KeenGlidemaster.java b/Mage.Sets/src/mage/cards/k/KeenGlidemaster.java
new file mode 100644
index 00000000000..9205f839289
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/k/KeenGlidemaster.java
@@ -0,0 +1,47 @@
+package mage.cards.k;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class KeenGlidemaster extends CardImpl {
+
+ public KeenGlidemaster(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.SOLDIER);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // {2}{U}: Target creature gains flying until end of turn.
+ Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(
+ FlyingAbility.getInstance(), Duration.EndOfTurn
+ ), new ManaCostsImpl("{2}{U}"));
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ }
+
+ private KeenGlidemaster(final KeenGlidemaster card) {
+ super(card);
+ }
+
+ @Override
+ public KeenGlidemaster copy() {
+ return new KeenGlidemaster(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/k/KeeningStone.java b/Mage.Sets/src/mage/cards/k/KeeningStone.java
index 9ed4d7fbec9..11a4de0547c 100644
--- a/Mage.Sets/src/mage/cards/k/KeeningStone.java
+++ b/Mage.Sets/src/mage/cards/k/KeeningStone.java
@@ -1,7 +1,6 @@
package mage.cards.k;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@@ -11,22 +10,22 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class KeeningStone extends CardImpl {
public KeeningStone(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}");
// {5}, {tap}: Target player puts the top X cards of their library into their graveyard, where X is the number of cards in that player's graveyard.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new KeeningStoneEffect(), new GenericManaCost(5));
+ Ability ability = new SimpleActivatedAbility(new KeeningStoneEffect(), new GenericManaCost(5));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
@@ -46,7 +45,7 @@ class KeeningStoneEffect extends OneShotEffect {
public KeeningStoneEffect() {
super(Outcome.Neutral);
- this.staticText = "Target player puts the top X cards of their library into their graveyard, where X is the number of cards in that player's graveyard";
+ this.staticText = "Target player mills X cards, where X is the number of cards in that player's graveyard";
}
public KeeningStoneEffect(final KeeningStoneEffect effect) {
@@ -62,7 +61,7 @@ class KeeningStoneEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getFirstTarget());
if (player != null) {
- player.moveCards(player.getLibrary().getTopCards(game, player.getGraveyard().size()), Zone.GRAVEYARD, source, game);
+ player.millCards(player.getGraveyard().size(), source, game);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/k/KeigaTheTideStar.java b/Mage.Sets/src/mage/cards/k/KeigaTheTideStar.java
index 3ba20234cce..6559e0b608b 100644
--- a/Mage.Sets/src/mage/cards/k/KeigaTheTideStar.java
+++ b/Mage.Sets/src/mage/cards/k/KeigaTheTideStar.java
@@ -5,7 +5,7 @@ package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -34,7 +34,7 @@ public final class KeigaTheTideStar extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Keiga, the Tide Star dies, gain control of target creature.
- Ability ability = new DiesTriggeredAbility(new GainControlTargetEffect(Duration.Custom));
+ Ability ability = new DiesSourceTriggeredAbility(new GainControlTargetEffect(Duration.Custom));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/k/KelsFightFixer.java b/Mage.Sets/src/mage/cards/k/KelsFightFixer.java
new file mode 100644
index 00000000000..3762736bc88
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/k/KelsFightFixer.java
@@ -0,0 +1,94 @@
+package mage.cards.k;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.SacrificeTargetCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.IndestructibleAbility;
+import mage.abilities.keyword.MenaceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.target.common.TargetControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class KelsFightFixer extends CardImpl {
+
+ public KelsFightFixer(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.AZRA);
+ this.subtype.add(SubType.WARLOCK);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(3);
+
+ // Menace
+ this.addAbility(new MenaceAbility());
+
+ // Whenever you sacrifice a creature, you may pay {U/B}. If you do, draw a card.
+ this.addAbility(new KelsFightFixerTriggeredAbility());
+
+ // {1}, Sacrifice a creature: Kels, Fight Fixer gains indestructible until end of turn.
+ Ability ability = new SimpleActivatedAbility(new GainAbilitySourceEffect(
+ IndestructibleAbility.getInstance(), Duration.EndOfTurn
+ ), new GenericManaCost(1));
+ ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT)));
+ this.addAbility(ability);
+ }
+
+ private KelsFightFixer(final KelsFightFixer card) {
+ super(card);
+ }
+
+ @Override
+ public KelsFightFixer copy() {
+ return new KelsFightFixer(this);
+ }
+}
+
+class KelsFightFixerTriggeredAbility extends TriggeredAbilityImpl {
+
+ KelsFightFixerTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{U/B}")), false);
+ setLeavesTheBattlefieldTrigger(true);
+ }
+
+ private KelsFightFixerTriggeredAbility(final KelsFightFixerTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public KelsFightFixerTriggeredAbility copy() {
+ return new KelsFightFixerTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.SACRIFICED_PERMANENT;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ return event.getPlayerId().equals(this.getControllerId())
+ && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).isCreature();
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever you sacrifice a creature, " + super.getRule();
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/k/KeralKeepDisciples.java b/Mage.Sets/src/mage/cards/k/KeralKeepDisciples.java
new file mode 100644
index 00000000000..83fbcf75b19
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/k/KeralKeepDisciples.java
@@ -0,0 +1,40 @@
+package mage.cards.k;
+
+import mage.MageInt;
+import mage.abilities.common.ActivatePlaneswalkerLoyaltyAbilityTriggeredAbility;
+import mage.abilities.effects.common.DamagePlayersEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class KeralKeepDisciples extends CardImpl {
+
+ public KeralKeepDisciples(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.MONK);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(3);
+
+ // Whenever you activate a loyalty ability of a Chandra planeswalker, Keral Keep Disciples deals 1 damage to each opponent.
+ this.addAbility(new ActivatePlaneswalkerLoyaltyAbilityTriggeredAbility(new DamagePlayersEffect(1, TargetController.OPPONENT), SubType.CHANDRA));
+ }
+
+ private KeralKeepDisciples(final KeralKeepDisciples card) {
+ super(card);
+ }
+
+ @Override
+ public KeralKeepDisciples copy() {
+ return new KeralKeepDisciples(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java
index c8ffa6637f8..13f65fe9018 100644
--- a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java
+++ b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java
@@ -6,7 +6,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -36,7 +36,7 @@ public final class KessigForgemaster extends CardImpl {
this.secondSideCardClazz = mage.cards.f.FlameheartWerewolf.class;
// Whenever Kessig Forgemaster blocks or becomes blocked by a creature, Kessig Forgemaster deals 1 damage to that creature.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new DamageTargetEffect(1, true, "that creature"),
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new DamageTargetEffect(1, true, "that creature"),
StaticFilters.FILTER_PERMANENT_CREATURE, false, null, true));
// At the beginning of each upkeep, if no spells were cast last turn, transform Kessig Forgemaster.
diff --git a/Mage.Sets/src/mage/cards/k/KeyToTheCity.java b/Mage.Sets/src/mage/cards/k/KeyToTheCity.java
index 1fce751780a..909321cf6cb 100644
--- a/Mage.Sets/src/mage/cards/k/KeyToTheCity.java
+++ b/Mage.Sets/src/mage/cards/k/KeyToTheCity.java
@@ -1,9 +1,6 @@
-
package mage.cards.k;
-import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.DiscardCardCost;
import mage.abilities.costs.common.TapSourceCost;
@@ -11,35 +8,35 @@ import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect;
+import mage.abilities.keyword.InspiredAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Zone;
-import mage.game.Game;
-import mage.game.events.GameEvent;
-import mage.game.events.GameEvent.EventType;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class KeyToTheCity extends CardImpl {
public KeyToTheCity(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// {T}, Discard a card: Up to one target creature can't be blocked this turn.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedTargetEffect(), new TapSourceCost());
+ Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new TapSourceCost());
ability.addCost(new DiscardCardCost());
ability.addTarget(new TargetCreaturePermanent(0, 1));
this.addAbility(ability);
// Whenever Key to the City becomes untapped, you may pay {2}. If you do, draw a card.
- this.addAbility(new KeyToTheCityTriggeredAbility());
+ this.addAbility(new InspiredAbility(new DoIfCostPaid(
+ new DrawCardSourceControllerEffect(1), new GenericManaCost(2)
+ ), false, false));
}
- public KeyToTheCity(final KeyToTheCity card) {
+ private KeyToTheCity(final KeyToTheCity card) {
super(card);
}
@@ -48,35 +45,3 @@ public final class KeyToTheCity extends CardImpl {
return new KeyToTheCity(this);
}
}
-
-class KeyToTheCityTriggeredAbility extends TriggeredAbilityImpl{
-
- KeyToTheCityTriggeredAbility() {
- super(Zone.BATTLEFIELD, new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new GenericManaCost(2)));
- }
-
- KeyToTheCityTriggeredAbility(final KeyToTheCityTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public KeyToTheCityTriggeredAbility copy() {
- return new KeyToTheCityTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == EventType.UNTAPPED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getTargetId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "Whenever Key to the City becomes untapped, you may pay {2}. If you do, draw a card.";
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/k/KhalniHydra.java b/Mage.Sets/src/mage/cards/k/KhalniHydra.java
index 0421a15082d..f37225ddcfb 100644
--- a/Mage.Sets/src/mage/cards/k/KhalniHydra.java
+++ b/Mage.Sets/src/mage/cards/k/KhalniHydra.java
@@ -1,45 +1,53 @@
-
package mage.cards.k;
-import java.util.Iterator;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCost;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.costs.mana.ManaCosts;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
-import mage.game.Game;
+
+import java.util.UUID;
/**
- *
* @author maurer.it_at_gmail.com
*/
public final class KhalniHydra extends CardImpl {
- private static final FilterControlledCreaturePermanent filter;
+ private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("green creature you control");
static {
- filter = new FilterControlledCreaturePermanent();
filter.add(new ColorPredicate(ObjectColor.GREEN));
}
public KhalniHydra(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{G}{G}{G}{G}{G}{G}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}{G}{G}{G}{G}{G}{G}");
this.subtype.add(SubType.HYDRA);
this.power = new MageInt(8);
this.toughness = new MageInt(8);
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new KhalniHydraCostReductionEffect()));
+
+ // This spell costs {G} less to cast for each green creature you control.
+ ManaCosts manaReduce = new ManaCostsImpl<>("{G}");
+ DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
+ this.addAbility(new SimpleStaticAbility(Zone.ALL,
+ new SpellCostReductionForEachSourceEffect(manaReduce, xValue))
+ .addHint(new ValueHint("Green creature you control", xValue))
+ );
+
+ // Trample
this.addAbility(TrampleAbility.getInstance());
}
@@ -47,47 +55,8 @@ public final class KhalniHydra extends CardImpl {
super(card);
}
- @Override
- public void adjustCosts(Ability ability, Game game) {
- super.adjustCosts(ability, game);
- int reductionAmount = game.getBattlefield().count(filter, ability.getSourceId(), ability.getControllerId(), game);
- Iterator iter = ability.getManaCostsToPay().iterator();
-
- while ( reductionAmount > 0 && iter.hasNext() ) {
- ManaCost manaCost = iter.next();
- if (manaCost.getMana().getGreen() > 0) { // in case another effect adds additional mana cost
- iter.remove();
- reductionAmount--;
- }
- }
- }
-
@Override
public KhalniHydra copy() {
return new KhalniHydra(this);
}
}
-
-class KhalniHydraCostReductionEffect extends OneShotEffect {
- private static final String effectText = "{this} costs {G} less to cast for each green creature you control";
-
- KhalniHydraCostReductionEffect ( ) {
- super(Outcome.Benefit);
- this.staticText = effectText;
- }
-
- KhalniHydraCostReductionEffect ( KhalniHydraCostReductionEffect effect ) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return false;
- }
-
- @Override
- public KhalniHydraCostReductionEffect copy() {
- return new KhalniHydraCostReductionEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java b/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java
index f6779f259af..7a53d2f08e2 100644
--- a/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java
+++ b/Mage.Sets/src/mage/cards/k/KheruSpellsnatcher.java
@@ -5,8 +5,6 @@ import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.AsThoughEffectImpl;
-import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.MorphAbility;
import mage.cards.Card;
@@ -14,14 +12,11 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
-import mage.game.stack.Spell;
import mage.game.stack.StackObject;
-import mage.players.Player;
import mage.target.TargetSpell;
-import mage.target.targetpointer.FixedTarget;
-import mage.util.CardUtil;
import java.util.UUID;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
/**
* @author emerald000
@@ -59,7 +54,9 @@ class KheruSpellsnatcherEffect extends OneShotEffect {
KheruSpellsnatcherEffect() {
super(Outcome.Benefit);
- this.staticText = "counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. You may cast that card without paying its mana cost as long as it remains exiled";
+ this.staticText = "counter target spell. If that spell is countered this way, "
+ + "exile it instead of putting it into its owner's graveyard. "
+ + "You may cast that card without paying its mana cost as long as it remains exiled";
}
KheruSpellsnatcherEffect(final KheruSpellsnatcherEffect effect) {
@@ -73,68 +70,14 @@ class KheruSpellsnatcherEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- UUID objectId = targetPointer.getFirst(game, source);
- UUID sourceId = source.getSourceId();
-
- StackObject stackObject = game.getStack().getStackObject(objectId);
- if (stackObject != null
+ MageObject sourceObject = source.getSourceObject(game);
+ StackObject stackObject = game.getStack().getStackObject(targetPointer.getFirst(game, source));
+ if (stackObject != null && sourceObject != null
&& game.getStack().counter(targetPointer.getFirst(game, source), source.getSourceId(), game, Zone.EXILED, false, ZoneDetail.NONE)) {
if (!stackObject.isCopy()) {
MageObject card = game.getObject(stackObject.getSourceId());
- if (card instanceof Card) {
- UUID exileId = CardUtil.getCardExileZoneId(game, sourceId);
- ((Card) card).moveToExile(exileId, "Kheru Spellsnatcher - cast without mana cost", sourceId, game);
- ContinuousEffect effect = new KheruSpellsnatcherCastFromExileEffect();
- effect.setTargetPointer(new FixedTarget(card.getId()));
- game.addEffect(effect, source);
- }
- }
- return true;
- }
- return false;
- }
-}
-
-class KheruSpellsnatcherCastFromExileEffect extends AsThoughEffectImpl {
-
- KheruSpellsnatcherCastFromExileEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
- staticText = "You may cast that card without paying its mana cost as long as it remains exiled";
- }
-
- KheruSpellsnatcherCastFromExileEffect(final KheruSpellsnatcherCastFromExileEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public KheruSpellsnatcherCastFromExileEffect copy() {
- return new KheruSpellsnatcherCastFromExileEffect(this);
- }
-
- @Override
- public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
- if (affectedControllerId.equals(source.getControllerId())) {
- if (getTargetPointer().getFirst(game, source) == null) {
- this.discard();
- return false;
- }
- if (sourceId.equals(getTargetPointer().getFirst(game, source))) {
- Card card = game.getCard(sourceId);
- if (card != null) {
- if (game.getState().getZone(sourceId) == Zone.EXILED) {
- Player player = game.getPlayer(affectedControllerId);
- if(player != null) {
- player.setCastSourceIdWithAlternateMana(sourceId, null, card.getSpellAbility().getCosts());
- return true;
- }
- } else {
- this.discard();
- }
+ if (card instanceof Card) {
+ return PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(game, source, (Card)card, TargetController.YOU, Duration.Custom, true);
}
}
}
diff --git a/Mage.Sets/src/mage/cards/k/KineticAugur.java b/Mage.Sets/src/mage/cards/k/KineticAugur.java
new file mode 100644
index 00000000000..458110b550d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/k/KineticAugur.java
@@ -0,0 +1,91 @@
+package mage.cards.k;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.SetPowerSourceEffect;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
+import mage.constants.*;
+import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
+import mage.filter.common.FilterInstantOrSorceryCard;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetDiscard;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class KineticAugur extends CardImpl {
+
+ private static final FilterCard filter = new FilterInstantOrSorceryCard("instant and sorcery cards");
+ private static final DynamicValue xValue = new CardsInControllerGraveyardCount(filter);
+
+ public KineticAugur(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.SHAMAN);
+ this.power = new MageInt(0);
+ this.toughness = new MageInt(4);
+
+ // Trample
+ this.addAbility(TrampleAbility.getInstance());
+
+ // Kinetic Augur's power is equal to the number of instant and sorcery cards in your graveyard.
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerSourceEffect(xValue, Duration.EndOfGame)));
+
+ // When Kinetic Augur enters the battlefield, discard up to two cards, then draw that many cards.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new KineticAugurEffect()));
+ }
+
+ private KineticAugur(final KineticAugur card) {
+ super(card);
+ }
+
+ @Override
+ public KineticAugur copy() {
+ return new KineticAugur(this);
+ }
+}
+
+class KineticAugurEffect extends OneShotEffect {
+
+ KineticAugurEffect() {
+ super(Outcome.Benefit);
+ staticText = "discard up to two cards, then draw that many cards";
+ }
+
+ private KineticAugurEffect(final KineticAugurEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public KineticAugurEffect copy() {
+ return new KineticAugurEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null || player.getHand().isEmpty()) {
+ return false;
+ }
+ TargetDiscard target = new TargetDiscard(0, 2, StaticFilters.FILTER_CARD, player.getId());
+ player.choose(Outcome.AIDontUseIt, player.getHand(), target, game);
+ int discarded = player.discard(new CardsImpl(target.getTargets()), source, game).size();
+ if (discarded > 0) {
+ player.drawCards(discarded, source.getSourceId(), game);
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/k/Kingfisher.java b/Mage.Sets/src/mage/cards/k/Kingfisher.java
index 1144f22229e..92ec2a993fe 100644
--- a/Mage.Sets/src/mage/cards/k/Kingfisher.java
+++ b/Mage.Sets/src/mage/cards/k/Kingfisher.java
@@ -3,7 +3,7 @@ package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -26,7 +26,7 @@ public final class Kingfisher extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Kingfisher dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public Kingfisher(final Kingfisher card) {
diff --git a/Mage.Sets/src/mage/cards/k/KinsbaileBorderguard.java b/Mage.Sets/src/mage/cards/k/KinsbaileBorderguard.java
index d8134ac4387..97feb48727f 100644
--- a/Mage.Sets/src/mage/cards/k/KinsbaileBorderguard.java
+++ b/Mage.Sets/src/mage/cards/k/KinsbaileBorderguard.java
@@ -4,7 +4,7 @@ package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
@@ -45,7 +45,7 @@ public final class KinsbaileBorderguard extends CardImpl {
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(0),
new PermanentsOnBattlefieldCount(filter), true), "with a +1/+1 counter on it for each other Kithkin you control"));
// When Kinsbaile Borderguard dies, create a 1/1 white Kithkin Soldier creature token for each counter on it.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new KithkinToken(), new AllCountersCount())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new KithkinToken(), new AllCountersCount())));
}
public KinsbaileBorderguard(final KinsbaileBorderguard card) {
diff --git a/Mage.Sets/src/mage/cards/k/KnollspineDragon.java b/Mage.Sets/src/mage/cards/k/KnollspineDragon.java
index 6b85accd453..63395447f9d 100644
--- a/Mage.Sets/src/mage/cards/k/KnollspineDragon.java
+++ b/Mage.Sets/src/mage/cards/k/KnollspineDragon.java
@@ -72,11 +72,10 @@ class KnollspineDragonEffect extends OneShotEffect {
if (watcher != null) {
int drawAmount = watcher.getAmountOfDamageReceivedThisTurn(targetOpponent.getId());
controller.drawCards(drawAmount, source.getSourceId(), game);
- game.informPlayers(controller.getLogName() + "draws " + drawAmount + " cards");
return true;
}
}
- game.informPlayers(controller.getLogName() + "drew no cards");
+ game.informPlayers(controller.getLogName() + " drew no cards");
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/k/KokushoTheEveningStar.java b/Mage.Sets/src/mage/cards/k/KokushoTheEveningStar.java
index 0336c4a7295..c1881be2aa1 100644
--- a/Mage.Sets/src/mage/cards/k/KokushoTheEveningStar.java
+++ b/Mage.Sets/src/mage/cards/k/KokushoTheEveningStar.java
@@ -5,7 +5,7 @@ package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -30,7 +30,7 @@ public final class KokushoTheEveningStar extends CardImpl {
this.power = new MageInt(5);
this.toughness = new MageInt(5);
this.addAbility(FlyingAbility.getInstance());
- this.addAbility(new DiesTriggeredAbility(new KokushoTheEveningStarEffect(), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new KokushoTheEveningStarEffect(), false));
}
public KokushoTheEveningStar(final KokushoTheEveningStar card) {
diff --git a/Mage.Sets/src/mage/cards/k/KraulHarpooner.java b/Mage.Sets/src/mage/cards/k/KraulHarpooner.java
index 13c16e28cb3..dbb43938a53 100644
--- a/Mage.Sets/src/mage/cards/k/KraulHarpooner.java
+++ b/Mage.Sets/src/mage/cards/k/KraulHarpooner.java
@@ -95,7 +95,7 @@ class KraulHarpoonerEffect extends OneShotEffect {
}
int xValue = player.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game);
game.addEffect(new BoostSourceEffect(xValue, 0, Duration.EndOfTurn), source);
- game.applyEffects();
+ game.getState().processAction(game);
Permanent creature = game.getPermanent(source.getFirstTarget());
if (creature == null || !player.chooseUse(outcome, "Have " + sourcePerm.getLogName() + " fight " + creature.getLogName() + "?", source, game)) {
return true;
diff --git a/Mage.Sets/src/mage/cards/k/KrenkoTinStreetKingpin.java b/Mage.Sets/src/mage/cards/k/KrenkoTinStreetKingpin.java
index 7ba8079a32a..10b4d902e58 100644
--- a/Mage.Sets/src/mage/cards/k/KrenkoTinStreetKingpin.java
+++ b/Mage.Sets/src/mage/cards/k/KrenkoTinStreetKingpin.java
@@ -70,7 +70,7 @@ class KrenkoTinStreetKingpinEffect extends OneShotEffect {
return false;
}
new AddCountersSourceEffect(CounterType.P1P1.createInstance()).apply(game, source);
- game.applyEffects();
+ game.getState().processAction(game);
int xValue = permanent.getPower().getValue();
return new CreateTokenEffect(new GoblinToken("WAR"), xValue).apply(game, source);
}
diff --git a/Mage.Sets/src/mage/cards/k/KrosanReclamation.java b/Mage.Sets/src/mage/cards/k/KrosanReclamation.java
index 73e848177cb..671b1144082 100644
--- a/Mage.Sets/src/mage/cards/k/KrosanReclamation.java
+++ b/Mage.Sets/src/mage/cards/k/KrosanReclamation.java
@@ -1,7 +1,6 @@
package mage.cards.k;
-import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -10,6 +9,7 @@ import mage.abilities.keyword.FlashbackAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TimingRule;
@@ -66,24 +66,9 @@ class KrosanReclamationEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getFirstTarget());
- if (player != null) {
- List targets = source.getTargets().get(1).getTargets();
- boolean shuffle = false;
- for (UUID targetId : targets) {
- Card card = game.getCard(targetId);
- if (card != null) {
- if (player.getGraveyard().contains(card.getId())) {
- player.getGraveyard().remove(card);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- shuffle = true;
- }
- }
- }
- if (shuffle) {
- player.shuffleLibrary(source, game);
- }
- return true;
+ Player targetPlayer = game.getPlayer(source.getFirstTarget());
+ if (targetPlayer != null) {
+ return targetPlayer.shuffleCardsToLibrary(new CardsImpl(source.getTargets().get(1).getTargets()), game, source);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/k/KumanoMasterYamabushi.java b/Mage.Sets/src/mage/cards/k/KumanoMasterYamabushi.java
index 371a716cbfe..a833e83fdbb 100644
--- a/Mage.Sets/src/mage/cards/k/KumanoMasterYamabushi.java
+++ b/Mage.Sets/src/mage/cards/k/KumanoMasterYamabushi.java
@@ -1,5 +1,5 @@
/*
- *
+ *
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
@@ -25,12 +25,11 @@
* 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.cards.k;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -40,21 +39,19 @@ import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.replacement.DealtDamageToCreatureBySourceDies;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Duration;
-import mage.constants.SuperType;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.target.common.TargetAnyTarget;
import mage.watchers.common.DamagedByWatcher;
+import java.util.UUID;
+
/**
* @author LevelX
*/
public final class KumanoMasterYamabushi extends CardImpl {
public KumanoMasterYamabushi(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SHAMAN);
@@ -62,13 +59,13 @@ public final class KumanoMasterYamabushi extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
- // {{1}{R}: Kumano, Master Yamabushi deals 1 damage to any target.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{1}{R}") );
+ // {1}{R}: Kumano, Master Yamabushi deals 1 damage to any target.
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{1}{R}"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
// If a creature dealt damage by Kumano this turn would die, exile it instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DealtDamageToCreatureBySourceDies(this, Duration.WhileOnBattlefield)), new DamagedByWatcher(false));
-
+
}
public KumanoMasterYamabushi(final KumanoMasterYamabushi card) {
diff --git a/Mage.Sets/src/mage/cards/k/KunorosHoundOfAthreos.java b/Mage.Sets/src/mage/cards/k/KunorosHoundOfAthreos.java
index fe8e6d8b153..f6eddc8ae6f 100644
--- a/Mage.Sets/src/mage/cards/k/KunorosHoundOfAthreos.java
+++ b/Mage.Sets/src/mage/cards/k/KunorosHoundOfAthreos.java
@@ -26,7 +26,7 @@ public final class KunorosHoundOfAthreos extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{B}");
this.addSuperType(SuperType.LEGENDARY);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/l/LaboratoryManiac.java b/Mage.Sets/src/mage/cards/l/LaboratoryManiac.java
index c01a0e7681b..7c372edebec 100644
--- a/Mage.Sets/src/mage/cards/l/LaboratoryManiac.java
+++ b/Mage.Sets/src/mage/cards/l/LaboratoryManiac.java
@@ -79,14 +79,14 @@ class LaboratoryManiacEffect extends ReplacementEffectImpl {
@Override
public boolean checksEventType(GameEvent event, Game game) {
- return event.getType() == EventType.EMPTY_DRAW;
+ return event.getType() == EventType.DRAW_CARD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getPlayerId().equals(source.getControllerId())) {
Player player = game.getPlayer(event.getPlayerId());
- if (player != null && !player.hasLost() && player.isEmptyDraw()) {
+ if (player != null && !player.hasLost() && !player.getLibrary().hasCards()) {
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/l/LaccolithGrunt.java b/Mage.Sets/src/mage/cards/l/LaccolithGrunt.java
index 6c0570f65a3..98c271a2e8f 100644
--- a/Mage.Sets/src/mage/cards/l/LaccolithGrunt.java
+++ b/Mage.Sets/src/mage/cards/l/LaccolithGrunt.java
@@ -4,7 +4,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.cards.CardImpl;
@@ -32,7 +32,7 @@ public final class LaccolithGrunt extends CardImpl {
this.toughness = new MageInt(2);
// Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn.
- Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/l/LaccolithTitan.java b/Mage.Sets/src/mage/cards/l/LaccolithTitan.java
index 2af5b5a8e35..886255e887d 100644
--- a/Mage.Sets/src/mage/cards/l/LaccolithTitan.java
+++ b/Mage.Sets/src/mage/cards/l/LaccolithTitan.java
@@ -4,7 +4,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.cards.CardImpl;
@@ -32,7 +32,7 @@ public final class LaccolithTitan extends CardImpl {
this.toughness = new MageInt(6);
// Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn.
- Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/l/LaccolithWarrior.java b/Mage.Sets/src/mage/cards/l/LaccolithWarrior.java
index 435b53cb719..cb65c938df2 100644
--- a/Mage.Sets/src/mage/cards/l/LaccolithWarrior.java
+++ b/Mage.Sets/src/mage/cards/l/LaccolithWarrior.java
@@ -4,7 +4,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.cards.CardImpl;
@@ -33,7 +33,7 @@ public final class LaccolithWarrior extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn.
- Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/l/LaccolithWhelp.java b/Mage.Sets/src/mage/cards/l/LaccolithWhelp.java
index 19472a6399e..fe6d96c22a9 100644
--- a/Mage.Sets/src/mage/cards/l/LaccolithWhelp.java
+++ b/Mage.Sets/src/mage/cards/l/LaccolithWhelp.java
@@ -4,7 +4,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.cards.CardImpl;
@@ -32,7 +32,7 @@ public final class LaccolithWhelp extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn.
- Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
+ Ability ability = new BecomesBlockedSourceTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/l/LammastideWeave.java b/Mage.Sets/src/mage/cards/l/LammastideWeave.java
index 9cd195c43b9..fc9365efdbc 100644
--- a/Mage.Sets/src/mage/cards/l/LammastideWeave.java
+++ b/Mage.Sets/src/mage/cards/l/LammastideWeave.java
@@ -9,7 +9,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
@@ -35,7 +34,7 @@ public final class LammastideWeave extends CardImpl {
}
- public LammastideWeave(final LammastideWeave card) {
+ private LammastideWeave(final LammastideWeave card) {
super(card);
}
@@ -47,13 +46,13 @@ public final class LammastideWeave extends CardImpl {
class LammastideWeaveEffect extends OneShotEffect {
- public LammastideWeaveEffect() {
+ LammastideWeaveEffect() {
super(Outcome.DrawCard);
- this.staticText = ", then target player puts the top card of their library into their graveyard. "
- + "If that card has the chosen name, you gain life equal to its converted mana cost.";
+ this.staticText = ", then target player mills a card. If a card with the chosen name was milled this way, " +
+ "you gain life equal to its converted mana cost.";
}
- public LammastideWeaveEffect(final LammastideWeaveEffect effect) {
+ private LammastideWeaveEffect(final LammastideWeaveEffect effect) {
super(effect);
}
@@ -67,17 +66,14 @@ class LammastideWeaveEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) {
- Card card = targetPlayer.getLibrary().getFromTop(game);
- if (card != null) {
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
- controller.gainLife(card.getConvertedManaCost(), game, source);
- }
- }
- return true;
+ if (controller == null || targetPlayer == null || cardName == null || cardName.isEmpty()) {
+ return false;
}
- return false;
+ for (Card card : targetPlayer.millCards(1, source, game).getCards(game)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
+ controller.gainLife(card.getConvertedManaCost(), game, source);
+ }
+ }
+ return true;
}
-
}
diff --git a/Mage.Sets/src/mage/cards/l/LastRites.java b/Mage.Sets/src/mage/cards/l/LastRites.java
index 7cb78edc19a..81d3dcb06b9 100644
--- a/Mage.Sets/src/mage/cards/l/LastRites.java
+++ b/Mage.Sets/src/mage/cards/l/LastRites.java
@@ -1,29 +1,30 @@
package mage.cards.l;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
-import mage.constants.Zone;
import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
+import mage.target.common.TargetDiscard;
import mage.target.targetpointer.FixedTarget;
+import java.util.UUID;
+
/**
- *
* @author L_J
*/
public final class LastRites extends CardImpl {
@@ -32,14 +33,13 @@ public final class LastRites extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
// Discard any number of cards. Target player reveals their hand, then
- //you choose a nonland card from it for each card discarded
+ // you choose a nonland card from it for each card discarded
// this way. That player discards those cards.
this.getSpellAbility().addEffect(new LastRitesEffect());
this.getSpellAbility().addTarget(new TargetPlayer());
-
}
- public LastRites(final LastRites card) {
+ private LastRites(final LastRites card) {
super(card);
}
@@ -58,7 +58,7 @@ class LastRitesEffect extends OneShotEffect {
+ "each card discarded this way. That player discards those cards";
}
- LastRitesEffect(final LastRitesEffect effect) {
+ private LastRitesEffect(final LastRitesEffect effect) {
super(effect);
}
@@ -71,28 +71,21 @@ class LastRitesEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source));
- if (controller != null && targetPlayer != null) {
- Cards cardsInHand = controller.getHand().copy();
- TargetCard target = new TargetCard(0, Integer.MAX_VALUE, Zone.HAND, new FilterCard("cards to discard"));
- controller.chooseTarget(Outcome.AIDontUseIt, cardsInHand, target, source, game);
- int discardCount = target.getTargets().size();
- if (discardCount > 0) {
- for (UUID cardId : target.getTargets()) {
- Card card = game.getCard(cardId);
- if (card != null) {
- controller.discard(card, source, game);
- }
- }
- FilterCard filter = new FilterCard((discardCount > 1 ? "" : "a")
- + " nonland card" + (discardCount > 1 ? "s" : ""));
- filter.add(Predicates.not(CardType.LAND.getPredicate()));
- StaticValue discardValue = StaticValue.get(discardCount);
- Effect effect = new DiscardCardYouChooseTargetEffect(discardValue, filter, TargetController.ANY);
- effect.setTargetPointer(new FixedTarget(targetPlayer.getId()));
- effect.apply(game, source);
- }
- return true;
+ if (controller == null || targetPlayer == null) {
+ return false;
}
- return false;
+ Cards cardsInHand = controller.getHand().copy();
+ TargetCard target = new TargetDiscard(
+ 0, Integer.MAX_VALUE, StaticFilters.FILTER_CARD_CARDS, controller.getId()
+ );
+ controller.chooseTarget(Outcome.AIDontUseIt, cardsInHand, target, source, game);
+ int discardCount = controller.discard(new CardsImpl(target.getTargets()), source, game).size();
+ FilterCard filter = new FilterCard((discardCount > 1 ? "" : "a")
+ + " nonland card" + (discardCount > 1 ? "s" : ""));
+ filter.add(Predicates.not(CardType.LAND.getPredicate()));
+ Effect effect = new DiscardCardYouChooseTargetEffect(StaticValue.get(discardCount), filter, TargetController.ANY);
+ effect.setTargetPointer(new FixedTarget(targetPlayer.getId()));
+ effect.apply(game, source);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/l/LastWord.java b/Mage.Sets/src/mage/cards/l/LastWord.java
index aa94e9991a2..bf8cb38408c 100644
--- a/Mage.Sets/src/mage/cards/l/LastWord.java
+++ b/Mage.Sets/src/mage/cards/l/LastWord.java
@@ -3,7 +3,7 @@
package mage.cards.l;
import java.util.UUID;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -19,7 +19,7 @@ public final class LastWord extends CardImpl {
public LastWord (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}{U}");
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
this.getSpellAbility().addEffect(new CounterTargetEffect());
this.getSpellAbility().addTarget(new TargetSpell());
}
diff --git a/Mage.Sets/src/mage/cards/l/LavaHounds.java b/Mage.Sets/src/mage/cards/l/LavaHounds.java
index 6e62d95e671..b7b481c90fc 100644
--- a/Mage.Sets/src/mage/cards/l/LavaHounds.java
+++ b/Mage.Sets/src/mage/cards/l/LavaHounds.java
@@ -19,7 +19,7 @@ public final class LavaHounds extends CardImpl {
public LavaHounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
diff --git a/Mage.Sets/src/mage/cards/l/LavabrinkFloodgates.java b/Mage.Sets/src/mage/cards/l/LavabrinkFloodgates.java
index a3f4e93fd3b..6dc1f35714e 100644
--- a/Mage.Sets/src/mage/cards/l/LavabrinkFloodgates.java
+++ b/Mage.Sets/src/mage/cards/l/LavabrinkFloodgates.java
@@ -2,22 +2,23 @@ package mage.cards.l;
import mage.Mana;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageAllEffect;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.TargetController;
+import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
@@ -93,45 +94,17 @@ class LavabrinkFloodgatesEffect extends OneShotEffect {
break;
case "Do nothing":
default:
- return false;
+ break;
}
if (permanent.getCounters(game).getCount(CounterType.DOOM) < 3
|| !permanent.sacrifice(source.getSourceId(), game)) {
return true;
}
- game.addDelayedTriggeredAbility(new LavabrinkFloodgatesReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class LavabrinkFloodgatesReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- LavabrinkFloodgatesReflexiveTriggeredAbility() {
- super(new DamageAllEffect(6, StaticFilters.FILTER_PERMANENT_CREATURE), Duration.OneUse, true);
- }
-
- private LavabrinkFloodgatesReflexiveTriggeredAbility(final LavabrinkFloodgatesReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public LavabrinkFloodgatesReflexiveTriggeredAbility copy() {
- return new LavabrinkFloodgatesReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "It deals 6 damage to each creature.";
+ game.fireReflexiveTriggeredAbility(new ReflexiveTriggeredAbility(
+ new DamageAllEffect(
+ 6, StaticFilters.FILTER_PERMANENT_CREATURE
+ ), false, "it deals 6 damage to each creature."
+ ), source);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/l/LavabrinkVenturer.java b/Mage.Sets/src/mage/cards/l/LavabrinkVenturer.java
index 6e300845383..ef18a42db35 100644
--- a/Mage.Sets/src/mage/cards/l/LavabrinkVenturer.java
+++ b/Mage.Sets/src/mage/cards/l/LavabrinkVenturer.java
@@ -79,7 +79,6 @@ class LavabrinkVenturerEffect extends GainAbilitySourceEffect {
if (choosenMode == null) {
return false;
}
- Ability ability;
switch (choosenMode) {
case "Odd":
this.ability = new ProtectionAbility(oddFilter);
diff --git a/Mage.Sets/src/mage/cards/l/LawlessBroker.java b/Mage.Sets/src/mage/cards/l/LawlessBroker.java
index 12ebf3c2562..d1ddc1b9290 100644
--- a/Mage.Sets/src/mage/cards/l/LawlessBroker.java
+++ b/Mage.Sets/src/mage/cards/l/LawlessBroker.java
@@ -4,7 +4,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -27,7 +27,7 @@ public final class LawlessBroker extends CardImpl {
this.toughness = new MageInt(2);
// When Lawless Broker dies, put a +1/+1 counter on target creature you control.
- Ability ability = new DiesTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false);
+ Ability ability = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false);
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/l/LeafkinAvenger.java b/Mage.Sets/src/mage/cards/l/LeafkinAvenger.java
new file mode 100644
index 00000000000..587e7d42496
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LeafkinAvenger.java
@@ -0,0 +1,68 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.Mana;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.mana.DynamicManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.ComparisonType;
+import mage.constants.SubType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.PowerPredicate;
+import mage.target.common.TargetPlayerOrPlaneswalker;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LeafkinAvenger extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterCreaturePermanent("creature you control with power 4 or greater");
+
+ static {
+ filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3));
+ }
+
+ private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
+ private static final DynamicValue xValue2 = new SourcePermanentPowerCount(false);
+
+ public LeafkinAvenger(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}");
+
+ this.subtype.add(SubType.ELEMENTAL);
+ this.subtype.add(SubType.DRUID);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(3);
+
+ // {T}: Add {G} for each creature you control with power 4 or greater.
+ this.addAbility(new DynamicManaAbility(Mana.GreenMana(1), xValue));
+
+ // {7}{R}: Leafkin Avenger deals damage equal to its power to target player or planeswalker.
+ Ability ability = new SimpleActivatedAbility(
+ new DamageTargetEffect(xValue2)
+ .setText("{this} deals damage equal to its power to target player or planeswalker"),
+ new ManaCostsImpl("{7}{R}")
+ );
+ ability.addTarget(new TargetPlayerOrPlaneswalker());
+ this.addAbility(ability);
+ }
+
+ private LeafkinAvenger(final LeafkinAvenger card) {
+ super(card);
+ }
+
+ @Override
+ public LeafkinAvenger copy() {
+ return new LeafkinAvenger(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/Leashling.java b/Mage.Sets/src/mage/cards/l/Leashling.java
index 41f20990423..c4dfc5cd1e2 100644
--- a/Mage.Sets/src/mage/cards/l/Leashling.java
+++ b/Mage.Sets/src/mage/cards/l/Leashling.java
@@ -28,7 +28,7 @@ public final class Leashling extends CardImpl {
public Leashling(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{6}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/l/LeaveChance.java b/Mage.Sets/src/mage/cards/l/LeaveChance.java
index 4298a545403..00c6923f172 100644
--- a/Mage.Sets/src/mage/cards/l/LeaveChance.java
+++ b/Mage.Sets/src/mage/cards/l/LeaveChance.java
@@ -1,39 +1,41 @@
-
package mage.cards.l;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.keyword.AftermathAbility;
-import mage.cards.Card;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.TargetController;
-import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPermanent;
-import mage.target.common.TargetCardInHand;
+import mage.target.common.TargetDiscard;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class LeaveChance extends SplitCard {
+ private static final FilterPermanent filter = new FilterPermanent("permanents you own");
+
+ static {
+ filter.add(TargetController.YOU.getOwnerPredicate());
+ }
+
public LeaveChance(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, new CardType[]{CardType.SORCERY}, "{1}{W}", "{3}{R}", SpellAbilityType.SPLIT_AFTERMATH);
// Return any number of target permanents you own to your hand.
- FilterPermanent filter = new FilterPermanent("permanents you own");
- filter.add(TargetController.YOU.getOwnerPredicate());
getLeftHalfCard().getSpellAbility().addEffect(new ReturnToHandTargetEffect());
getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(0, Integer.MAX_VALUE, filter, false));
@@ -41,12 +43,12 @@ public final class LeaveChance extends SplitCard {
// Sorcery
// Aftermath
getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true));
+
// Discard any number of cards, then draw that many cards.
getRightHalfCard().getSpellAbility().addEffect(new ChanceEffect());
-
}
- public LeaveChance(final LeaveChance card) {
+ private LeaveChance(final LeaveChance card) {
super(card);
}
@@ -63,7 +65,7 @@ class ChanceEffect extends OneShotEffect {
this.staticText = "Discard any number of cards, then draw that many cards";
}
- ChanceEffect(final ChanceEffect effect) {
+ private ChanceEffect(final ChanceEffect effect) {
super(effect);
}
@@ -75,22 +77,13 @@ class ChanceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Cards cardsInHand = controller.getHand().copy();
- TargetCard target = new TargetCardInHand(0, cardsInHand.size(), new FilterCard());
- controller.chooseTarget(outcome, cardsInHand, target, source, game);
- if (!target.getTargets().isEmpty()) {
- for (UUID cardId : target.getTargets()) {
- Card card = game.getCard(cardId);
- if (card != null) {
- controller.discard(card, source, game);
- }
- }
- game.applyEffects();
- controller.drawCards(target.getTargets().size(), source.getSourceId(), game);
- }
- return true;
+ if (controller == null) {
+ return false;
}
- return false;
+ TargetCard target = new TargetDiscard(0, controller.getHand().size(), StaticFilters.FILTER_CARD_CARDS, controller.getId());
+ controller.chooseTarget(outcome, controller.getHand(), target, source, game);
+ int amount = controller.discard(new CardsImpl(target.getTargets()), source, game).size();
+ controller.drawCards(amount, source.getSourceId(), game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/l/LedevChampion.java b/Mage.Sets/src/mage/cards/l/LedevChampion.java
index 108ac4328de..10303e8e7d2 100644
--- a/Mage.Sets/src/mage/cards/l/LedevChampion.java
+++ b/Mage.Sets/src/mage/cards/l/LedevChampion.java
@@ -1,6 +1,5 @@
package mage.cards.l;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
@@ -9,23 +8,20 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
-import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.TargetController;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.game.Game;
+import mage.game.permanent.Permanent;
import mage.game.permanent.token.SoldierLifelinkToken;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class LedevChampion extends CardImpl {
@@ -86,9 +82,10 @@ class LedevChampionEffect extends OneShotEffect {
TargetCreaturePermanent target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true);
if (target.canChoose(source.getControllerId(), game)
&& target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), game)) {
- for (UUID creature : target.getTargets()) {
+ for (UUID creatureId : target.getTargets()) {
+ Permanent creature = game.getPermanent(creatureId);
if (creature != null) {
- game.getPermanent(creature).tap(game);
+ creature.tap(game);
tappedAmount++;
}
}
diff --git a/Mage.Sets/src/mage/cards/l/LeeryFogbeast.java b/Mage.Sets/src/mage/cards/l/LeeryFogbeast.java
index 6e9ac41b3a6..9cef5b01847 100644
--- a/Mage.Sets/src/mage/cards/l/LeeryFogbeast.java
+++ b/Mage.Sets/src/mage/cards/l/LeeryFogbeast.java
@@ -3,7 +3,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.PreventAllDamageByAllPermanentsEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class LeeryFogbeast extends CardImpl {
this.toughness = new MageInt(2);
// Whenever Leery Fogbeast becomes blocked, prevent all combat damage that would be dealt this turn.
- this.addAbility(new BecomesBlockedTriggeredAbility(new PreventAllDamageByAllPermanentsEffect(Duration.EndOfTurn, true), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new PreventAllDamageByAllPermanentsEffect(Duration.EndOfTurn, true), false));
}
public LeeryFogbeast(final LeeryFogbeast card) {
diff --git a/Mage.Sets/src/mage/cards/l/LeoninOfTheLostPride.java b/Mage.Sets/src/mage/cards/l/LeoninOfTheLostPride.java
index 3d5719900f4..1fb3efdf0e7 100644
--- a/Mage.Sets/src/mage/cards/l/LeoninOfTheLostPride.java
+++ b/Mage.Sets/src/mage/cards/l/LeoninOfTheLostPride.java
@@ -1,7 +1,7 @@
package mage.cards.l;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -28,7 +28,7 @@ public final class LeoninOfTheLostPride extends CardImpl {
this.toughness = new MageInt(1);
// When Leonin of the Lost Pride dies, exile target card from an opponent’s graveyard.
- DiesTriggeredAbility diesTriggeredAbility = new DiesTriggeredAbility(new ExileTargetEffect());
+ DiesSourceTriggeredAbility diesTriggeredAbility = new DiesSourceTriggeredAbility(new ExileTargetEffect());
diesTriggeredAbility.addTarget(new TargetCardInOpponentsGraveyard(new FilterCard("card from an opponent's graveyard")));
this.addAbility(diesTriggeredAbility);
}
diff --git a/Mage.Sets/src/mage/cards/l/LiarsPendulum.java b/Mage.Sets/src/mage/cards/l/LiarsPendulum.java
index 195878591b6..e30258077d1 100644
--- a/Mage.Sets/src/mage/cards/l/LiarsPendulum.java
+++ b/Mage.Sets/src/mage/cards/l/LiarsPendulum.java
@@ -93,7 +93,7 @@ class LiarsPendulumEffect extends OneShotEffect {
rightGuess = opponentGuess;
}
}
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
rightGuess = opponentGuess;
}
}
diff --git a/Mage.Sets/src/mage/cards/l/LibraryLarcenist.java b/Mage.Sets/src/mage/cards/l/LibraryLarcenist.java
new file mode 100644
index 00000000000..ad1c72df677
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LibraryLarcenist.java
@@ -0,0 +1,38 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LibraryLarcenist extends CardImpl {
+
+ public LibraryLarcenist(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
+
+ this.subtype.add(SubType.MERFOLK);
+ this.subtype.add(SubType.ROGUE);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(2);
+
+ // Whenever Library Larcenist attacks, draw a card.
+ this.addAbility(new AttacksTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ }
+
+ private LibraryLarcenist(final LibraryLarcenist card) {
+ super(card);
+ }
+
+ @Override
+ public LibraryLarcenist copy() {
+ return new LibraryLarcenist(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LichsMirror.java b/Mage.Sets/src/mage/cards/l/LichsMirror.java
index 3bff7b7d4e7..d12065242e3 100644
--- a/Mage.Sets/src/mage/cards/l/LichsMirror.java
+++ b/Mage.Sets/src/mage/cards/l/LichsMirror.java
@@ -8,7 +8,10 @@ import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.constants.*;
+import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.other.OwnerIdPredicate;
import mage.game.Game;
@@ -64,32 +67,20 @@ class LichsMirrorEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player player = game.getPlayer(event.getPlayerId());
if (player != null) {
+ Cards toLib = new CardsImpl();
FilterControlledPermanent filter = new FilterControlledPermanent();
filter.add(new OwnerIdPredicate(player.getId()));
- for (UUID uuid : player.getHand().copy()) {
- Card card = game.getCard(uuid);
- if (card != null) {
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- }
-
- for (UUID uuid : player.getGraveyard().copy()) {
- Card card = game.getCard(uuid);
- if (card != null) {
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- }
-
+ toLib.addAll(player.getHand());
+ toLib.addAll(player.getGraveyard());
for(Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)){
- permanent.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- player.shuffleLibrary(source, game);
-
- player.drawCards(7, source.getSourceId(), game);
-
- player.setLife(20, game, source);
+ toLib.add(permanent);
+ }
+ player.shuffleCardsToLibrary(toLib, game, source);
+ game.getState().processAction(game);
+ player.drawCards(7, source.getSourceId(), game);
+ player.setLife(20, game, source);
}
- return true;
+ return true; // replace the loses event
}
@Override
@@ -99,10 +90,7 @@ class LichsMirrorEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
- if (event.getPlayerId().equals(source.getControllerId())) {
- return true;
- }
- return false;
+ return event.getPlayerId().equals(source.getControllerId());
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/l/LiciaSanguineTribune.java b/Mage.Sets/src/mage/cards/l/LiciaSanguineTribune.java
index aa1c3722051..67e9c624b52 100644
--- a/Mage.Sets/src/mage/cards/l/LiciaSanguineTribune.java
+++ b/Mage.Sets/src/mage/cards/l/LiciaSanguineTribune.java
@@ -40,7 +40,7 @@ public final class LiciaSanguineTribune extends CardImpl {
this.toughness = new MageInt(4);
// Licia, Sanguine Tribune costs 1 less to cast for each 1 life you gained this turn.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new LiciaSanguineTribuneCostReductionEffect()), new PlayerGainedLifeWatcher());
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new LiciaSanguineTribuneCostReductionEffect()), new PlayerGainedLifeWatcher());
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/l/LiegeOfTheHollows.java b/Mage.Sets/src/mage/cards/l/LiegeOfTheHollows.java
new file mode 100644
index 00000000000..dc3267a00d9
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LiegeOfTheHollows.java
@@ -0,0 +1,95 @@
+package mage.cards.l;
+
+import java.util.HashMap;
+import java.util.Map;
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DiesSourceTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.game.Game;
+import mage.game.permanent.token.SquirrelToken;
+import mage.players.Player;
+import mage.util.ManaUtil;
+
+import java.util.UUID;
+
+/**
+ * @author arcox
+ */
+public final class LiegeOfTheHollows extends CardImpl {
+
+ public LiegeOfTheHollows(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
+ this.subtype.add(SubType.SPIRIT);
+
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(4);
+
+ // When Liege of the Hollows dies, each player may pay any amount of mana.
+ // Then each player creates a number of 1/1 green Squirrel creature tokens
+ // equal to the amount of mana they paid this way.
+ this.addAbility(new DiesSourceTriggeredAbility(new LiegeOfTheHollowsEffect()));
+ }
+
+ public LiegeOfTheHollows(final LiegeOfTheHollows card) {
+ super(card);
+ }
+
+ @Override
+ public LiegeOfTheHollows copy() {
+ return new LiegeOfTheHollows(this);
+ }
+}
+
+class LiegeOfTheHollowsEffect extends OneShotEffect {
+
+ public LiegeOfTheHollowsEffect() {
+ super(Outcome.Detriment);
+ this.staticText = "each player may pay any amount of mana. Then each player creates a number "
+ + "of 1/1 green Squirrel creature tokens equal to the amount of mana they paid this way";
+ }
+
+ public LiegeOfTheHollowsEffect(final LiegeOfTheHollowsEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public LiegeOfTheHollowsEffect copy() {
+ return new LiegeOfTheHollowsEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ Map paidMana = new HashMap<>();
+ if (controller != null) {
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player != null) {
+ paidMana.put(player.getId(), ManaUtil.playerPaysXGenericMana(false,
+ "Liege of the Hollows", player, source, game));
+ }
+ }
+ // create tokens
+ SquirrelToken token = new SquirrelToken();
+ for (Map.Entry entry
+ : paidMana.entrySet()) {
+ Player player = game.getPlayer(entry.getKey());
+ if (player != null) {
+ token.putOntoBattlefield(entry.getValue(), game, source.getSourceId(), player.getId());
+ }
+ }
+ game.getState().processAction(game);
+
+ // prevent undo
+ controller.resetStoredBookmark(game);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LifeMatrix.java b/Mage.Sets/src/mage/cards/l/LifeMatrix.java
index 09bb4c904ec..137c62abe98 100644
--- a/Mage.Sets/src/mage/cards/l/LifeMatrix.java
+++ b/Mage.Sets/src/mage/cards/l/LifeMatrix.java
@@ -1,4 +1,3 @@
-
package mage.cards.l;
import java.util.UUID;
@@ -30,10 +29,19 @@ public final class LifeMatrix extends CardImpl {
public LifeMatrix(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
- // {4}, {T}: Put a matrix counter on target creature and that creature gains “Remove a matrix counter from this creature: Regenerate this creature.” Activate this ability only during your upkeep.
- Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.MATRIX.createInstance()), new GenericManaCost(4),
- new IsStepCondition(PhaseStep.UPKEEP), null);
- Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new RemoveCountersSourceCost(CounterType.MATRIX.createInstance()));
+ // {4}, {T}: Put a matrix counter on target creature and that creature gains
+ // “Remove a matrix counter from this creature: Regenerate this creature.”
+ // Activate this ability only during your upkeep.
+ Ability ability = new ConditionalActivatedAbility(
+ Zone.BATTLEFIELD,
+ new AddCountersTargetEffect(CounterType.MATRIX.createInstance()),
+ new GenericManaCost(4),
+ new IsStepCondition(PhaseStep.UPKEEP), "Put a matrix counter on target creature and "
+ + "that creature gains “Remove a matrix counter from this creature: "
+ + "Regenerate this creature.” Activate this ability only during your upkeep.");
+ Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD,
+ new RegenerateSourceEffect(),
+ new RemoveCountersSourceCost(CounterType.MATRIX.createInstance()));
ability.addEffect(new GainAbilityTargetEffect(ability2, Duration.Custom));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent());
diff --git a/Mage.Sets/src/mage/cards/l/LifebloodHydra.java b/Mage.Sets/src/mage/cards/l/LifebloodHydra.java
index 64488b6dadb..7a772125413 100644
--- a/Mage.Sets/src/mage/cards/l/LifebloodHydra.java
+++ b/Mage.Sets/src/mage/cards/l/LifebloodHydra.java
@@ -4,7 +4,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect;
@@ -39,7 +39,7 @@ public final class LifebloodHydra extends CardImpl {
this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance())));
// When Lifeblood Hydra dies, you gain life and draw cards equal to its power.
- this.addAbility(new DiesTriggeredAbility(new LifebloodHydraEffect(), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new LifebloodHydraEffect(), false));
}
public LifebloodHydra(final LifebloodHydra card) {
diff --git a/Mage.Sets/src/mage/cards/l/LightOfPromise.java b/Mage.Sets/src/mage/cards/l/LightOfPromise.java
new file mode 100644
index 00000000000..622f7ee7ea1
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LightOfPromise.java
@@ -0,0 +1,84 @@
+package mage.cards.l;
+
+import mage.abilities.Ability;
+import mage.abilities.common.GainLifeControllerTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.AttachEffect;
+import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
+import mage.abilities.keyword.EnchantAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.AttachmentType;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LightOfPromise extends CardImpl {
+
+ public LightOfPromise(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
+
+ this.subtype.add(SubType.AURA);
+
+ // Enchant creature
+ TargetPermanent auraTarget = new TargetCreaturePermanent();
+ this.getSpellAbility().addTarget(auraTarget);
+ this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
+ Ability ability = new EnchantAbility(auraTarget.getTargetName());
+ this.addAbility(ability);
+
+ // Enchanted creature has "Whenever you gain life, put that many +1/+1 counters on this creature."
+ this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect(
+ new GainLifeControllerTriggeredAbility(
+ new LightOfPromiseEffect(), false, true
+ ), AttachmentType.AURA
+ )));
+ }
+
+ private LightOfPromise(final LightOfPromise card) {
+ super(card);
+ }
+
+ @Override
+ public LightOfPromise copy() {
+ return new LightOfPromise(this);
+ }
+}
+
+class LightOfPromiseEffect extends OneShotEffect {
+
+ LightOfPromiseEffect() {
+ super(Outcome.Benefit);
+ staticText = "put that many +1/+1 counters on this creature";
+ }
+
+ private LightOfPromiseEffect(final LightOfPromiseEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public LightOfPromiseEffect copy() {
+ return new LightOfPromiseEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanent(source.getSourceId());
+ if (permanent == null) {
+ return false;
+ }
+ int gainedLife = (int) this.getValue("gainedLife");
+ return permanent.addCounters(CounterType.P1P1.createInstance(gainedLife), source, game);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LightOfTheLegion.java b/Mage.Sets/src/mage/cards/l/LightOfTheLegion.java
index c9581e39495..ebe0aac8bf7 100644
--- a/Mage.Sets/src/mage/cards/l/LightOfTheLegion.java
+++ b/Mage.Sets/src/mage/cards/l/LightOfTheLegion.java
@@ -3,7 +3,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.constants.SubType;
import mage.abilities.keyword.FlyingAbility;
@@ -42,7 +42,7 @@ public final class LightOfTheLegion extends CardImpl {
this.addAbility(new MentorAbility());
// When Light of the Legion dies, put a +1/+1 counter on each white creature you control.
- this.addAbility(new DiesTriggeredAbility(new AddCountersAllEffect(
+ this.addAbility(new DiesSourceTriggeredAbility(new AddCountersAllEffect(
CounterType.P1P1.createInstance(), filter
)));
}
diff --git a/Mage.Sets/src/mage/cards/l/LightningCoils.java b/Mage.Sets/src/mage/cards/l/LightningCoils.java
index b3b8a32f3a0..fbc516c5b5d 100644
--- a/Mage.Sets/src/mage/cards/l/LightningCoils.java
+++ b/Mage.Sets/src/mage/cards/l/LightningCoils.java
@@ -1,7 +1,5 @@
-
package mage.cards.l;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.DiesCreatureTriggeredAbility;
@@ -19,16 +17,18 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import mage.game.permanent.token.ElementalToken;
+import mage.game.permanent.token.ElementalTokenWithHaste;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author escplan9 - Derek Monturo
*/
public final class LightningCoils extends CardImpl {
-
+
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a nontoken creature you control");
+
static {
filter.add(TargetController.YOU.getControllerPredicate());
filter.add(Predicates.not(TokenPredicate.instance));
@@ -36,13 +36,13 @@ public final class LightningCoils extends CardImpl {
public LightningCoils(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
-
+
// Whenever a nontoken creature you control dies, put a charge counter on Lightning Coils.
this.addAbility(
new DiesCreatureTriggeredAbility(
- new AddCountersSourceEffect(CounterType.CHARGE.createInstance(), true),
+ new AddCountersSourceEffect(CounterType.CHARGE.createInstance(), true),
false, filter));
-
+
// At the beginning of your upkeep, if Lightning Coils has five or more charge counters on it, remove all of them from it
// and put that many 3/1 red Elemental creature tokens with haste onto the battlefield.
// Exile them at the beginning of the next end step.
@@ -79,9 +79,9 @@ class LightningCoilsEffect extends OneShotEffect {
if (counters >= 5) {
// remove all the counters and create that many tokens
p.removeCounters(CounterType.CHARGE.getName(), p.getCounters(game).getCount(CounterType.CHARGE), game);
- CreateTokenEffect effect = new CreateTokenEffect(new ElementalToken("CON", 1, true), counters);
+ CreateTokenEffect effect = new CreateTokenEffect(new ElementalTokenWithHaste(), counters);
effect.apply(game, source);
-
+
// exile those tokens at next end step
effect.exileTokensCreatedAtNextEndStep(game, source);
return true;
diff --git a/Mage.Sets/src/mage/cards/l/LightningCoreExcavator.java b/Mage.Sets/src/mage/cards/l/LightningCoreExcavator.java
new file mode 100644
index 00000000000..b0ee776149c
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LightningCoreExcavator.java
@@ -0,0 +1,48 @@
+package mage.cards.l;
+
+import mage.MageInt;
+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.common.DamageTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import java.util.UUID;
+import mage.filter.common.FilterCreaturePlayerOrPlaneswalker;
+import mage.target.common.TargetAnyTarget;
+
+/**
+ * @author TheElk801
+ */
+public final class LightningCoreExcavator extends CardImpl {
+
+ public LightningCoreExcavator(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}");
+
+ this.subtype.add(SubType.GOLEM);
+ this.power = new MageInt(0);
+ this.toughness = new MageInt(3);
+
+ // {5}, {T}, Sacrifice Lightning-Core Excavator: It deals 3 damage to any target.
+ Ability ability = new SimpleActivatedAbility(
+ new DamageTargetEffect(3), new GenericManaCost(5)
+ );
+ ability.addCost(new TapSourceCost());
+ ability.addCost(new SacrificeSourceCost());
+ ability.addTarget(new TargetAnyTarget(new FilterCreaturePlayerOrPlaneswalker("any target")));
+ this.addAbility(ability);
+ }
+
+ private LightningCoreExcavator(final LightningCoreExcavator card) {
+ super(card);
+ }
+
+ @Override
+ public LightningCoreExcavator copy() {
+ return new LightningCoreExcavator(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LightningHounds.java b/Mage.Sets/src/mage/cards/l/LightningHounds.java
index 4aba0b130e4..36ed3340f59 100644
--- a/Mage.Sets/src/mage/cards/l/LightningHounds.java
+++ b/Mage.Sets/src/mage/cards/l/LightningHounds.java
@@ -17,7 +17,7 @@ public final class LightningHounds extends CardImpl {
public LightningHounds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/l/LightningMare.java b/Mage.Sets/src/mage/cards/l/LightningMare.java
index 557cd1daa89..7d33dde8d3c 100644
--- a/Mage.Sets/src/mage/cards/l/LightningMare.java
+++ b/Mage.Sets/src/mage/cards/l/LightningMare.java
@@ -3,7 +3,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -39,7 +39,7 @@ public final class LightningMare extends CardImpl {
this.toughness = new MageInt(1);
// This spell can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Lightning Mare can't be blocked by blue creatures.
this.addAbility(new SimpleStaticAbility(
diff --git a/Mage.Sets/src/mage/cards/l/LightningPhoenix.java b/Mage.Sets/src/mage/cards/l/LightningPhoenix.java
new file mode 100644
index 00000000000..82649cc8c4b
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LightningPhoenix.java
@@ -0,0 +1,106 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.common.CantBlockAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.abilities.keyword.HasteAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.watchers.Watcher;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LightningPhoenix extends CardImpl {
+
+ public LightningPhoenix(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
+
+ this.subtype.add(SubType.PHOENIX);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Haste
+ this.addAbility(HasteAbility.getInstance());
+
+ // Lightning Phoenix can't block.
+ this.addAbility(new CantBlockAbility());
+
+ // At the beginning of your end step, if an opponent was dealt 3 or more damage this turn, you may pay {R}. If you do, return Lightning Phoenix from your graveyard to the battlefield.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfEndStepTriggeredAbility(
+ Zone.GRAVEYARD,
+ new DoIfCostPaid(
+ new ReturnSourceFromGraveyardToBattlefieldEffect(), new ManaCostsImpl<>("{R}")
+ ), TargetController.YOU, null, false
+ ), LightningPhoenixCondition.instance, "At the beginning of your end step, " +
+ "if an opponent was dealt 3 or more damage this turn, you may pay {R}. " +
+ "If you do, return {this} from your graveyard to the battlefield."
+ ), new LightningPhoenixWatcher());
+ }
+
+ private LightningPhoenix(final LightningPhoenix card) {
+ super(card);
+ }
+
+ @Override
+ public LightningPhoenix copy() {
+ return new LightningPhoenix(this);
+ }
+}
+
+enum LightningPhoenixCondition implements Condition {
+ instance;
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ LightningPhoenixWatcher watcher = game.getState().getWatcher(LightningPhoenixWatcher.class);
+ return watcher != null && watcher.checkDamage(source.getControllerId());
+ }
+}
+
+class LightningPhoenixWatcher extends Watcher {
+
+ private final Map damageMap = new HashMap<>();
+
+ LightningPhoenixWatcher() {
+ super(WatcherScope.GAME);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() != GameEvent.EventType.DAMAGED_PLAYER) {
+ return;
+ }
+ for (UUID playerId : game.getOpponents(event.getTargetId())) {
+ damageMap.compute(playerId, ((u, i) -> i == null ? event.getAmount() : Integer.sum(i, event.getAmount())));
+ }
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ damageMap.clear();
+ }
+
+ boolean checkDamage(UUID playerId) {
+ return damageMap.getOrDefault(playerId, 0) >= 3;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LightningVisionary.java b/Mage.Sets/src/mage/cards/l/LightningVisionary.java
new file mode 100644
index 00000000000..282585748bc
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LightningVisionary.java
@@ -0,0 +1,37 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.abilities.keyword.ProwessAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LightningVisionary extends CardImpl {
+
+ public LightningVisionary(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
+
+ this.subtype.add(SubType.MINOTAUR);
+ this.subtype.add(SubType.SHAMAN);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // Prowess
+ this.addAbility(new ProwessAbility());
+ }
+
+ private LightningVisionary(final LightningVisionary card) {
+ super(card);
+ }
+
+ @Override
+ public LightningVisionary copy() {
+ return new LightningVisionary(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LilianaDeathMage.java b/Mage.Sets/src/mage/cards/l/LilianaDeathMage.java
new file mode 100644
index 00000000000..0e1d8341ce4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LilianaDeathMage.java
@@ -0,0 +1,121 @@
+package mage.cards.l;
+
+import mage.abilities.Ability;
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DestroyTargetEffect;
+import mage.abilities.effects.common.LoseLifeTargetControllerEffect;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.constants.Zone;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetCardInYourGraveyard;
+import mage.target.common.TargetCreaturePermanent;
+import mage.target.common.TargetOpponent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class LilianaDeathMage extends CardImpl {
+
+ public LilianaDeathMage(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{B}{B}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.LILIANA);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
+
+ // +1: Return up to one target creature card from your graveyard to your hand.
+ Ability plusAbility = new LoyaltyAbility(new LilianaDeathMagePlusEffect(), 1);
+ plusAbility.addTarget(new TargetCardInYourGraveyard(0, 1, StaticFilters.FILTER_CARD_CREATURE));
+ this.addAbility(plusAbility);
+
+ // −3: Destroy target creature. Its controller loses 2 life.
+ Ability minusAbility = new LoyaltyAbility(new DestroyTargetEffect(), -3);
+ minusAbility.addTarget(new TargetCreaturePermanent());
+ minusAbility.addEffect(new LoseLifeTargetControllerEffect(2));
+ this.addAbility(minusAbility);
+
+ // −7: Target opponent loses 2 life for each creature card in their graveyard.
+ Ability ultimateAbility = new LoyaltyAbility(new LilianaDeathMageUltimateEffect(), -7);
+ ultimateAbility.addTarget(new TargetOpponent());
+ this.addAbility(ultimateAbility);
+ }
+
+ private LilianaDeathMage(final LilianaDeathMage card) {
+ super(card);
+ }
+
+ @Override
+ public LilianaDeathMage copy() {
+ return new LilianaDeathMage(this);
+ }
+}
+
+class LilianaDeathMagePlusEffect extends OneShotEffect {
+
+ LilianaDeathMagePlusEffect() {
+ super(Outcome.Benefit);
+ staticText = "Return up to one target creature card from your graveyard to your hand";
+ }
+
+ private LilianaDeathMagePlusEffect(LilianaDeathMagePlusEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public LilianaDeathMagePlusEffect copy() {
+ return new LilianaDeathMagePlusEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null) {
+ return false;
+ }
+ Card card = game.getCard(source.getTargets().get(0).getFirstTarget());
+ if (card == null) {
+ return false;
+ }
+ return player.moveCards(card, Zone.HAND, source, game);
+ }
+}
+
+class LilianaDeathMageUltimateEffect extends OneShotEffect {
+
+ LilianaDeathMageUltimateEffect() {
+ super(Outcome.Damage);
+ staticText = "Target opponent loses 2 life for each creature card in their graveyard";
+ }
+
+ private LilianaDeathMageUltimateEffect(LilianaDeathMageUltimateEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public LilianaDeathMageUltimateEffect copy() {
+ return new LilianaDeathMageUltimateEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player opponent = game.getPlayer(source.getFirstTarget());
+ if (opponent != null) {
+ int amount = opponent.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game);
+ opponent.loseLife(amount * 2, game, false);
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/l/LilianaDreadhordeGeneral.java b/Mage.Sets/src/mage/cards/l/LilianaDreadhordeGeneral.java
index a538d5ada61..5b77db31f2a 100644
--- a/Mage.Sets/src/mage/cards/l/LilianaDreadhordeGeneral.java
+++ b/Mage.Sets/src/mage/cards/l/LilianaDreadhordeGeneral.java
@@ -31,7 +31,7 @@ import java.util.UUID;
*/
public final class LilianaDreadhordeGeneral extends CardImpl {
- private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("creatures");
+ private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent(" creatures");
public LilianaDreadhordeGeneral(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{B}{B}");
diff --git a/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java b/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java
index f131e898ac6..dde813dd580 100644
--- a/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java
+++ b/Mage.Sets/src/mage/cards/l/LilianaUntouchedByDeath.java
@@ -1,7 +1,5 @@
package mage.cards.l;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
@@ -12,22 +10,17 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.Card;
-import mage.constants.SubType;
-import mage.constants.SuperType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AsThoughEffectType;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class LilianaUntouchedByDeath extends CardImpl {
@@ -73,8 +66,7 @@ class LilianaUntouchedByDeathEffect extends OneShotEffect {
public LilianaUntouchedByDeathEffect() {
super(Outcome.Benefit);
- this.staticText = "put the top three cards of your library into your graveyard. "
- + "If at least one of them is a Zombie card, each opponent loses 2 life and you gain 2 life";
+ this.staticText = "mill three cards. If at least one of them is a Zombie card, each opponent loses 2 life and you gain 2 life";
}
public LilianaUntouchedByDeathEffect(final LilianaUntouchedByDeathEffect effect) {
@@ -92,15 +84,11 @@ class LilianaUntouchedByDeathEffect extends OneShotEffect {
if (player == null) {
return false;
}
- boolean doEffect = false;
- Set top3 = player.moveCardsToGraveyardWithInfo(player.getLibrary().getTopCards(game, 3), source, game, Zone.LIBRARY);
- for (Card card : top3) {
- if (card != null && card.hasSubtype(SubType.ZOMBIE, game)) {
- doEffect = true;
- break;
- }
- }
- if (doEffect) {
+ if (player
+ .millCards(3, source, game)
+ .getCards(game)
+ .stream()
+ .anyMatch(card -> card.hasSubtype(SubType.ZOMBIE, game))) {
new LoseLifeOpponentsEffect(2).apply(game, source);
player.gainLife(2, game, source);
}
diff --git a/Mage.Sets/src/mage/cards/l/LilianaWakerOfTheDead.java b/Mage.Sets/src/mage/cards/l/LilianaWakerOfTheDead.java
new file mode 100644
index 00000000000..56a80487022
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LilianaWakerOfTheDead.java
@@ -0,0 +1,119 @@
+package mage.cards.l;
+
+import mage.abilities.Ability;
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.GetEmblemEffect;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.abilities.hint.ValueHint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
+import mage.constants.*;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.command.emblems.LilianaWakerOfTheDeadEmblem;
+import mage.players.Player;
+import mage.target.Target;
+import mage.target.common.TargetCreaturePermanent;
+import mage.target.common.TargetDiscard;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class LilianaWakerOfTheDead extends CardImpl {
+
+ private static final DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD, -1);
+ private static final DynamicValue xValue_hint = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD);
+
+ public LilianaWakerOfTheDead(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{B}{B}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.LILIANA);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
+
+ // +1: Each player discards a card. Each opponent who can't loses 3 life.
+ this.addAbility(new LoyaltyAbility(new LilianaWakerOfTheDeadDiscardEffect(), 1));
+
+ // −3: Target creature gets -X/-X until end of turn, where X is the number of cards in your graveyard.
+ Ability ability = new LoyaltyAbility(new BoostTargetEffect(
+ xValue, xValue, Duration.EndOfTurn, true
+ ).setText("target creature gets -X/-X until end of turn, where X is the number of cards in your graveyard"), -3)
+ .addHint(new ValueHint("Cards in your graveyard", xValue_hint));
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+
+ // −7: You get an emblem with "At the beginning of combat on your turn, put target creature card from a graveyard onto the battlefield under your control. It gains haste."
+ this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new LilianaWakerOfTheDeadEmblem()), -7));
+ }
+
+ private LilianaWakerOfTheDead(final LilianaWakerOfTheDead card) {
+ super(card);
+ }
+
+ @Override
+ public LilianaWakerOfTheDead copy() {
+ return new LilianaWakerOfTheDead(this);
+ }
+}
+
+class LilianaWakerOfTheDeadDiscardEffect extends OneShotEffect {
+
+ LilianaWakerOfTheDeadDiscardEffect() {
+ super(Outcome.Discard);
+ staticText = "Each player discards a card. Each opponent who can't loses 3 life";
+ }
+
+ private LilianaWakerOfTheDeadDiscardEffect(LilianaWakerOfTheDeadDiscardEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public LilianaWakerOfTheDeadDiscardEffect copy() {
+ return new LilianaWakerOfTheDeadDiscardEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ Map cardsToDiscard = new HashMap<>();
+ if (controller == null) {
+ return true;
+ }
+ // choose cards to discard
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
+ }
+ int numberOfCardsToDiscard = Math.min(1, player.getHand().size());
+ Cards cards = new CardsImpl();
+ Target target = new TargetDiscard(numberOfCardsToDiscard, numberOfCardsToDiscard, StaticFilters.FILTER_CARD, playerId);
+ player.chooseTarget(outcome, target, source, game);
+ cards.addAll(target.getTargets());
+ cardsToDiscard.put(playerId, cards);
+ }
+ // discard all choosen cards
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
+ }
+ int amountDiscarded = player.discard(cardsToDiscard.get(playerId), source, game).size();
+ if (controller.hasOpponent(playerId, game) && amountDiscarded == 0) {
+ player.loseLife(3, game, false);
+ }
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/l/LilianasDefeat.java b/Mage.Sets/src/mage/cards/l/LilianasDefeat.java
index c39d3aaf27a..02bedc3b11f 100644
--- a/Mage.Sets/src/mage/cards/l/LilianasDefeat.java
+++ b/Mage.Sets/src/mage/cards/l/LilianasDefeat.java
@@ -67,7 +67,7 @@ class LilianasDefeatEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (player != null && permanent != null) {
permanent.destroy(source.getSourceId(), game, true);
- game.applyEffects();
+ game.getState().processAction(game);
if (permanent.isPlaneswalker() && permanent.hasSubtype(SubType.LILIANA, game)) {
Player permanentController = game.getPlayer(permanent.getControllerId());
if (permanentController != null) {
diff --git a/Mage.Sets/src/mage/cards/l/LilianasDevotee.java b/Mage.Sets/src/mage/cards/l/LilianasDevotee.java
new file mode 100644
index 00000000000..32a0236aebb
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LilianasDevotee.java
@@ -0,0 +1,62 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.MorbidCondition;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.game.permanent.token.ZombieToken;
+import mage.watchers.common.MorbidWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LilianasDevotee extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.ZOMBIE, "Zombies");
+
+ public LilianasDevotee(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WARLOCK);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Zombies you control get +1/+0.
+ this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(
+ 1, 0, Duration.WhileOnBattlefield, filter
+ )));
+
+ // At the beginning of your end step, if a creature died this turn, you may pay {1}{B}. If you do, create a 2/2 black Zombie creature token.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfEndStepTriggeredAbility(new DoIfCostPaid(
+ new CreateTokenEffect(new ZombieToken()), new ManaCostsImpl("{1}{B}")
+ ), TargetController.YOU, false), MorbidCondition.instance,
+ "At the beginning of your end step, if a creature died this turn, " +
+ "you may pay {1}{B}. If you do, create a 2/2 black Zombie creature token."
+ ), new MorbidWatcher());
+ }
+
+ private LilianasDevotee(final LilianasDevotee card) {
+ super(card);
+ }
+
+ @Override
+ public LilianasDevotee copy() {
+ return new LilianasDevotee(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LilianasIndignation.java b/Mage.Sets/src/mage/cards/l/LilianasIndignation.java
index 67d0d59c1c7..3456d56f29f 100644
--- a/Mage.Sets/src/mage/cards/l/LilianasIndignation.java
+++ b/Mage.Sets/src/mage/cards/l/LilianasIndignation.java
@@ -1,24 +1,21 @@
package mage.cards.l;
-import java.util.Set;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
-import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class LilianasIndignation extends CardImpl {
@@ -45,7 +42,7 @@ class LilianasIndignationEffect extends OneShotEffect {
public LilianasIndignationEffect() {
super(Outcome.LoseLife);
- this.staticText = "Put the top X cards of your library into your graveyard. Target player loses 2 life for each creature card put into your graveyard this way";
+ this.staticText = "Mill X cards. Target player loses 2 life for each creature card put into your graveyard this way";
}
public LilianasIndignationEffect(final LilianasIndignationEffect effect) {
@@ -60,27 +57,28 @@ class LilianasIndignationEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- int x = source.getManaCostsToPay().getX();
- if (x > 0) {
- Cards cardsToGraveyard = new CardsImpl();
- cardsToGraveyard.addAll(controller.getLibrary().getTopCards(game, x));
- if (!cardsToGraveyard.isEmpty()) {
- Set movedCards = controller.moveCardsToGraveyardWithInfo(cardsToGraveyard.getCards(game), source, game, Zone.LIBRARY);
- Cards cardsMoved = new CardsImpl();
- cardsMoved.addAll(movedCards);
- int creatures = cardsMoved.count(StaticFilters.FILTER_CARD_CREATURE, game);
- if (creatures > 0) {
- Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
- if (targetPlayer != null) {
- targetPlayer.loseLife(creatures * 2, game, false);
- }
-
- }
- }
- }
+ if (controller == null) {
+ return false;
+ }
+ int xValue = source.getManaCostsToPay().getX();
+ if (xValue < 1) {
return true;
}
- return false;
+ int creatures = controller
+ .millCards(xValue, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(card -> game.getState().getZone(card.getId()) == Zone.GRAVEYARD)
+ .filter(MageObject::isCreature)
+ .mapToInt(x -> 2)
+ .sum();
+ if (creatures > 0) {
+ Player targetPlayer = game.getPlayer(source.getFirstTarget());
+ if (targetPlayer != null) {
+ targetPlayer.loseLife(creatures, game, false);
+ }
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/l/LilianasScorn.java b/Mage.Sets/src/mage/cards/l/LilianasScorn.java
new file mode 100644
index 00000000000..0b577a559c8
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LilianasScorn.java
@@ -0,0 +1,42 @@
+package mage.cards.l;
+
+import mage.abilities.effects.common.DestroyTargetEffect;
+import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.filter.FilterCard;
+import mage.filter.predicate.mageobject.NamePredicate;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LilianasScorn extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard("Liliana, Death Mage");
+
+ static {
+ filter.add(new NamePredicate("Liliana, Death Mage"));
+ }
+
+ public LilianasScorn(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}");
+
+ // Destroy target creature. You may search your library and/or graveyard for a card named Liliana, Death Mage, reveal it, and put it into your hand. If you search your library this way, shuffle it.
+ this.getSpellAbility().addEffect(new DestroyTargetEffect());
+ this.getSpellAbility().addEffect(new SearchLibraryGraveyardPutInHandEffect(filter, false, true));
+ this.getSpellAbility().addTarget(new TargetCreaturePermanent());
+ }
+
+ private LilianasScorn(final LilianasScorn card) {
+ super(card);
+ }
+
+ @Override
+ public LilianasScorn copy() {
+ return new LilianasScorn(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LilianasScrounger.java b/Mage.Sets/src/mage/cards/l/LilianasScrounger.java
new file mode 100644
index 00000000000..0553782b083
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LilianasScrounger.java
@@ -0,0 +1,90 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.condition.common.MorbidCondition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.counters.CounterType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPlaneswalkerPermanent;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.TargetPermanent;
+import mage.watchers.common.MorbidWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LilianasScrounger extends CardImpl {
+
+ public LilianasScrounger(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WIZARD);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(2);
+
+ // At the beginning of each end step, if a creature died this turn, you may put a loyalty counter on a Liliana planeswalker you control.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility(
+ new LilianasScroungerEffect(), TargetController.ANY, false
+ ), MorbidCondition.instance, "At the beginning of each end step, " +
+ "if a creature died this turn, you may put a loyalty counter on a Liliana planeswalker you control."
+ ), new MorbidWatcher());
+ }
+
+ private LilianasScrounger(final LilianasScrounger card) {
+ super(card);
+ }
+
+ @Override
+ public LilianasScrounger copy() {
+ return new LilianasScrounger(this);
+ }
+}
+
+class LilianasScroungerEffect extends OneShotEffect {
+
+ private static final FilterPermanent filter
+ = new FilterControlledPlaneswalkerPermanent(SubType.LILIANA, "Liliana planeswalker you control");
+
+ LilianasScroungerEffect() {
+ super(Outcome.Benefit);
+ }
+
+ private LilianasScroungerEffect(final LilianasScroungerEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public LilianasScroungerEffect copy() {
+ return new LilianasScroungerEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null || game.getBattlefield().count(
+ filter, source.getSourceId(), source.getControllerId(), game
+ ) < 1 || !player.chooseUse(
+ outcome, "Put a loyalty counter on a Liliana planeswalker you control?", source, game
+ )) {
+ return false;
+ }
+ TargetPermanent target = new TargetPermanent(0, 1, filter, true);
+ player.choose(outcome, target, source.getSourceId(), game);
+ Permanent permanent = game.getPermanent(target.getFirstTarget());
+ return permanent != null && permanent.addCounters(CounterType.LOYALTY.createInstance(), source, game);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LilianasStandardBearer.java b/Mage.Sets/src/mage/cards/l/LilianasStandardBearer.java
new file mode 100644
index 00000000000..791b089bbaf
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LilianasStandardBearer.java
@@ -0,0 +1,105 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.keyword.FlashAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.WatcherScope;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.ZoneChangeEvent;
+import mage.watchers.Watcher;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LilianasStandardBearer extends CardImpl {
+
+ public LilianasStandardBearer(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
+
+ this.subtype.add(SubType.ZOMBIE);
+ this.subtype.add(SubType.KNIGHT);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(1);
+
+ // Flash
+ this.addAbility(FlashAbility.getInstance());
+
+ // When Liliana's Standard Bearer enters the battlefield, draw X cards, where X is the number of creatures that died under your control this turn.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(
+ new DrawCardSourceControllerEffect(LilianasStandardBearerCount.instance)
+ .setText("draw X cards, where X is the number of creatures that died under your control this turn")
+ ), new LilianasStandardBearerWatcher());
+ }
+
+ private LilianasStandardBearer(final LilianasStandardBearer card) {
+ super(card);
+ }
+
+ @Override
+ public LilianasStandardBearer copy() {
+ return new LilianasStandardBearer(this);
+ }
+}
+
+enum LilianasStandardBearerCount implements DynamicValue {
+ instance;
+
+ @Override
+ public int calculate(Game game, Ability sourceAbility, Effect effect) {
+ LilianasStandardBearerWatcher watcher = game.getState().getWatcher(LilianasStandardBearerWatcher.class);
+ return watcher == null ? 0 : watcher.getCount(sourceAbility.getControllerId());
+ }
+
+ @Override
+ public LilianasStandardBearerCount copy() {
+ return instance;
+ }
+
+ @Override
+ public String getMessage() {
+ return "";
+ }
+}
+
+class LilianasStandardBearerWatcher extends Watcher {
+
+ private final Map playerMap = new HashMap<>();
+
+ LilianasStandardBearerWatcher() {
+ super(WatcherScope.GAME);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() != GameEvent.EventType.ZONE_CHANGE) {
+ return;
+ }
+ ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
+ if (zEvent.isDiesEvent() && zEvent.getTarget().isCreature()) {
+ playerMap.compute(zEvent.getTarget().getControllerId(), (u, i) -> i == null ? 1 : Integer.sum(i, 1));
+ }
+ }
+
+ @Override
+ public void reset() {
+ playerMap.clear();
+ super.reset();
+ }
+
+ int getCount(UUID playerId) {
+ return playerMap.getOrDefault(playerId, 0);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/l/LilianasSteward.java b/Mage.Sets/src/mage/cards/l/LilianasSteward.java
new file mode 100644
index 00000000000..9e7c7a5e4d3
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LilianasSteward.java
@@ -0,0 +1,47 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.ActivateAsSorceryActivatedAbility;
+import mage.abilities.costs.common.SacrificeSourceCost;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.effects.common.discard.DiscardTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.target.common.TargetOpponent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LilianasSteward extends CardImpl {
+
+ public LilianasSteward(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
+
+ this.subtype.add(SubType.ZOMBIE);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(2);
+
+ // {T}, Sacrifice Liliana's Steward: Target opponent discards a card. Activate this ability only any time you could cast a sorcery.
+ Ability ability = new ActivateAsSorceryActivatedAbility(
+ Zone.BATTLEFIELD, new DiscardTargetEffect(1), new TapSourceCost()
+ );
+ ability.addCost(new SacrificeSourceCost());
+ ability.addTarget(new TargetOpponent());
+ this.addAbility(ability);
+ }
+
+ private LilianasSteward(final LilianasSteward card) {
+ super(card);
+ }
+
+ @Override
+ public LilianasSteward copy() {
+ return new LilianasSteward(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LimDulsCohort.java b/Mage.Sets/src/mage/cards/l/LimDulsCohort.java
index fee4085bbd9..af21382902b 100644
--- a/Mage.Sets/src/mage/cards/l/LimDulsCohort.java
+++ b/Mage.Sets/src/mage/cards/l/LimDulsCohort.java
@@ -2,7 +2,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.CantBeRegeneratedTargetEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
@@ -25,7 +25,7 @@ public final class LimDulsCohort extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Lim-Dûl's Cohort blocks or becomes blocked by a creature, that creature can't be regenerated this turn.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(
new CantBeRegeneratedTargetEffect(Duration.EndOfTurn),
new FilterCreaturePermanent(),
false,
diff --git a/Mage.Sets/src/mage/cards/l/LimDulsPaladin.java b/Mage.Sets/src/mage/cards/l/LimDulsPaladin.java
index 27a88b67f1e..d2187c28db4 100644
--- a/Mage.Sets/src/mage/cards/l/LimDulsPaladin.java
+++ b/Mage.Sets/src/mage/cards/l/LimDulsPaladin.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.costs.common.DiscardTargetCost;
import mage.abilities.effects.Effect;
@@ -44,7 +44,7 @@ public final class LimDulsPaladin extends CardImpl {
// At the beginning of your upkeep, you may discard a card. If you don't, sacrifice Lim-Dul's Paladin and draw a card.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new LimDulsPaladinEffect(), TargetController.YOU, false));
// Whenever Lim-Dul's Paladin becomes blocked, it gets +6/+3 until end of turn.
- this.addAbility(new BecomesBlockedTriggeredAbility(new BoostSourceEffect(6, 3, Duration.EndOfTurn), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(6, 3, Duration.EndOfTurn), false));
// Whenever Lim-Dul's Paladin attacks and isn't blocked, it assigns no combat damage to defending player this turn and that player loses 4 life.
Effect effect = new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn);
effect.setText("it assigns no combat damage this turn");
diff --git a/Mage.Sets/src/mage/cards/l/LingeringSouls.java b/Mage.Sets/src/mage/cards/l/LingeringSouls.java
index e6d972cb4ef..0ebfd5ca775 100644
--- a/Mage.Sets/src/mage/cards/l/LingeringSouls.java
+++ b/Mage.Sets/src/mage/cards/l/LingeringSouls.java
@@ -1,7 +1,5 @@
-
package mage.cards.l;
-import java.util.UUID;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.FlashbackAbility;
@@ -11,18 +9,19 @@ import mage.constants.CardType;
import mage.constants.TimingRule;
import mage.game.permanent.token.SpiritWhiteToken;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class LingeringSouls extends CardImpl {
public LingeringSouls(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}");
// Create two 1/1 white Spirit creature tokens with flying.
- this.getSpellAbility().addEffect(new CreateTokenEffect(new SpiritWhiteToken("ISD"), 2));
+ this.getSpellAbility().addEffect(new CreateTokenEffect(new SpiritWhiteToken(), 2));
// Flashback {1}{B}
this.addAbility(new FlashbackAbility(new ManaCostsImpl("{1}{B}"), TimingRule.SORCERY));
}
diff --git a/Mage.Sets/src/mage/cards/l/LivingDeath.java b/Mage.Sets/src/mage/cards/l/LivingDeath.java
index 904c560c385..bfe880cbcab 100644
--- a/Mage.Sets/src/mage/cards/l/LivingDeath.java
+++ b/Mage.Sets/src/mage/cards/l/LivingDeath.java
@@ -76,13 +76,13 @@ class LivingDeathEffect extends OneShotEffect {
}
}
}
- game.applyEffects();
+ game.getState().processAction(game);
// Sacrifice all creatures
for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game)) {
permanent.sacrifice(source.getSourceId(), game);
}
- game.applyEffects();
+ game.getState().processAction(game);
// Exiled cards are put onto the battlefield at the same time under their owner's control
Set cardsToReturnFromExile = new HashSet<>();
diff --git a/Mage.Sets/src/mage/cards/l/LivingLightning.java b/Mage.Sets/src/mage/cards/l/LivingLightning.java
new file mode 100644
index 00000000000..d024eb6c2a3
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LivingLightning.java
@@ -0,0 +1,47 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DiesSourceTriggeredAbility;
+import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterCard;
+import mage.filter.common.FilterInstantOrSorceryCard;
+import mage.target.common.TargetCardInYourGraveyard;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LivingLightning extends CardImpl {
+
+ private static final FilterCard filter
+ = new FilterInstantOrSorceryCard("instant or sorcery card from your graveyard");
+
+ public LivingLightning(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
+
+ this.subtype.add(SubType.ELEMENTAL);
+ this.subtype.add(SubType.SHAMAN);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(2);
+
+ // When Living Lightning dies, return target instant or sorcery card from your graveyard to your hand.
+ Ability ability = new DiesSourceTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
+ ability.addTarget(new TargetCardInYourGraveyard(filter));
+ this.addAbility(ability);
+ }
+
+ private LivingLightning(final LivingLightning card) {
+ super(card);
+ }
+
+ @Override
+ public LivingLightning copy() {
+ return new LivingLightning(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LlanowarVisionary.java b/Mage.Sets/src/mage/cards/l/LlanowarVisionary.java
new file mode 100644
index 00000000000..d8bb2379130
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LlanowarVisionary.java
@@ -0,0 +1,42 @@
+package mage.cards.l;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.mana.GreenManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LlanowarVisionary extends CardImpl {
+
+ public LlanowarVisionary(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
+
+ this.subtype.add(SubType.ELF);
+ this.subtype.add(SubType.DRUID);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // When Llanowar Visionary enters the battlefield, draw a card.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)));
+
+ // {T}: Add {G}.
+ this.addAbility(new GreenManaAbility());
+ }
+
+ private LlanowarVisionary(final LlanowarVisionary card) {
+ super(card);
+ }
+
+ @Override
+ public LlanowarVisionary copy() {
+ return new LlanowarVisionary(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LoafingGiant.java b/Mage.Sets/src/mage/cards/l/LoafingGiant.java
index 0bffafbc682..2cd86e58f72 100644
--- a/Mage.Sets/src/mage/cards/l/LoafingGiant.java
+++ b/Mage.Sets/src/mage/cards/l/LoafingGiant.java
@@ -1,29 +1,31 @@
package mage.cards.l;
-import java.util.UUID;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AttacksOrBlocksTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PreventCombatDamageBySourceEffect;
-import mage.abilities.effects.common.combat.CantBeBlockedByAllSourceEffect;
-import mage.cards.Card;
-import mage.constants.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.filter.StaticFilters;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.game.Game;
import mage.players.Player;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author noahg
*/
public final class LoafingGiant extends CardImpl {
public LoafingGiant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}");
-
+
this.subtype.add(SubType.GIANT);
this.power = new MageInt(4);
this.toughness = new MageInt(6);
@@ -46,7 +48,7 @@ class LoafingGiantEffect extends OneShotEffect {
public LoafingGiantEffect() {
super(Outcome.UnboostCreature);
- this.staticText = "Put the top card of your library into your graveyard. If that card is a land card, prevent all combat damage {this} would deal this turn.";
+ this.staticText = "Mill a card. If a land card was milled this way, prevent all combat damage {this} would deal this turn.";
}
public LoafingGiantEffect(final LoafingGiantEffect effect) {
@@ -61,14 +63,14 @@ class LoafingGiantEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- Card card = player.getLibrary().getFromTop(game);
- if (card != null) {
- player.moveCards(card, Zone.GRAVEYARD, source, game);
- if (card.isLand()) {
- game.addEffect(new PreventCombatDamageBySourceEffect(Duration.EndOfTurn), source);
- }
- }
+ if (player != null
+ && player
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .anyMatch(MageObject::isLand)) {
+ game.addEffect(new PreventCombatDamageBySourceEffect(Duration.EndOfTurn), source);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/l/LoathsomeCatoblepas.java b/Mage.Sets/src/mage/cards/l/LoathsomeCatoblepas.java
index ad78c80979c..306d696d3a8 100644
--- a/Mage.Sets/src/mage/cards/l/LoathsomeCatoblepas.java
+++ b/Mage.Sets/src/mage/cards/l/LoathsomeCatoblepas.java
@@ -4,7 +4,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneSourceEffect;
@@ -41,7 +41,7 @@ public final class LoathsomeCatoblepas extends CardImpl {
// {2}{G}: Loathsome Catoblepas must be blocked this turn if able.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new MustBeBlockedByAtLeastOneSourceEffect(), new ManaCostsImpl("{2}{G}")));
// When Loathsome Catoblepas dies, target creature an opponent controls gets -3/-3 until end of turn.
- Ability ability = new DiesTriggeredAbility(new BoostTargetEffect(-3,-3, Duration.EndOfTurn), false);
+ Ability ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(-3,-3, Duration.EndOfTurn), false);
Target target = new TargetCreaturePermanent(filter);
ability.addTarget(target);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/l/LockjawSnapper.java b/Mage.Sets/src/mage/cards/l/LockjawSnapper.java
index 7fd25e75c72..9ec5b304c26 100644
--- a/Mage.Sets/src/mage/cards/l/LockjawSnapper.java
+++ b/Mage.Sets/src/mage/cards/l/LockjawSnapper.java
@@ -4,7 +4,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.WitherAbility;
import mage.cards.CardImpl;
@@ -34,7 +34,7 @@ public final class LockjawSnapper extends CardImpl {
this.addAbility(WitherAbility.getInstance());
// When Lockjaw Snapper dies, put a -1/-1 counter on each creature with a -1/-1 counter on it.
- this.addAbility(new DiesTriggeredAbility(new LockjawSnapperEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new LockjawSnapperEffect()));
}
diff --git a/Mage.Sets/src/mage/cards/l/LodestoneGolem.java b/Mage.Sets/src/mage/cards/l/LodestoneGolem.java
index 3121068d07a..0a75868adae 100644
--- a/Mage.Sets/src/mage/cards/l/LodestoneGolem.java
+++ b/Mage.Sets/src/mage/cards/l/LodestoneGolem.java
@@ -1,30 +1,30 @@
-
package mage.cards.l;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.costs.mana.GenericManaCost;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
-import mage.cards.Card;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.CostModificationType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.constants.Zone;
-import mage.game.Game;
+import mage.filter.FilterCard;
+import mage.filter.predicate.Predicates;
+
+import java.util.UUID;
/**
- *
* @author jeffwadsworth
*/
public final class LodestoneGolem extends CardImpl {
+ private static final FilterCard filter = new FilterCard("Nonartifact spells");
+
+ static {
+ filter.add(Predicates.not(CardType.ARTIFACT.getPredicate()));
+ }
+
public LodestoneGolem(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}");
this.subtype.add(SubType.GOLEM);
@@ -33,7 +33,7 @@ public final class LodestoneGolem extends CardImpl {
this.toughness = new MageInt(3);
// Nonartifact spells cost {1} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LodestoneGolemCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(1, filter, TargetController.ANY)));
}
public LodestoneGolem(final LodestoneGolem card) {
@@ -45,39 +45,3 @@ public final class LodestoneGolem extends CardImpl {
return new LodestoneGolem(this);
}
}
-
-class LodestoneGolemCostReductionEffect extends CostModificationEffectImpl {
-
- LodestoneGolemCostReductionEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Nonartifact spells cost {1} more to cast";
- }
-
- LodestoneGolemCostReductionEffect(LodestoneGolemCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- spellAbility.getManaCostsToPay().add(new GenericManaCost(1));
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- Card card = game.getCard(abilityToModify.getSourceId());
- if (card != null && !card.isArtifact()) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public LodestoneGolemCostReductionEffect copy() {
- return new LodestoneGolemCostReductionEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/l/LoftyDenial.java b/Mage.Sets/src/mage/cards/l/LoftyDenial.java
new file mode 100644
index 00000000000..30d834e78c8
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/l/LoftyDenial.java
@@ -0,0 +1,53 @@
+package mage.cards.l;
+
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.decorator.ConditionalOneShotEffect;
+import mage.abilities.effects.common.CounterUnlessPaysEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+import mage.target.TargetSpell;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class LoftyDenial extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
+
+ static {
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ }
+
+ private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
+
+ public LoftyDenial(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
+
+ // Counter target spell unless its controller pays {1}. If you control a creature with flying, counter that spell unless its controller pays {4} instead.
+ this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
+ new CounterUnlessPaysEffect(new GenericManaCost(4)),
+ new CounterUnlessPaysEffect(new GenericManaCost(1)),
+ condition, "counter target spell unless its controller pays {1}. " +
+ "If you control a creature with flying, counter that spell unless its controller pays {4} instead"
+ ));
+ this.getSpellAbility().addTarget(new TargetSpell());
+ }
+
+ private LoftyDenial(final LoftyDenial card) {
+ super(card);
+ }
+
+ @Override
+ public LoftyDenial copy() {
+ return new LoftyDenial(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/l/LoneRider.java b/Mage.Sets/src/mage/cards/l/LoneRider.java
index bfc95848545..db9fa6f0b0f 100644
--- a/Mage.Sets/src/mage/cards/l/LoneRider.java
+++ b/Mage.Sets/src/mage/cards/l/LoneRider.java
@@ -1,31 +1,34 @@
-
package mage.cards.l;
-import java.util.UUID;
-
import mage.MageInt;
-import mage.abilities.TriggeredAbility;
-import mage.abilities.common.OnEventTriggeredAbility;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.condition.Condition;
import mage.abilities.condition.common.YouGainedLifeCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.TransformSourceEffect;
+import mage.abilities.hint.ConditionHint;
+import mage.abilities.hint.Hint;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.ComparisonType;
-import mage.game.events.GameEvent;
+import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.watchers.common.PlayerGainedLifeWatcher;
+import java.util.UUID;
+
/**
* @author fireshoes
*/
public final class LoneRider extends CardImpl {
private static final String ruleText = "At the beginning of the end step, if you gained 3 or more life this turn, transform {this}";
+ private static final Condition condition = new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2);
+ private static final Hint hint = new ConditionHint(condition, "You gained 3 or more life this turn");
public LoneRider(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
@@ -45,11 +48,14 @@ public final class LoneRider extends CardImpl {
// At the beginning of the end step, if you gained 3 or more life this turn, transform Lone Rider.
this.addAbility(new TransformAbility());
- TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new TransformSourceEffect(true));
- this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2), ruleText), new PlayerGainedLifeWatcher());
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfEndStepTriggeredAbility(
+ new TransformSourceEffect(true), TargetController.NEXT, false
+ ), condition, ruleText
+ ), new PlayerGainedLifeWatcher());
}
- public LoneRider(final LoneRider card) {
+ private LoneRider(final LoneRider card) {
super(card);
}
@@ -57,4 +63,4 @@ public final class LoneRider extends CardImpl {
public LoneRider copy() {
return new LoneRider(this);
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/l/LongshotSquad.java b/Mage.Sets/src/mage/cards/l/LongshotSquad.java
index 42676ccb5b4..21f05d8648b 100644
--- a/Mage.Sets/src/mage/cards/l/LongshotSquad.java
+++ b/Mage.Sets/src/mage/cards/l/LongshotSquad.java
@@ -35,7 +35,7 @@ public final class LongshotSquad extends CardImpl {
public LongshotSquad(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.ARCHER);
this.power = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/l/LookoutsDispersal.java b/Mage.Sets/src/mage/cards/l/LookoutsDispersal.java
index ca432b80c01..c3b224a46c7 100644
--- a/Mage.Sets/src/mage/cards/l/LookoutsDispersal.java
+++ b/Mage.Sets/src/mage/cards/l/LookoutsDispersal.java
@@ -1,13 +1,13 @@
-
package mage.cards.l;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.CounterUnlessPaysEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -16,8 +16,9 @@ import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.target.TargetSpell;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class LookoutsDispersal extends CardImpl {
@@ -32,8 +33,10 @@ public final class LookoutsDispersal extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}");
// Lookout's Dispersal costs {1} less to cast if you control a Pirate.
- Ability ability = new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(1, new PermanentsOnTheBattlefieldCondition(filter)));
+ Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(1, condition));
ability.setRuleAtTheTop(true);
+ ability.addHint(new ConditionHint(condition, "You control a Pirate"));
this.addAbility(ability);
// Counter target spell unless its controller pays {4}.
diff --git a/Mage.Sets/src/mage/cards/l/LorescaleCoatl.java b/Mage.Sets/src/mage/cards/l/LorescaleCoatl.java
index 45a24b501ab..80077d3d8f5 100644
--- a/Mage.Sets/src/mage/cards/l/LorescaleCoatl.java
+++ b/Mage.Sets/src/mage/cards/l/LorescaleCoatl.java
@@ -1,8 +1,5 @@
-
-
package mage.cards.l;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DrawCardControllerTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@@ -12,25 +9,26 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class LorescaleCoatl extends CardImpl {
- public LorescaleCoatl (UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}{U}");
+ public LorescaleCoatl(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}");
this.subtype.add(SubType.SNAKE);
-
-
this.power = new MageInt(2);
this.toughness = new MageInt(2);
- this.addAbility(new DrawCardControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), true));
+ this.addAbility(new DrawCardControllerTriggeredAbility(
+ new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false
+ ));
}
- public LorescaleCoatl (final LorescaleCoatl card) {
+ private LorescaleCoatl(final LorescaleCoatl card) {
super(card);
}
@@ -38,4 +36,4 @@ public final class LorescaleCoatl extends CardImpl {
public LorescaleCoatl copy() {
return new LorescaleCoatl(this);
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/l/LoxodonSmiter.java b/Mage.Sets/src/mage/cards/l/LoxodonSmiter.java
index f43e90bebae..834e7544cdf 100644
--- a/Mage.Sets/src/mage/cards/l/LoxodonSmiter.java
+++ b/Mage.Sets/src/mage/cards/l/LoxodonSmiter.java
@@ -3,7 +3,7 @@ package mage.cards.l;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.DiscardOntoBattlefieldEffect;
import mage.cards.CardImpl;
@@ -26,7 +26,7 @@ public final class LoxodonSmiter extends CardImpl {
this.toughness = new MageInt(4);
// Loxodon Smiter can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// If a spell or ability an opponent controls causes you to discard Loxodon Smiter, put it onto the battlefield instead of putting it into your graveyard.
this.addAbility(new SimpleStaticAbility(Zone.HAND, new DiscardOntoBattlefieldEffect()));
diff --git a/Mage.Sets/src/mage/cards/l/LoyalCathar.java b/Mage.Sets/src/mage/cards/l/LoyalCathar.java
index 8282b63392d..8764ce01df9 100644
--- a/Mage.Sets/src/mage/cards/l/LoyalCathar.java
+++ b/Mage.Sets/src/mage/cards/l/LoyalCathar.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@@ -42,7 +42,7 @@ public final class LoyalCathar extends CardImpl {
// When Loyal Cathar dies, return it to the battlefield transformed under your control at the beginning of the next end step.
this.addAbility(new TransformAbility());
- this.addAbility(new DiesTriggeredAbility(new LoyalCatharEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new LoyalCatharEffect()));
}
public LoyalCathar(final LoyalCathar card) {
diff --git a/Mage.Sets/src/mage/cards/l/LurkingJackals.java b/Mage.Sets/src/mage/cards/l/LurkingJackals.java
index 4e292aad812..b46ee2691ac 100644
--- a/Mage.Sets/src/mage/cards/l/LurkingJackals.java
+++ b/Mage.Sets/src/mage/cards/l/LurkingJackals.java
@@ -110,7 +110,7 @@ class LurkingJackalsToken extends TokenImpl {
public LurkingJackalsToken() {
super("Hound", "3/2 Hound creature");
cardType.add(CardType.CREATURE);
- subtype.add(SubType.HOUND);
+ subtype.add(SubType.DOG);
power = new MageInt(3);
toughness = new MageInt(2);
}
diff --git a/Mage.Sets/src/mage/cards/l/LurrusOfTheDreamDen.java b/Mage.Sets/src/mage/cards/l/LurrusOfTheDreamDen.java
index 4fbb000772e..5500a93a93a 100644
--- a/Mage.Sets/src/mage/cards/l/LurrusOfTheDreamDen.java
+++ b/Mage.Sets/src/mage/cards/l/LurrusOfTheDreamDen.java
@@ -1,7 +1,11 @@
package mage.cards.l;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
+import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.AsThoughEffectImpl;
@@ -16,6 +20,7 @@ import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.common.FilterPermanentCard;
+import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ConvertedManaCostPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -24,10 +29,6 @@ import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.Watcher;
-import java.util.Set;
-import java.util.UUID;
-import mage.filter.predicate.Predicates;
-
/**
* @author TheElk801
*/
@@ -94,8 +95,8 @@ class LurrusOfTheDreamDenContinuousEffect extends ContinuousEffectImpl {
LurrusOfTheDreamDenContinuousEffect() {
super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit);
- staticText = "During each of your turns, you may cast one permanent spell " +
- "with converted mana cost 2 or less from your graveyard";
+ staticText = "During each of your turns, you may cast one permanent spell "
+ + "with converted mana cost 2 or less from your graveyard";
}
private LurrusOfTheDreamDenContinuousEffect(final LurrusOfTheDreamDenContinuousEffect effect) {
@@ -113,13 +114,16 @@ class LurrusOfTheDreamDenContinuousEffect extends ContinuousEffectImpl {
if (player == null) {
return false;
}
- if (!game.isActivePlayer(player.getId())) {
- return false;
- }
- for (Card card : player.getGraveyard().getCards(filter, game)) {
- ContinuousEffect effect = new LurrusOfTheDreamDenCastFromGraveyardEffect();
- effect.setTargetPointer(new FixedTarget(card, game));
- game.addEffect(effect, source);
+ if (game.isActivePlayer(player.getId())) {
+ LurrusOfTheDreamDenWatcher watcher = game.getState().getWatcher(LurrusOfTheDreamDenWatcher.class);
+ if (watcher != null && !watcher.isAbilityUsed(new MageObjectReference(source.getSourceId(), game))) {
+ // if not used yet, add effect per card in graveyard to cast it
+ for (Card card : player.getGraveyard().getCards(filter, game)) {
+ ContinuousEffect effect = new LurrusOfTheDreamDenCastFromGraveyardEffect();
+ effect.setTargetPointer(new FixedTarget(card, game));
+ game.addEffect(effect, source);
+ }
+ }
}
return true;
}
@@ -154,38 +158,40 @@ class LurrusOfTheDreamDenCastFromGraveyardEffect extends AsThoughEffectImpl {
if (!affectedControllerId.equals(source.getControllerId())) {
return false;
}
- LurrusOfTheDreamDenWatcher watcher = game.getState().getWatcher(LurrusOfTheDreamDenWatcher.class, source.getSourceId());
- return watcher != null && !watcher.isAbilityUsed();
+ LurrusOfTheDreamDenWatcher watcher = game.getState().getWatcher(LurrusOfTheDreamDenWatcher.class);
+ return watcher != null && !watcher.isAbilityUsed(new MageObjectReference(source.getSourceId(), game));
}
}
class LurrusOfTheDreamDenWatcher extends Watcher {
- private boolean abilityUsed = false;
+ private final Set abilityUsed = new HashSet<>();
LurrusOfTheDreamDenWatcher() {
- super(WatcherScope.CARD);
+ super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
- if (event.getType() != GameEvent.EventType.SPELL_CAST || event.getZone() != Zone.GRAVEYARD) {
+ if (event.getType() != GameEvent.EventType.SPELL_CAST
+ || event.getZone() != Zone.GRAVEYARD
+ || event.getAdditionalReference() == null) { // permitting source to cast from graveyard
return;
}
Spell spell = game.getSpell(event.getTargetId());
if (spell == null || !spell.isPermanent() || spell.getConvertedManaCost() > 2) {
return;
}
- abilityUsed = true;
+ abilityUsed.add(event.getAdditionalReference());
}
@Override
public void reset() {
super.reset();
- abilityUsed = false;
+ abilityUsed.clear();
}
- boolean isAbilityUsed() {
- return abilityUsed;
+ boolean isAbilityUsed(MageObjectReference mor) {
+ return abilityUsed.contains(mor);
}
}
diff --git a/Mage.Sets/src/mage/cards/m/MaalfeldTwins.java b/Mage.Sets/src/mage/cards/m/MaalfeldTwins.java
index 1d080c5ed46..b13f6cb1072 100644
--- a/Mage.Sets/src/mage/cards/m/MaalfeldTwins.java
+++ b/Mage.Sets/src/mage/cards/m/MaalfeldTwins.java
@@ -3,7 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class MaalfeldTwins extends CardImpl {
this.toughness = new MageInt(4);
// When Maalfeld Twins dies, create two 2/2 black Zombie creature tokens.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ZombieToken(), 2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new ZombieToken(), 2)));
}
public MaalfeldTwins(final MaalfeldTwins card) {
diff --git a/Mage.Sets/src/mage/cards/m/MadDog.java b/Mage.Sets/src/mage/cards/m/MadDog.java
index 17254366cdf..797f4cf6c3e 100644
--- a/Mage.Sets/src/mage/cards/m/MadDog.java
+++ b/Mage.Sets/src/mage/cards/m/MadDog.java
@@ -30,7 +30,7 @@ public final class MadDog extends CardImpl {
public MadDog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/m/MaelstromArchangel.java b/Mage.Sets/src/mage/cards/m/MaelstromArchangel.java
index fe3106b78c2..a02f430b5d1 100644
--- a/Mage.Sets/src/mage/cards/m/MaelstromArchangel.java
+++ b/Mage.Sets/src/mage/cards/m/MaelstromArchangel.java
@@ -53,11 +53,11 @@ public final class MaelstromArchangel extends CardImpl {
class MaelstromArchangelCastEffect extends OneShotEffect {
- private static final FilterCard filter = new FilterNonlandCard("nonland card from your hand");
+ private static final FilterCard filter = new FilterNonlandCard("spell from your hand");
public MaelstromArchangelCastEffect() {
super(Outcome.PlayForFree);
- this.staticText = "you may cast a nonland card from your hand without paying its mana cost";
+ this.staticText = "you may cast a spell from your hand without paying its mana cost";
}
public MaelstromArchangelCastEffect(final MaelstromArchangelCastEffect effect) {
@@ -75,7 +75,7 @@ class MaelstromArchangelCastEffect extends OneShotEffect {
if (controller != null) {
Target target = new TargetCardInHand(filter);
if (target.canChoose(source.getSourceId(), controller.getId(), game)
- && controller.chooseUse(outcome, "Cast a nonland card from your hand without paying its mana cost?", source, game)) {
+ && controller.chooseUse(outcome, "Cast a spell from your hand without paying its mana cost?", source, game)) {
Card cardToCast = null;
boolean cancel = false;
while (controller.canRespond() && !cancel) {
diff --git a/Mage.Sets/src/mage/cards/m/MagmaPhoenix.java b/Mage.Sets/src/mage/cards/m/MagmaPhoenix.java
index 06b95eb719a..848673d978a 100644
--- a/Mage.Sets/src/mage/cards/m/MagmaPhoenix.java
+++ b/Mage.Sets/src/mage/cards/m/MagmaPhoenix.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DamageEverythingEffect;
@@ -30,7 +30,7 @@ public final class MagmaPhoenix extends CardImpl {
this.toughness = new MageInt(3);
this.addAbility(FlyingAbility.getInstance());
- this.addAbility(new DiesTriggeredAbility(new DamageEverythingEffect(3), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DamageEverythingEffect(3), false));
this.addAbility(new SimpleActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), new ManaCostsImpl("{3}{R}{R}")));
}
diff --git a/Mage.Sets/src/mage/cards/m/MagmaSliver.java b/Mage.Sets/src/mage/cards/m/MagmaSliver.java
index eadc0ecd654..967629a898d 100644
--- a/Mage.Sets/src/mage/cards/m/MagmaSliver.java
+++ b/Mage.Sets/src/mage/cards/m/MagmaSliver.java
@@ -1,4 +1,3 @@
-
package mage.cards.m;
import java.util.UUID;
@@ -9,6 +8,7 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.dynamicvalue.common.StaticValue;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.cards.CardImpl;
@@ -35,11 +35,22 @@ public final class MagmaSliver extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(3);
- // All Slivers have "{tap}: Target Sliver creature gets +X/+0 until end of turn, where X is the number of Slivers on the battlefield."
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(new PermanentsOnBattlefieldCount(StaticFilters.FILTER_PERMANENT_CREATURE_SLIVERS), StaticValue.get(0), Duration.EndOfTurn, true), new TapSourceCost());
- Target target = new TargetCreaturePermanent(new FilterCreaturePermanent(SubType.SLIVER, "Sliver creature"));
+ // All Slivers have "{tap}: Target Sliver creature gets +X/+0 until end of turn,
+ // where X is the number of Slivers on the battlefield."
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
+ new BoostTargetEffect(new PermanentsOnBattlefieldCount(
+ StaticFilters.FILTER_PERMANENT_CREATURE_SLIVERS),
+ StaticValue.get(0), Duration.EndOfTurn, true),
+ new TapSourceCost());
+ Target target = new TargetCreaturePermanent(
+ new FilterCreaturePermanent(SubType.SLIVER, "Sliver creature"));
ability.addTarget(target);
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURE_SLIVERS)));
+ Effect effect = new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield,
+ StaticFilters.FILTER_PERMANENT_CREATURE_SLIVERS);
+ effect.setText("All Slivers have \"{T}: Target Sliver creature gets +X/+0 until end of turn,"
+ + "where X is the number of Slivers on the battlefield.\"");
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ effect));
}
public MagmaSliver(final MagmaSliver card) {
diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheBalance.java b/Mage.Sets/src/mage/cards/m/MagusOfTheBalance.java
index b5b386a5598..bea16480291 100644
--- a/Mage.Sets/src/mage/cards/m/MagusOfTheBalance.java
+++ b/Mage.Sets/src/mage/cards/m/MagusOfTheBalance.java
@@ -6,22 +6,12 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
-import mage.cards.*;
+import mage.abilities.effects.common.BalanceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.filter.FilterCard;
-import mage.filter.common.FilterControlledCreaturePermanent;
-import mage.filter.common.FilterControlledLandPermanent;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
-import mage.target.common.TargetCardInHand;
-import mage.target.common.TargetControlledPermanent;
-import java.util.HashMap;
-import java.util.Map;
import java.util.UUID;
/**
@@ -39,7 +29,7 @@ public final class MagusOfTheBalance extends CardImpl {
// {4}{W}, {T}, Sacrifice Magus of the Balance: Each player chooses a number of lands they control equal to the number of lands controlled by the player who controls the fewest, then sacrifices the rest. Players discard cards and sacrifice creatures the same way.
Ability ability = new SimpleActivatedAbility(
- new MagusOfTheBalanceEffect(),
+ new BalanceEffect(),
new ManaCostsImpl("{4}{W}")
);
ability.addCost(new TapSourceCost());
@@ -47,7 +37,7 @@ public final class MagusOfTheBalance extends CardImpl {
this.addAbility(ability);
}
- public MagusOfTheBalance(final MagusOfTheBalance card) {
+ private MagusOfTheBalance(final MagusOfTheBalance card) {
super(card);
}
@@ -56,139 +46,3 @@ public final class MagusOfTheBalance extends CardImpl {
return new MagusOfTheBalance(this);
}
}
-
-class MagusOfTheBalanceEffect extends OneShotEffect {
-
- MagusOfTheBalanceEffect() {
- super(Outcome.Sacrifice);
- staticText = "each player chooses a number of lands they control "
- + "equal to the number of lands controlled by the player "
- + "who controls the fewest, then sacrifices the rest. "
- + "Players discard cards and sacrifice creatures the same way";
- }
-
- MagusOfTheBalanceEffect(final MagusOfTheBalanceEffect effect) {
- super(effect);
- }
-
- @Override
- public MagusOfTheBalanceEffect copy() {
- return new MagusOfTheBalanceEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- //Lands
- int minLand = Integer.MAX_VALUE;
- Cards landsToSacrifice = new CardsImpl();
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int count = game.getBattlefield().countAll(new FilterControlledLandPermanent(), player.getId(), game);
- if (count < minLand) {
- minLand = count;
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- TargetControlledPermanent target = new TargetControlledPermanent(minLand, minLand, new FilterControlledLandPermanent("lands to keep"), true);
- if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) {
- for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledLandPermanent(), player.getId(), source.getSourceId(), game)) {
- if (permanent != null && !target.getTargets().contains(permanent.getId())) {
- landsToSacrifice.add(permanent);
- }
- }
- }
- }
- }
-
- for (UUID cardId : landsToSacrifice) {
- Permanent permanent = game.getPermanent(cardId);
- if (permanent != null) {
- permanent.sacrifice(source.getSourceId(), game);
- }
- }
-
- //Creatures
- int minCreature = Integer.MAX_VALUE;
- Cards creaturesToSacrifice = new CardsImpl();
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int count = game.getBattlefield().countAll(new FilterControlledCreaturePermanent(), player.getId(), game);
- if (count < minCreature) {
- minCreature = count;
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- TargetControlledPermanent target = new TargetControlledPermanent(minCreature, minCreature, new FilterControlledCreaturePermanent("creatures to keep"), true);
- if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) {
- for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), player.getId(), source.getSourceId(), game)) {
- if (permanent != null && !target.getTargets().contains(permanent.getId())) {
- creaturesToSacrifice.add(permanent);
- }
- }
- }
- }
- }
-
- for (UUID cardId : creaturesToSacrifice) {
- Permanent permanent = game.getPermanent(cardId);
- if (permanent != null) {
- permanent.sacrifice(source.getSourceId(), game);
- }
- }
-
- //Cards in hand
- int minCard = Integer.MAX_VALUE;
- Map cardsToDiscard = new HashMap<>(2);
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int count = player.getHand().size();
- if (count < minCard) {
- minCard = count;
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Cards cards = new CardsImpl();
- TargetCardInHand target = new TargetCardInHand(minCard, new FilterCard("cards to keep"));
- if (target.choose(Outcome.Discard, player.getId(), source.getSourceId(), game)) {
- for (Card card : player.getHand().getCards(game)) {
- if (card != null && !target.getTargets().contains(card.getId())) {
- cards.add(card);
- }
- }
- cardsToDiscard.put(playerId, cards);
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null && cardsToDiscard.get(playerId) != null) {
- for (UUID cardId : cardsToDiscard.get(playerId)) {
- Card card = game.getCard(cardId);
- player.discard(card, source, game);
-
- }
- }
- }
- return true;
- }
- return false;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java b/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java
index 26a6b6e3e2e..c3aa993fd2a 100644
--- a/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java
+++ b/Mage.Sets/src/mage/cards/m/MagusOfTheMind.java
@@ -1,4 +1,3 @@
-
package mage.cards.m;
import java.util.Set;
@@ -10,21 +9,19 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.AsThoughEffectImpl;
-import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
-import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.CastSpellLastTurnWatcher;
/**
@@ -79,7 +76,7 @@ class MagusOfTheMindEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class);
- if(watcher == null){
+ if (watcher == null) {
return false;
}
int stormCount = watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() + 1;
@@ -87,60 +84,10 @@ class MagusOfTheMindEffect extends OneShotEffect {
controller.shuffleLibrary(source, game);
if (controller.getLibrary().hasCards()) {
Set cards = controller.getLibrary().getTopCards(game, stormCount);
- if (cards != null) {
- for (Card card : cards) {
- if (card != null) {
- controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true);
- ContinuousEffect effect = new MagusOfTheMindCastFromExileEffect();
- effect.setTargetPointer(new FixedTarget(card.getId()));
- game.addEffect(effect, source);
- }
- }
- }
+ return PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(game, source, cards, TargetController.YOU, Duration.EndOfTurn, true);
}
return true;
}
return false;
}
}
-
-class MagusOfTheMindCastFromExileEffect extends AsThoughEffectImpl {
-
- MagusOfTheMindCastFromExileEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
- staticText = "you may play that card without paying its mana cost";
- }
-
- MagusOfTheMindCastFromExileEffect(final MagusOfTheMindCastFromExileEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public MagusOfTheMindCastFromExileEffect copy() {
- return new MagusOfTheMindCastFromExileEffect(this);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- if (objectId != null && objectId.equals(getTargetPointer().getFirst(game, source))) {
- if (affectedControllerId.equals(source.getControllerId())) {
- Card card = game.getCard(objectId);
- if (card != null && game.getState().getZone(objectId) == Zone.EXILED) {
- if (!card.isLand() && card.getSpellAbility().getCosts() != null) {
- Player player = game.getPlayer(affectedControllerId);
- if (player != null) {
- player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
- }
- }
- return true;
- }
- }
- }
- return false;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheScroll.java b/Mage.Sets/src/mage/cards/m/MagusOfTheScroll.java
index 71f059afe6d..3fd5ef28094 100644
--- a/Mage.Sets/src/mage/cards/m/MagusOfTheScroll.java
+++ b/Mage.Sets/src/mage/cards/m/MagusOfTheScroll.java
@@ -76,7 +76,7 @@ class MagusOfTheScrollEffect extends OneShotEffect {
}
revealed.add(card);
you.revealCards(sourceObject.getName(), revealed, game);
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
if (creature != null) {
creature.damage(2, source.getSourceId(), game, false, true);
diff --git a/Mage.Sets/src/mage/cards/m/MairsilThePretender.java b/Mage.Sets/src/mage/cards/m/MairsilThePretender.java
index 3a85125af05..3188b78a03d 100644
--- a/Mage.Sets/src/mage/cards/m/MairsilThePretender.java
+++ b/Mage.Sets/src/mage/cards/m/MairsilThePretender.java
@@ -46,10 +46,12 @@ public final class MairsilThePretender extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
- // When Mairsil, the Pretender enters the battlefield, you may exile an artifact or creature card from your hand or graveyard and put a cage counter on it.
+ // When Mairsil, the Pretender enters the battlefield, you may exile an artifact or creature card from your hand
+ // or graveyard and put a cage counter on it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new MairsilThePretenderExileEffect(), true));
- // Mairsil, the Pretender has all activated abilities of all cards you own in exile with cage counters on them. You may activate each of those abilities only once each turn.
+ // Mairsil, the Pretender has all activated abilities of all cards you own in exile with cage counters on them.
+ // You may activate each of those abilities only once each turn.
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new MairsilThePretenderGainAbilitiesEffect());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/MaleficScythe.java b/Mage.Sets/src/mage/cards/m/MaleficScythe.java
new file mode 100644
index 00000000000..d89b4cc62e7
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MaleficScythe.java
@@ -0,0 +1,58 @@
+package mage.cards.m;
+
+import mage.abilities.common.DiesAttachedTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CountersSourceCount;
+import mage.abilities.effects.common.continuous.BoostEquippedEffect;
+import mage.abilities.effects.common.counter.AddCountersSourceEffect;
+import mage.abilities.keyword.EquipAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class MaleficScythe extends CardImpl {
+
+ private static final DynamicValue xValue = new CountersSourceCount(CounterType.SOUL);
+
+ public MaleficScythe(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{B}");
+
+ this.subtype.add(SubType.EQUIPMENT);
+
+ // Malefic Scythe enters the battlefield with a soul counter on it.
+ this.addAbility(new EntersBattlefieldAbility(
+ new AddCountersSourceEffect(CounterType.SOUL.createInstance(1)),
+ "with a soul counter on it"
+ ));
+
+ // Equipped creature gets +1/+1 for each soul counter on Malefic Scythe.
+ this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(xValue, xValue, Duration.WhileOnBattlefield)));
+
+ // Whenever equipped creature dies, put a soul counter on Malefic Scythe.
+ this.addAbility(new DiesAttachedTriggeredAbility(
+ new AddCountersSourceEffect(CounterType.SOUL.createInstance()), "equipped"
+ ));
+
+ // Equip {1}
+ this.addAbility(new EquipAbility(1));
+ }
+
+ private MaleficScythe(final MaleficScythe card) {
+ super(card);
+ }
+
+ @Override
+ public MaleficScythe copy() {
+ return new MaleficScythe(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/m/MammothHarness.java b/Mage.Sets/src/mage/cards/m/MammothHarness.java
index aa126f999d0..0df36ee9cfc 100644
--- a/Mage.Sets/src/mage/cards/m/MammothHarness.java
+++ b/Mage.Sets/src/mage/cards/m/MammothHarness.java
@@ -3,7 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
@@ -61,7 +61,7 @@ public final class MammothHarness extends CardImpl {
}
}
-class MammothHarnessTriggeredAbility extends BlocksOrBecomesBlockedTriggeredAbility {
+class MammothHarnessTriggeredAbility extends BlocksOrBecomesBlockedSourceTriggeredAbility {
public MammothHarnessTriggeredAbility() {
super(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), StaticFilters.FILTER_PERMANENT_CREATURE, false, null, false);
diff --git a/Mage.Sets/src/mage/cards/m/ManaCache.java b/Mage.Sets/src/mage/cards/m/ManaCache.java
index 54cb19a0bac..be93b51c677 100644
--- a/Mage.Sets/src/mage/cards/m/ManaCache.java
+++ b/Mage.Sets/src/mage/cards/m/ManaCache.java
@@ -1,7 +1,5 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
@@ -27,8 +25,9 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author L_J
*/
public final class ManaCache extends CardImpl {
@@ -105,7 +104,7 @@ class ManaCacheManaAbility extends ActivatedManaAbilityImpl {
if (player != null && playerId.equals(game.getActivePlayerId()) && game.getStep().getType().isBefore(PhaseStep.END_TURN)) {
if (costs.canPay(this, sourceId, playerId, game)) {
this.setControllerId(playerId);
- return ActivationStatus.getTrue();
+ return ActivationStatus.getTrue(this, game);
}
}
return ActivationStatus.getFalse();
diff --git a/Mage.Sets/src/mage/cards/m/ManaClash.java b/Mage.Sets/src/mage/cards/m/ManaClash.java
index ef946eb3979..1232a402f80 100644
--- a/Mage.Sets/src/mage/cards/m/ManaClash.java
+++ b/Mage.Sets/src/mage/cards/m/ManaClash.java
@@ -1,5 +1,6 @@
package mage.cards.m;
+import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
@@ -10,8 +11,6 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
-import java.util.UUID;
-
/**
* @author LevelX2
*/
@@ -20,7 +19,8 @@ public final class ManaClash extends CardImpl {
public ManaClash(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}");
- // You and target opponent each flip a coin. Mana Clash deals 1 damage to each player whose coin comes up tails. Repeat this process until both players' coins come up heads on the same flip.
+ // You and target opponent each flip a coin. Mana Clash deals 1 damage to each player whose coin comes up tails.
+ // Repeat this process until both players' coins come up heads on the same flip.
this.getSpellAbility().addEffect(new ManaClashEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
}
diff --git a/Mage.Sets/src/mage/cards/m/MangaraTheDiplomat.java b/Mage.Sets/src/mage/cards/m/MangaraTheDiplomat.java
new file mode 100644
index 00000000000..6ecfbad160a
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MangaraTheDiplomat.java
@@ -0,0 +1,131 @@
+package mage.cards.m;
+
+import mage.MageInt;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.players.Player;
+import mage.watchers.common.CastSpellLastTurnWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class MangaraTheDiplomat extends CardImpl {
+
+ public MangaraTheDiplomat(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(4);
+
+ // Lifelink
+ this.addAbility(LifelinkAbility.getInstance());
+
+ // Whenever an opponent attacks with creatures, if two or more of those creatures are attacking you and/or a planeswalker you control, draw a card.
+ this.addAbility(new MangaraTheDiplomatAttackTriggeredAbility());
+
+ // Whenever an opponent casts their second spell each turn, draw a card.
+ this.addAbility(new MangaraTheDiplomatCastTriggeredAbility());
+ }
+
+ private MangaraTheDiplomat(final MangaraTheDiplomat card) {
+ super(card);
+ }
+
+ @Override
+ public MangaraTheDiplomat copy() {
+ return new MangaraTheDiplomat(this);
+ }
+}
+
+class MangaraTheDiplomatAttackTriggeredAbility extends TriggeredAbilityImpl {
+
+ MangaraTheDiplomatAttackTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1));
+ }
+
+ private MangaraTheDiplomatAttackTriggeredAbility(final MangaraTheDiplomatAttackTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ Player player = game.getPlayer(getControllerId());
+ return player != null
+ && player.hasOpponent(game.getActivePlayerId(), game)
+ && game
+ .getCombat()
+ .getAttackers()
+ .stream()
+ .map(uuid -> game.getCombat().getDefendingPlayerId(uuid, game))
+ .filter(getControllerId()::equals)
+ .count() >= 2;
+ }
+
+ @Override
+ public MangaraTheDiplomatAttackTriggeredAbility copy() {
+ return new MangaraTheDiplomatAttackTriggeredAbility(this);
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever an opponent attacks with creatures, " +
+ "if two or more of those creatures are attacking you " +
+ "and/or a planeswalker you control, draw a card.";
+ }
+}
+
+
+class MangaraTheDiplomatCastTriggeredAbility extends TriggeredAbilityImpl {
+
+ MangaraTheDiplomatCastTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1));
+ }
+
+ private MangaraTheDiplomatCastTriggeredAbility(final MangaraTheDiplomatCastTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.SPELL_CAST;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ Player player = game.getPlayer(getControllerId());
+ CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class);
+ return player != null
+ && watcher != null
+ && player.hasOpponent(event.getPlayerId(), game)
+ && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2;
+ }
+
+ @Override
+ public MangaraTheDiplomatCastTriggeredAbility copy() {
+ return new MangaraTheDiplomatCastTriggeredAbility(this);
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever an opponent casts their second spell each turn, draw a card.";
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/m/ManicScribe.java b/Mage.Sets/src/mage/cards/m/ManicScribe.java
index 26db45a69da..775f264a519 100644
--- a/Mage.Sets/src/mage/cards/m/ManicScribe.java
+++ b/Mage.Sets/src/mage/cards/m/ManicScribe.java
@@ -1,7 +1,5 @@
package mage.cards.m;
-import java.util.UUID;
-
import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -17,6 +15,8 @@ import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
+import java.util.UUID;
+
/**
* @author fireshoes
*/
@@ -30,19 +30,22 @@ public final class ManicScribe extends CardImpl {
this.toughness = new MageInt(3);
// When Manic Scribe enters the battlefield, each opponent puts the top three cards of their library into their graveyard.
- this.addAbility(new EntersBattlefieldTriggeredAbility(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(3, TargetController.OPPONENT), false));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(
+ new PutTopCardOfLibraryIntoGraveEachPlayerEffect(3, TargetController.OPPONENT), false
+ ));
// Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard,
// that player puts the top three cards of their library into their graveyard.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
- new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveTargetEffect(3), TargetController.OPPONENT, false, true),
- DeliriumCondition.instance,
- "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, "
- + "that player puts the top three cards of their library into their graveyard.")
- .addHint(DeliriumHint.instance));
+ new BeginningOfUpkeepTriggeredAbility(
+ Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveTargetEffect(3),
+ TargetController.OPPONENT, false, true
+ ), DeliriumCondition.instance, "Delirium — At the beginning of each opponent's upkeep, " +
+ "if there are four or more card types among cards in your graveyard, that player mills three cards."
+ ).addHint(DeliriumHint.instance));
}
- public ManicScribe(final ManicScribe card) {
+ private ManicScribe(final ManicScribe card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/m/MarduWoeReaper.java b/Mage.Sets/src/mage/cards/m/MarduWoeReaper.java
index c87fd0e5086..4a9e2061ccc 100644
--- a/Mage.Sets/src/mage/cards/m/MarduWoeReaper.java
+++ b/Mage.Sets/src/mage/cards/m/MarduWoeReaper.java
@@ -1,45 +1,46 @@
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.TriggeredAbilityImpl;
-import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
+import mage.abilities.effects.common.ExileTargetEffect;
+import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.constants.Zone;
-import mage.filter.common.FilterCreatureCard;
-import mage.game.Game;
-import mage.game.events.GameEvent;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
+import mage.filter.FilterPermanent;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInGraveyard;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class MarduWoeReaper extends CardImpl {
+ private static final FilterPermanent filter = new FilterPermanent(SubType.WARRIOR, "Warrior");
+
public MarduWoeReaper(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// Whenever Mardu Woe-Reaper or another Warrior enters the battlefield under your control, you may exile target creature card from a graveyard. If you do, you gain 1 life.
- Ability ability = new MarduWoeReaperTriggeredAbility();
- ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard")));
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new ExileTargetEffect("exile target creature card from a graveyard.")
+ , filter, true, true
+ );
+ ability.addEffect(new GainLifeEffect(1).concatBy("If you do,"));
+ ability.addTarget(new TargetCardInGraveyard(StaticFilters.FILTER_CARD_CREATURE));
this.addAbility(ability);
}
- public MarduWoeReaper(final MarduWoeReaper card) {
+ private MarduWoeReaper(final MarduWoeReaper card) {
super(card);
}
@@ -48,70 +49,3 @@ public final class MarduWoeReaper extends CardImpl {
return new MarduWoeReaper(this);
}
}
-
-class MarduWoeReaperTriggeredAbility extends TriggeredAbilityImpl {
-
- MarduWoeReaperTriggeredAbility() {
- super(Zone.BATTLEFIELD, new MarduWoeReaperEffect(), true);
- }
-
- MarduWoeReaperTriggeredAbility(final MarduWoeReaperTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public MarduWoeReaperTriggeredAbility copy() {
- return new MarduWoeReaperTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- if (event.getPlayerId().equals(this.getControllerId())) {
- Permanent permanent = game.getPermanent(event.getTargetId());
- if (permanent != null && (permanent.getId().equals(this.getSourceId()) || permanent.hasSubtype(SubType.WARRIOR, game))) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public String getRule() {
- return "Whenever {this} or another Warrior enters the battlefield under your control, " + super.getRule();
- }
-}
-
-class MarduWoeReaperEffect extends OneShotEffect {
-
- MarduWoeReaperEffect() {
- super(Outcome.GainLife);
- this.staticText = "you may exile target creature card from a graveyard. If you do, you gain 1 life";
- }
-
- MarduWoeReaperEffect(final MarduWoeReaperEffect effect) {
- super(effect);
- }
-
- @Override
- public MarduWoeReaperEffect copy() {
- return new MarduWoeReaperEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getControllerId());
- Card card = game.getCard(this.getTargetPointer().getFirst(game, source));
- if (player != null && card != null) {
- if (player.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.GRAVEYARD, true)) {
- player.gainLife(1, game, source);
- }
- return true;
- }
- return false;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/m/MaritLagesSlumber.java b/Mage.Sets/src/mage/cards/m/MaritLagesSlumber.java
index 4588829ab93..5f2890ac7d1 100644
--- a/Mage.Sets/src/mage/cards/m/MaritLagesSlumber.java
+++ b/Mage.Sets/src/mage/cards/m/MaritLagesSlumber.java
@@ -1,7 +1,7 @@
package mage.cards.m;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.costs.common.SacrificeSourceCost;
@@ -27,7 +27,7 @@ import java.util.UUID;
public final class MaritLagesSlumber extends CardImpl {
private static final FilterPermanent filter
- = new FilterControlledPermanent("{this} or another snow permanent");
+ = new FilterControlledPermanent("snow permanent");
static {
filter.add(SuperType.SNOW.getPredicate());
@@ -43,7 +43,9 @@ public final class MaritLagesSlumber extends CardImpl {
this.addSuperType(SuperType.SNOW);
// Whenever Marit Lage's Slumber or another snow permanent enters the battlefield under your control, scry 1.
- this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new ScryEffect(1), filter));
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new ScryEffect(1), filter, false, true
+ ));
// At the beginning of your upkeep, if you control ten or more snow permanents, sacrifice Marit Lage's Slumber. If you do, create Marit Lage, a legendary 20/20 black Avatar creature token with flying and indestructible.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
diff --git a/Mage.Sets/src/mage/cards/m/MarkerBeetles.java b/Mage.Sets/src/mage/cards/m/MarkerBeetles.java
index 4e4f6b2af89..14c4c857480 100644
--- a/Mage.Sets/src/mage/cards/m/MarkerBeetles.java
+++ b/Mage.Sets/src/mage/cards/m/MarkerBeetles.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -31,7 +31,7 @@ public final class MarkerBeetles extends CardImpl {
this.toughness = new MageInt(3);
// When Marker Beetles dies, target creature gets +1/+1 until end of turn.
- Ability ability = new DiesTriggeredAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), false);
+ Ability ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), false);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
// {2}, Sacrifice Marker Beetles: Draw a card.
diff --git a/Mage.Sets/src/mage/cards/m/MarrowGnawer.java b/Mage.Sets/src/mage/cards/m/MarrowGnawer.java
index cdf48890efc..487d5f3e4cb 100644
--- a/Mage.Sets/src/mage/cards/m/MarrowGnawer.java
+++ b/Mage.Sets/src/mage/cards/m/MarrowGnawer.java
@@ -2,7 +2,6 @@
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -21,6 +20,8 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.game.permanent.token.RatToken;
import mage.target.common.TargetControlledPermanent;
+import java.util.UUID;
+
/**
*
* @author LevelX
@@ -50,9 +51,10 @@ public final class MarrowGnawer extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(FearAbility.getInstance(), Duration.WhileOnBattlefield, filterFear)));
// {T}, Sacrifice a Rat: create X 1/1 black Rat creature tokens, where X is the number of Rats you control.
- Ability ability;
- ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new RatToken(),new PermanentsOnBattlefieldCount(filter3)), new SacrificeTargetCost(new TargetControlledPermanent(filterSacrifice)));
- ability.addCost(new TapSourceCost());
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
+ new CreateTokenEffect(new RatToken(), new PermanentsOnBattlefieldCount(filter3, null)),
+ new TapSourceCost());
+ ability.addCost( new SacrificeTargetCost(new TargetControlledPermanent(filterSacrifice)));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/MarshmistTitan.java b/Mage.Sets/src/mage/cards/m/MarshmistTitan.java
index 71df001f009..8c380f606ef 100644
--- a/Mage.Sets/src/mage/cards/m/MarshmistTitan.java
+++ b/Mage.Sets/src/mage/cards/m/MarshmistTitan.java
@@ -1,16 +1,15 @@
package mage.cards.m;
import mage.MageInt;
-import mage.Mana;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.DevotionCount;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
import java.util.UUID;
@@ -26,9 +25,11 @@ public final class MarshmistTitan extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(5);
- // Marshmist Titan costs {X} less to cast, where X is your devotion to black.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new MarshmistTitanCostReductionEffect())
- .addHint(DevotionCount.B.getHint()));
+ // This spell costs {X} less to cast, where X is your devotion to black.
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(DevotionCount.B));
+ ability.addHint(DevotionCount.B.getHint());
+ this.addAbility(ability);
+
}
private MarshmistTitan(final MarshmistTitan card) {
@@ -40,40 +41,3 @@ public final class MarshmistTitan extends CardImpl {
return new MarshmistTitan(this);
}
}
-
-class MarshmistTitanCostReductionEffect extends CostModificationEffectImpl {
-
- MarshmistTitanCostReductionEffect() {
- super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {X} less to cast, where X is your devotion to black. " +
- "(Each {B} in the mana costs of permanents you control counts toward your devotion to black.) ";
- }
-
- private MarshmistTitanCostReductionEffect(final MarshmistTitanCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- Mana mana = spellAbility.getManaCostsToPay().getMana();
- if (mana.getGeneric() == 0) {
- return false;
- }
- int count = DevotionCount.B.calculate(game, source, this);
- mana.setGeneric(Math.max(mana.getGeneric() - count, 0));
- spellAbility.getManaCostsToPay().load(mana.toString());
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- return abilityToModify instanceof SpellAbility
- && abilityToModify.getSourceId().equals(source.getSourceId());
- }
-
- @Override
- public MarshmistTitanCostReductionEffect copy() {
- return new MarshmistTitanCostReductionEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/m/MartyrForTheCause.java b/Mage.Sets/src/mage/cards/m/MartyrForTheCause.java
index 19a17d1ec8a..0cf33c2cd76 100644
--- a/Mage.Sets/src/mage/cards/m/MartyrForTheCause.java
+++ b/Mage.Sets/src/mage/cards/m/MartyrForTheCause.java
@@ -1,7 +1,7 @@
package mage.cards.m;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.ProliferateEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class MartyrForTheCause extends CardImpl {
this.toughness = new MageInt(2);
// When Martyr for the Cause dies, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
- this.addAbility(new DiesTriggeredAbility(new ProliferateEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new ProliferateEffect()));
}
private MartyrForTheCause(final MartyrForTheCause card) {
diff --git a/Mage.Sets/src/mage/cards/m/MartyrOfBones.java b/Mage.Sets/src/mage/cards/m/MartyrOfBones.java
index a90e986f1b8..dd47c908df9 100644
--- a/Mage.Sets/src/mage/cards/m/MartyrOfBones.java
+++ b/Mage.Sets/src/mage/cards/m/MartyrOfBones.java
@@ -1,4 +1,3 @@
-
package mage.cards.m;
import mage.MageInt;
@@ -11,7 +10,6 @@ import mage.abilities.costs.VariableCostImpl;
import mage.abilities.costs.common.RevealTargetFromHandCost;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -19,6 +17,7 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.players.Player;
@@ -41,13 +40,12 @@ public final class MartyrOfBones extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
- //TODO: Make ability properly copiable
+ // TODO: Make ability properly copiable
// {1}, Reveal X black cards from your hand, Sacrifice Martyr of Bones: Exile up to X target cards from a single graveyard.
- Effect effect = new ExileTargetEffect(null, null, Zone.GRAVEYARD);
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(1));
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new GenericManaCost(1));
ability.addCost(new RevealVariableBlackCardsFromHandCost());
ability.addCost(new SacrificeSourceCost());
- ability.addTarget(new TargetCardInASingleGraveyard(0, 1, new FilterCard("cards in a single graveyard")));
+ ability.addTarget(new TargetCardInASingleGraveyard(0, 1, StaticFilters.FILTER_CARD_CARDS));
ability.setTargetAdjuster(MartyrOfBonesAdjuster.instance);
this.addAbility(ability);
}
@@ -74,7 +72,7 @@ enum MartyrOfBonesAdjuster implements TargetAdjuster {
}
}
ability.getTargets().clear();
- ability.addTarget(new TargetCardInASingleGraveyard(0, amount, new FilterCard()));
+ ability.addTarget(new TargetCardInASingleGraveyard(0, amount, StaticFilters.FILTER_CARD_CARDS));
}
}
diff --git a/Mage.Sets/src/mage/cards/m/MartyrOfDusk.java b/Mage.Sets/src/mage/cards/m/MartyrOfDusk.java
index 5e3591429d5..fcbdf48f5d7 100644
--- a/Mage.Sets/src/mage/cards/m/MartyrOfDusk.java
+++ b/Mage.Sets/src/mage/cards/m/MartyrOfDusk.java
@@ -3,7 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class MartyrOfDusk extends CardImpl {
this.toughness = new MageInt(1);
// When Martyr of Dusk dies, create a 1/1 white Vampire creature token with lifelink.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new IxalanVampireToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new IxalanVampireToken())));
}
public MartyrOfDusk(final MartyrOfDusk card) {
diff --git a/Mage.Sets/src/mage/cards/m/Martyrdom.java b/Mage.Sets/src/mage/cards/m/Martyrdom.java
index 067ad072787..a693c43277d 100644
--- a/Mage.Sets/src/mage/cards/m/Martyrdom.java
+++ b/Mage.Sets/src/mage/cards/m/Martyrdom.java
@@ -66,7 +66,7 @@ class MartyrdomGainAbilityTargetEffect extends ContinuousEffectImpl {
if (permanent != null) {
ActivatedAbilityImpl ability = new MartyrdomActivatedAbility(source.getControllerId());
ability.setMayActivate(TargetController.ANY);
- permanent.addAbility(ability, source.getSourceId(), game, false);
+ permanent.addAbility(ability, source.getSourceId(), game);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/m/MaskOfImmolation.java b/Mage.Sets/src/mage/cards/m/MaskOfImmolation.java
index 97688431cdd..60cb9da3b83 100644
--- a/Mage.Sets/src/mage/cards/m/MaskOfImmolation.java
+++ b/Mage.Sets/src/mage/cards/m/MaskOfImmolation.java
@@ -16,7 +16,7 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import mage.game.permanent.token.YoungPyromancerElementalToken;
+import mage.game.permanent.token.RedElementalToken;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
@@ -59,7 +59,7 @@ public final class MaskOfImmolation extends CardImpl {
class MaskOfImmolationEffect extends CreateTokenEffect {
MaskOfImmolationEffect() {
- super(new YoungPyromancerElementalToken());
+ super(new RedElementalToken());
staticText = "create a 1/1 red Elemental creature token, then attach {this} to it.";
}
diff --git a/Mage.Sets/src/mage/cards/m/MaskedBlackguard.java b/Mage.Sets/src/mage/cards/m/MaskedBlackguard.java
new file mode 100644
index 00000000000..345956e6ce6
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MaskedBlackguard.java
@@ -0,0 +1,46 @@
+package mage.cards.m;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.keyword.FlashAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class MaskedBlackguard extends CardImpl {
+
+ public MaskedBlackguard(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.ROGUE);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // Flash
+ this.addAbility(FlashAbility.getInstance());
+
+ // {2}{B}: Masked Blackguard gets +1/+1 until end of turn.
+ this.addAbility(new SimpleActivatedAbility(
+ new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{2}{B}")
+ ));
+ }
+
+ private MaskedBlackguard(final MaskedBlackguard card) {
+ super(card);
+ }
+
+ @Override
+ public MaskedBlackguard copy() {
+ return new MaskedBlackguard(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/m/MasterThief.java b/Mage.Sets/src/mage/cards/m/MasterThief.java
index f7125665443..c71f95d1a2c 100644
--- a/Mage.Sets/src/mage/cards/m/MasterThief.java
+++ b/Mage.Sets/src/mage/cards/m/MasterThief.java
@@ -1,4 +1,3 @@
-
package mage.cards.m;
import java.util.UUID;
@@ -11,9 +10,10 @@ import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
+import mage.constants.SubType;
import mage.target.common.TargetArtifactPermanent;
+import mage.watchers.common.LostControlWatcher;
/**
* @author Loki, JayDi85
@@ -33,9 +33,10 @@ public final class MasterThief extends CardImpl {
new GainControlTargetEffect(Duration.Custom),
new SourceOnBattlefieldControlUnchangedCondition(),
"gain control of target artifact for as long as you control {this}"),
- false);
+ false);
ability.addTarget(new TargetArtifactPermanent());
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/MathasFiendSeeker.java b/Mage.Sets/src/mage/cards/m/MathasFiendSeeker.java
index 97ef3aca9a8..e8c020953ce 100644
--- a/Mage.Sets/src/mage/cards/m/MathasFiendSeeker.java
+++ b/Mage.Sets/src/mage/cards/m/MathasFiendSeeker.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardAllEffect;
@@ -54,7 +54,7 @@ public final class MathasFiendSeeker extends CardImpl {
// At the beginning of your end step, put a bounty counter on target creature an opponent controls. For as long as that creature has a bounty counter on it, it has "When this creature dies, each opponent draws a card and gains 2 life."
Ability ability = new BeginningOfYourEndStepTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()), false);
ability.addTarget(new TargetCreaturePermanent(filter));
- Ability ability2 = new DiesTriggeredAbility(new DrawCardAllEffect(1, TargetController.OPPONENT));
+ Ability ability2 = new DiesSourceTriggeredAbility(new DrawCardAllEffect(1, TargetController.OPPONENT));
ability2.addEffect(new OpponentsGainLifeEffect());
Effect effect = new MathasFiendSeekerGainAbilityEffect(ability2, Duration.Custom, rule);
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/m/MatterReshaper.java b/Mage.Sets/src/mage/cards/m/MatterReshaper.java
index 164315f45e1..5d4455be7ca 100644
--- a/Mage.Sets/src/mage/cards/m/MatterReshaper.java
+++ b/Mage.Sets/src/mage/cards/m/MatterReshaper.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
@@ -34,7 +34,7 @@ public final class MatterReshaper extends CardImpl {
// When Matter Reshaper dies, reveal the top card of your library. You may put that card onto the battlefield
// if it's a permanent card with converted mana cost 3 or less. Otherwise, put that card into your hand.
- this.addAbility(new DiesTriggeredAbility(new MatterReshaperEffect(), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new MatterReshaperEffect(), false));
}
public MatterReshaper(final MatterReshaper card) {
diff --git a/Mage.Sets/src/mage/cards/m/MausoleumGuard.java b/Mage.Sets/src/mage/cards/m/MausoleumGuard.java
index e25cd9df41c..0d64b008ce7 100644
--- a/Mage.Sets/src/mage/cards/m/MausoleumGuard.java
+++ b/Mage.Sets/src/mage/cards/m/MausoleumGuard.java
@@ -1,9 +1,7 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -11,13 +9,15 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.game.permanent.token.SpiritWhiteToken;
+import java.util.UUID;
+
/**
* @author nantuko
*/
public final class MausoleumGuard extends CardImpl {
public MausoleumGuard(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SCOUT);
@@ -25,7 +25,7 @@ public final class MausoleumGuard extends CardImpl {
this.toughness = new MageInt(2);
// When Mausoleum Guard dies, create two 1/1 white Spirit creature tokens with flying.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken("ISD"), 2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken(), 2)));
}
public MausoleumGuard(final MausoleumGuard card) {
diff --git a/Mage.Sets/src/mage/cards/m/MayaelsAria.java b/Mage.Sets/src/mage/cards/m/MayaelsAria.java
index 027b039b671..2344735fc15 100644
--- a/Mage.Sets/src/mage/cards/m/MayaelsAria.java
+++ b/Mage.Sets/src/mage/cards/m/MayaelsAria.java
@@ -75,7 +75,7 @@ class MayaelsAriaEffect extends OneShotEffect {
creature.addCounters(CounterType.P1P1.createInstance(), source, game);
}
}
- game.applyEffects(); // needed because otehrwise the +1/+1 counters wouldn't be taken into account
+ game.getState().processAction(game); // needed because otehrwise the +1/+1 counters wouldn't be taken into account
// Then you gain 10 life if you control a creature with power 10 or greater.
filter = new FilterCreaturePermanent();
diff --git a/Mage.Sets/src/mage/cards/m/MazemindTome.java b/Mage.Sets/src/mage/cards/m/MazemindTome.java
new file mode 100644
index 00000000000..282b220a4ee
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MazemindTome.java
@@ -0,0 +1,86 @@
+package mage.cards.m;
+
+import mage.abilities.Ability;
+import mage.abilities.StateTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.ExileSourceCost;
+import mage.abilities.costs.common.PutCountersSourceCost;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.keyword.ScryEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Zone;
+import mage.counters.CounterType;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class MazemindTome extends CardImpl {
+
+ public MazemindTome(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
+
+ // {T}, Put a page counter on Mazemind Tome: Scry 1.
+ Ability ability = new SimpleActivatedAbility(new ScryEffect(1), new TapSourceCost());
+ ability.addCost(new PutCountersSourceCost(CounterType.PAGE.createInstance()));
+ this.addAbility(ability);
+
+ // {2}, {T}, Put a page counter on Mazemind Tome: Draw a card.
+ ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(2));
+ ability.addCost(new TapSourceCost());
+ ability.addCost(new PutCountersSourceCost(CounterType.PAGE.createInstance()));
+ this.addAbility(ability);
+
+ // When there are four or more page counters on Mazemind Tome, exile it. If you do, you gain 4 life.
+ this.addAbility(new MazemindTomeTriggeredAbility());
+ }
+
+ private MazemindTome(final MazemindTome card) {
+ super(card);
+ }
+
+ @Override
+ public MazemindTome copy() {
+ return new MazemindTome(this);
+ }
+}
+
+class MazemindTomeTriggeredAbility extends StateTriggeredAbility {
+
+ MazemindTomeTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new DoIfCostPaid(
+ new GainLifeEffect(4), new ExileSourceCost(), null, false
+ ));
+ }
+
+ private MazemindTomeTriggeredAbility(final MazemindTomeTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public MazemindTomeTriggeredAbility copy() {
+ return new MazemindTomeTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ Permanent permanent = game.getPermanent(getSourceId());
+ return permanent != null && permanent.getCounters(game).getCount(CounterType.PAGE) >= 4;
+ }
+
+ @Override
+ public String getRule() {
+ return "When there are four or more page counters on {this}, exile it. If you do, you gain 4 life.";
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/m/MeddlingMage.java b/Mage.Sets/src/mage/cards/m/MeddlingMage.java
index c2afa5dce53..cd912639bc9 100644
--- a/Mage.Sets/src/mage/cards/m/MeddlingMage.java
+++ b/Mage.Sets/src/mage/cards/m/MeddlingMage.java
@@ -1,6 +1,5 @@
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@@ -10,17 +9,15 @@ import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
+import mage.util.CardUtil;
+
+import java.util.UUID;
/**
- *
* @author Plopman
*/
public final class MeddlingMage extends CardImpl {
@@ -33,10 +30,10 @@ public final class MeddlingMage extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
- // As Meddling Mage enters the battlefield, name a nonland card.
+ // As Meddling Mage enters the battlefield, choose a nonland card name.
this.addAbility(new AsEntersBattlefieldAbility(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME)));
- //The named card can't be cast.
+ // Spells with the chosen name can't be cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MeddlingMageReplacementEffect()));
}
@@ -75,21 +72,22 @@ class MeddlingMageReplacementEffect extends ContinuousRuleModifyingEffectImpl {
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
- return "You can't cast a spell with that name (" + mageObject.getLogName() + " in play).";
+ return "You can't cast a spell with that name (" + mageObject.getName() + " in play).";
}
return null;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
- return event.getType() == EventType.CAST_SPELL;
+ return event.getType() == EventType.CAST_SPELL_LATE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
- // fixes issue #1072
- return object != null && !object.isCopy() && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY));
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ return object != null
+ && !object.isCopy()
+ && CardUtil.haveSameNames(object, cardName, game);
}
-
}
diff --git a/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java b/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java
index 3c6124c9463..7565cfdca9d 100644
--- a/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java
+++ b/Mage.Sets/src/mage/cards/m/MeliraSylvokOutcast.java
@@ -149,7 +149,7 @@ class MeliraSylvokOutcastEffect3 extends ContinuousEffectImpl {
Set opponents = game.getOpponents(source.getControllerId());
for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
if (opponents.contains(perm.getControllerId())) {
- perm.getAbilities().remove(InfectAbility.getInstance());
+ perm.removeAbility(InfectAbility.getInstance(), source.getSourceId(), game);
}
}
return true;
diff --git a/Mage.Sets/src/mage/cards/m/Memnarch.java b/Mage.Sets/src/mage/cards/m/Memnarch.java
index 75129bda421..09a585fdfeb 100644
--- a/Mage.Sets/src/mage/cards/m/Memnarch.java
+++ b/Mage.Sets/src/mage/cards/m/Memnarch.java
@@ -1,4 +1,3 @@
-
package mage.cards.m;
import java.util.UUID;
@@ -12,8 +11,8 @@ import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
+import mage.constants.SubType;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.target.TargetPermanent;
@@ -26,7 +25,7 @@ import mage.target.common.TargetArtifactPermanent;
public final class Memnarch extends CardImpl {
public Memnarch(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{7}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.WIZARD);
@@ -34,7 +33,7 @@ public final class Memnarch extends CardImpl {
this.toughness = new MageInt(5);
// {1}{U}{U}: Target permanent becomes an artifact in addition to its other types.
- Effect effect = new AddCardTypeTargetEffect(Duration.WhileOnBattlefield, CardType.ARTIFACT);
+ Effect effect = new AddCardTypeTargetEffect(Duration.Custom, CardType.ARTIFACT);
effect.setText("Target permanent becomes an artifact in addition to its other types");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{U}{U}"));
ability.addTarget(new TargetPermanent());
@@ -46,8 +45,12 @@ public final class Memnarch extends CardImpl {
this.addAbility(ability2);
}
- public Memnarch(final Memnarch card){ super(card); }
+ public Memnarch(final Memnarch card) {
+ super(card);
+ }
@Override
- public Memnarch copy() { return new Memnarch(this); }
+ public Memnarch copy() {
+ return new Memnarch(this);
+ }
}
diff --git a/Mage.Sets/src/mage/cards/m/MemoryErosion.java b/Mage.Sets/src/mage/cards/m/MemoryErosion.java
index dc6bfd720c8..5aa6273b58d 100644
--- a/Mage.Sets/src/mage/cards/m/MemoryErosion.java
+++ b/Mage.Sets/src/mage/cards/m/MemoryErosion.java
@@ -68,7 +68,7 @@ class SpellCastTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever an opponent casts a spell, that player puts the top two cards of their library into their graveyard";
+ return "Whenever an opponent casts a spell, that player mills two cards";
}
@Override
diff --git a/Mage.Sets/src/mage/cards/m/MemorysJourney.java b/Mage.Sets/src/mage/cards/m/MemorysJourney.java
index a54963a8037..4893700f1b1 100644
--- a/Mage.Sets/src/mage/cards/m/MemorysJourney.java
+++ b/Mage.Sets/src/mage/cards/m/MemorysJourney.java
@@ -10,6 +10,7 @@ import mage.abilities.keyword.FlashbackAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TimingRule;
@@ -65,24 +66,9 @@ class MemorysJourneyEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getFirstTarget());
- if (player != null) {
- List targets = source.getTargets().get(1).getTargets();
- boolean shuffle = false;
- for (UUID targetId : targets) {
- Card card = game.getCard(targetId);
- if (card != null) {
- if (player.getGraveyard().contains(card.getId())) {
- player.getGraveyard().remove(card);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- shuffle = true;
- }
- }
- }
- if (shuffle) {
- player.shuffleLibrary(source, game);
- }
- return true;
+ Player targetPlayer = game.getPlayer(source.getFirstTarget());
+ if (targetPlayer != null) {
+ return targetPlayer.shuffleCardsToLibrary(new CardsImpl(source.getTargets().get(1).getTargets()), game, source);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/m/MephiticOoze.java b/Mage.Sets/src/mage/cards/m/MephiticOoze.java
index a89562f39e7..f90dbcc6d73 100644
--- a/Mage.Sets/src/mage/cards/m/MephiticOoze.java
+++ b/Mage.Sets/src/mage/cards/m/MephiticOoze.java
@@ -1,45 +1,37 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
+import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.common.FilterControlledPermanent;
+
+import java.util.UUID;
/**
- *
* @author fireshoes
*/
public final class MephiticOoze extends CardImpl {
- private static final FilterControlledPermanent filter = new FilterControlledPermanent("artifact you control");
-
- static {
- filter.add(CardType.ARTIFACT.getPredicate());
- }
-
public MephiticOoze(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
this.subtype.add(SubType.OOZE);
this.power = new MageInt(0);
this.toughness = new MageInt(5);
// Mephitic Ooze gets +1/+0 for each artifact you control.
- Effect effect = new BoostSourceEffect(new PermanentsOnBattlefieldCount(filter), StaticValue.get(0), Duration.WhileOnBattlefield);
- effect.setText("{this} gets +1/+0 for each artifact you control");
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
+ Effect effect = new BoostSourceEffect(ArtifactYouControlCount.instance, StaticValue.get(0), Duration.WhileOnBattlefield);
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect).addHint(ArtifactYouControlHint.instance));
// Whenever Mephitic Ooze deals combat damage to a creature, destroy that creature. The creature can't be regenerated.
this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(new DestroyTargetEffect(true), false, true));
diff --git a/Mage.Sets/src/mage/cards/m/MerfolkSeer.java b/Mage.Sets/src/mage/cards/m/MerfolkSeer.java
index f7eef20f977..66de865d953 100644
--- a/Mage.Sets/src/mage/cards/m/MerfolkSeer.java
+++ b/Mage.Sets/src/mage/cards/m/MerfolkSeer.java
@@ -3,7 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
@@ -26,7 +26,7 @@ public final class MerfolkSeer extends CardImpl {
this.toughness = new MageInt(2);
// When Merfolk Seer dies, you may pay {1}{U}. If you do, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{1}{U}"))));
+ this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{1}{U}"))));
}
public MerfolkSeer(final MerfolkSeer card) {
diff --git a/Mage.Sets/src/mage/cards/m/MeriekeRiBerit.java b/Mage.Sets/src/mage/cards/m/MeriekeRiBerit.java
index 1e2a0c4a5f0..7e20fbf9282 100644
--- a/Mage.Sets/src/mage/cards/m/MeriekeRiBerit.java
+++ b/Mage.Sets/src/mage/cards/m/MeriekeRiBerit.java
@@ -1,4 +1,3 @@
-
package mage.cards.m;
import java.util.UUID;
@@ -25,6 +24,7 @@ import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;
+import mage.watchers.common.LostControlWatcher;
/**
*
@@ -50,6 +50,7 @@ public final class MeriekeRiBerit extends CardImpl {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, MeriekeRiBeritGainControlEffect, new TapSourceCost());
ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("target creature")));
ability.addEffect(new MeriekeRiBeritCreateDelayedTriggerEffect());
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/MesmericOrb.java b/Mage.Sets/src/mage/cards/m/MesmericOrb.java
index 6b8608259b9..9dae5bf385f 100644
--- a/Mage.Sets/src/mage/cards/m/MesmericOrb.java
+++ b/Mage.Sets/src/mage/cards/m/MesmericOrb.java
@@ -1,9 +1,7 @@
package mage.cards.m;
-import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -15,22 +13,21 @@ import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class MesmericOrb extends CardImpl {
public MesmericOrb(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// Whenever a permanent becomes untapped, that permanent's controller puts the top card of their library into their graveyard.
- Effect effect = new PutTopCardOfLibraryIntoGraveTargetEffect(1);
- effect.setText("that permanent's controller puts the top card of their library into their graveyard");
- this.addAbility(new BecomesUntappedPermanentTriggeredAbility(effect, false));
+ this.addAbility(new MesmericOrbTriggeredAbility());
}
- public MesmericOrb(final MesmericOrb card) {
+ private MesmericOrb(final MesmericOrb card) {
super(card);
}
@@ -40,19 +37,19 @@ public final class MesmericOrb extends CardImpl {
}
}
-class BecomesUntappedPermanentTriggeredAbility extends TriggeredAbilityImpl{
+class MesmericOrbTriggeredAbility extends TriggeredAbilityImpl {
- public BecomesUntappedPermanentTriggeredAbility(Effect effect, boolean optional) {
- super(Zone.BATTLEFIELD, effect, optional);
+ MesmericOrbTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveTargetEffect(1), false);
}
- public BecomesUntappedPermanentTriggeredAbility(final BecomesUntappedPermanentTriggeredAbility ability) {
+ private MesmericOrbTriggeredAbility(final MesmericOrbTriggeredAbility ability) {
super(ability);
}
@Override
- public BecomesUntappedPermanentTriggeredAbility copy() {
- return new BecomesUntappedPermanentTriggeredAbility(this);
+ public MesmericOrbTriggeredAbility copy() {
+ return new MesmericOrbTriggeredAbility(this);
}
@Override
@@ -72,7 +69,7 @@ class BecomesUntappedPermanentTriggeredAbility extends TriggeredAbilityImpl{
@Override
public String getRule() {
- return "Whenever a permanent becomes untapped, " + super.getRule();
+ return "Whenever a permanent becomes untapped, that permanent's controller mills a card.";
}
}
diff --git a/Mage.Sets/src/mage/cards/m/MessengerDrake.java b/Mage.Sets/src/mage/cards/m/MessengerDrake.java
index 1c15bcf7b2b..d2b1c1e81a7 100644
--- a/Mage.Sets/src/mage/cards/m/MessengerDrake.java
+++ b/Mage.Sets/src/mage/cards/m/MessengerDrake.java
@@ -3,7 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class MessengerDrake extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Messenger Drake dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1)));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)));
}
public MessengerDrake(final MessengerDrake card) {
diff --git a/Mage.Sets/src/mage/cards/m/MetalworkColossus.java b/Mage.Sets/src/mage/cards/m/MetalworkColossus.java
index 6052cf4bb79..47895a12a52 100644
--- a/Mage.Sets/src/mage/cards/m/MetalworkColossus.java
+++ b/Mage.Sets/src/mage/cards/m/MetalworkColossus.java
@@ -39,7 +39,7 @@ public final class MetalworkColossus extends CardImpl {
this.toughness = new MageInt(10);
// Metalwork Colossus costs {X} less to cast, where X is the total converted mana cost of noncreature artifacts you control.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new MetalworkColossusCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new MetalworkColossusCostReductionEffect()));
// Sacrifice two artifacts: Return Metalwork Colossus from your graveyard to your hand.
this.addAbility(new SimpleActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), new SacrificeTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledArtifactPermanent("two artifacts"), true))));
diff --git a/Mage.Sets/src/mage/cards/m/MidnightHaunting.java b/Mage.Sets/src/mage/cards/m/MidnightHaunting.java
index d54a8eef61e..93e947eacdf 100644
--- a/Mage.Sets/src/mage/cards/m/MidnightHaunting.java
+++ b/Mage.Sets/src/mage/cards/m/MidnightHaunting.java
@@ -1,25 +1,24 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.game.permanent.token.SpiritWhiteToken;
+import java.util.UUID;
+
/**
- *
* @author nantuko
*/
public final class MidnightHaunting extends CardImpl {
public MidnightHaunting(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
// Create two 1/1 white Spirit creature tokens with flying.
- this.getSpellAbility().addEffect(new CreateTokenEffect(new SpiritWhiteToken("ISD"), 2));
+ this.getSpellAbility().addEffect(new CreateTokenEffect(new SpiritWhiteToken(), 2));
}
public MidnightHaunting(final MidnightHaunting card) {
diff --git a/Mage.Sets/src/mage/cards/m/MidnightOil.java b/Mage.Sets/src/mage/cards/m/MidnightOil.java
index 954d3408969..97280100aea 100644
--- a/Mage.Sets/src/mage/cards/m/MidnightOil.java
+++ b/Mage.Sets/src/mage/cards/m/MidnightOil.java
@@ -1,14 +1,11 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.BeginningOfDrawTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
-import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.DiscardCardControllerTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect;
@@ -20,42 +17,48 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.TargetController;
-import mage.constants.Zone;
-import mage.counters.Counter;
import mage.counters.CounterType;
-import mage.game.Game;
-import mage.game.events.GameEvent;
-import mage.game.events.GameEvent.EventType;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class MidnightOil extends CardImpl {
public MidnightOil(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}");
// Midnight Oil enters the battlefield with seven hour counters on it.
- this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(new Counter(CounterType.HOUR.createInstance(7))),
- "with seven hour counters on it"));
+ this.addAbility(new EntersBattlefieldAbility(
+ new AddCountersSourceEffect(
+ CounterType.HOUR.createInstance(7)
+ ), "with seven hour counters on it"
+ ));
// At the beginning of your draw step, draw an additional card and remove two hour counters from Midnight Oil.
- Ability ability = new BeginningOfDrawTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.YOU, false);
- Effect effect = new RemoveCounterSourceEffect(CounterType.HOUR.createInstance(2));
- effect.setText("and remove two hour counters from {this}");
- ability.addEffect(effect);
+ Ability ability = new BeginningOfDrawTriggeredAbility(
+ new DrawCardSourceControllerEffect(1),
+ TargetController.YOU, false
+ );
+ ability.addEffect(new RemoveCounterSourceEffect(
+ CounterType.HOUR.createInstance(2)
+ ).concatBy("and"));
this.addAbility(ability);
// Your maximum hand size is equal to the number of hour counters on Midnight Oil.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MaximumHandSizeControllerEffect(new CountersSourceCount(CounterType.HOUR), Duration.WhileOnBattlefield, HandSizeModification.SET, TargetController.YOU)));
+ this.addAbility(new SimpleStaticAbility(new MaximumHandSizeControllerEffect(
+ new CountersSourceCount(CounterType.HOUR), Duration.WhileOnBattlefield,
+ HandSizeModification.SET, TargetController.YOU
+ ).setText("your maximum hand size is equal to the number of hour counters on {this}")));
// Whenever you discard a card, you lose 1 life.
- this.addAbility(new MidnightOilTriggeredAbility(new LoseLifeSourceControllerEffect(1)));
-
+ this.addAbility(new DiscardCardControllerTriggeredAbility(
+ new LoseLifeSourceControllerEffect(1), false
+ ));
}
- public MidnightOil(final MidnightOil card) {
+ private MidnightOil(final MidnightOil card) {
super(card);
}
@@ -64,35 +67,3 @@ public final class MidnightOil extends CardImpl {
return new MidnightOil(this);
}
}
-
-class MidnightOilTriggeredAbility extends TriggeredAbilityImpl {
-
- MidnightOilTriggeredAbility(Effect effect) {
- super(Zone.BATTLEFIELD, effect, false);
- }
-
- MidnightOilTriggeredAbility(final MidnightOilTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public MidnightOilTriggeredAbility copy() {
- return new MidnightOilTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == EventType.DISCARDED_CARD;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return isControlledBy(event.getPlayerId());
-
- }
-
- @Override
- public String getRule() {
- return "Whenever you discard a card, " + super.getRule();
- }
-}
diff --git a/Mage.Sets/src/mage/cards/m/MinamosMeddling.java b/Mage.Sets/src/mage/cards/m/MinamosMeddling.java
index bed01234fde..11887b5046f 100644
--- a/Mage.Sets/src/mage/cards/m/MinamosMeddling.java
+++ b/Mage.Sets/src/mage/cards/m/MinamosMeddling.java
@@ -1,7 +1,5 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
@@ -10,29 +8,27 @@ import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
-import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetSpell;
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class MinamosMeddling extends CardImpl {
public MinamosMeddling(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}{U}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}");
// Counter target spell. That spell's controller reveals their hand, then discards each card with the same name as a card spliced onto that spell.
- this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL));
this.getSpellAbility().addEffect(new MinamosMeddlingCounterTargetEffect());
+ this.getSpellAbility().addTarget(new TargetSpell());
}
- public MinamosMeddling(final MinamosMeddling card) {
+ private MinamosMeddling(final MinamosMeddling card) {
super(card);
}
@@ -44,12 +40,12 @@ public final class MinamosMeddling extends CardImpl {
class MinamosMeddlingCounterTargetEffect extends OneShotEffect {
- public MinamosMeddlingCounterTargetEffect() {
+ MinamosMeddlingCounterTargetEffect() {
super(Outcome.Benefit);
staticText = "Counter target spell. That spell's controller reveals their hand, then discards each card with the same name as a card spliced onto that spell";
}
- public MinamosMeddlingCounterTargetEffect(final MinamosMeddlingCounterTargetEffect effect) {
+ private MinamosMeddlingCounterTargetEffect(final MinamosMeddlingCounterTargetEffect effect) {
super(effect);
}
@@ -61,36 +57,34 @@ class MinamosMeddlingCounterTargetEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
MageObject sourceObject = game.getObject(source.getSourceId());
- if (sourceObject != null) {
- for (UUID targetId : getTargetPointer().getTargets(game, source) ) {
- Spell spell = game.getStack().getSpell(targetId);
- if (spell != null) {
- game.getStack().counter(targetId, source.getSourceId(), game);
- Player spellController = game.getPlayer(spell.getControllerId());
- if (spellController != null) {
- spellController.revealCards(sourceObject.getName(), spellController.getHand(), game);
- Cards cardsToDiscard = new CardsImpl();
- for (SpellAbility spellAbility : spell.getSpellAbilities()) {
- if (spellAbility.getSpellAbilityType() == SpellAbilityType.SPLICE) {
- for (Card card: spellController.getHand().getCards(game)) {
- if (card.getName().equals(spellAbility.getCardName())) {
- cardsToDiscard.add(card);
- }
- }
- }
- }
- if (!cardsToDiscard.isEmpty()) {
- for (Card card :cardsToDiscard.getCards(game)) {
- spellController.discard(card, source, game);
- }
+ if (sourceObject == null) {
+ return false;
+ }
+ for (UUID targetId : getTargetPointer().getTargets(game, source)) {
+ Spell spell = game.getStack().getSpell(targetId);
+ if (spell == null) {
+ continue;
+ }
+ game.getStack().counter(targetId, source.getSourceId(), game);
+ Player spellController = game.getPlayer(spell.getControllerId());
+ if (spellController == null) {
+ continue;
+ }
+ spellController.revealCards(sourceObject.getName(), spellController.getHand(), game);
+ Cards cardsToDiscard = new CardsImpl();
+ for (SpellAbility spellAbility : spell.getSpellAbilities()) {
+ if (spellAbility.getSpellAbilityType() == SpellAbilityType.SPLICE) {
+ for (Card card : spellController.getHand().getCards(game)) {
+ if (card.getName().equals(spellAbility.getCardName())) {
+ cardsToDiscard.add(card);
}
}
-
}
}
- return true;
+ if (!cardsToDiscard.isEmpty()) {
+ spellController.discard(cardsToDiscard, source, game);
+ }
}
- return false;
+ return true;
}
-
}
diff --git a/Mage.Sets/src/mage/cards/m/MindBomb.java b/Mage.Sets/src/mage/cards/m/MindBomb.java
index 16074428a2e..4fa1119c70c 100644
--- a/Mage.Sets/src/mage/cards/m/MindBomb.java
+++ b/Mage.Sets/src/mage/cards/m/MindBomb.java
@@ -3,7 +3,10 @@ package mage.cards.m;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.*;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
@@ -28,7 +31,7 @@ public final class MindBomb extends CardImpl {
this.getSpellAbility().addEffect(new MindBombEffect());
}
- public MindBomb(final MindBomb card) {
+ private MindBomb(final MindBomb card) {
super(card);
}
@@ -40,13 +43,13 @@ public final class MindBomb extends CardImpl {
class MindBombEffect extends OneShotEffect {
- public MindBombEffect() {
+ MindBombEffect() {
super(Outcome.Neutral);
this.staticText = "Each player may discard up to three cards."
+ " {this} deals damage to each player equal to 3 minus the number of cards they discarded this way";
}
- public MindBombEffect(final MindBombEffect effect) {
+ private MindBombEffect(final MindBombEffect effect) {
super(effect);
}
@@ -59,48 +62,44 @@ class MindBombEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
- if (controller != null && sourceObject != null) {
- Map cardsToDiscard = new HashMap<>();
-
- // choose
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Cards cards = new CardsImpl();
- Target target = new TargetDiscard(0, 3, new FilterCard(), playerId);
- player.chooseTarget(outcome, target, source, game);
- cards.addAll(target.getTargets());
- cardsToDiscard.put(playerId, cards);
- }
- }
-
- // discard
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Cards cardsPlayer = cardsToDiscard.get(playerId);
- if (cardsPlayer != null) {
- for (UUID cardId : cardsPlayer) {
- Card card = game.getCard(cardId);
- player.discard(card, source, game);
-
- }
- }
- }
- }
-
- // damage
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Cards cardsPlayer = cardsToDiscard.get(playerId);
- if (cardsPlayer != null) {
- player.damage(3 - cardsPlayer.size(), source.getId(), game);
- }
- }
- }
- return true;
+ if (controller == null || sourceObject == null) {
+ return false;
}
- return false;
+ Map cardsToDiscard = new HashMap<>();
+
+ // choose
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
+ }
+ Cards cards = new CardsImpl();
+ Target target = new TargetDiscard(0, 3, new FilterCard(), playerId);
+ player.chooseTarget(Outcome.Discard, target, source, game);
+ cards.addAll(target.getTargets());
+ cardsToDiscard.put(playerId, cards);
+ }
+
+ // discard
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player != null) {
+ Cards cardsPlayer = cardsToDiscard.get(playerId);
+ cardsToDiscard.put(playerId, player.discard(cardsPlayer, source, game));
+ }
+ }
+
+ // damage
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
+ }
+ Cards cardsPlayer = cardsToDiscard.get(playerId);
+ if (cardsPlayer != null) {
+ player.damage(3 - cardsPlayer.size(), source.getId(), game);
+ }
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/m/MindExtraction.java b/Mage.Sets/src/mage/cards/m/MindExtraction.java
index 485c0fa3808..7a377321463 100644
--- a/Mage.Sets/src/mage/cards/m/MindExtraction.java
+++ b/Mage.Sets/src/mage/cards/m/MindExtraction.java
@@ -99,9 +99,7 @@ class MindExtractionEffect extends OneShotEffect {
.stream()
.filter(card -> card.getColor(game).shares(color))
.forEach(toDiscard::add);
- toDiscard.getCards(game)
- .stream()
- .forEach(card -> player.discard(card, source, game));
+ player.discard(toDiscard, source, game);
return true;
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/m/MindMaggots.java b/Mage.Sets/src/mage/cards/m/MindMaggots.java
index e98e414ce8b..c68088cb883 100644
--- a/Mage.Sets/src/mage/cards/m/MindMaggots.java
+++ b/Mage.Sets/src/mage/cards/m/MindMaggots.java
@@ -1,25 +1,26 @@
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.counter.AddCountersSourceEffect;
-import mage.cards.Card;
-import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.Game;
+import mage.game.permanent.Permanent;
import mage.players.Player;
-import mage.target.common.TargetCardInHand;
+import mage.target.TargetCard;
+import mage.target.common.TargetDiscard;
+
+import java.util.UUID;
/**
- *
* @author jeffwadsworth
*/
public final class MindMaggots extends CardImpl {
@@ -34,10 +35,9 @@ public final class MindMaggots extends CardImpl {
// When Mind Maggots enters the battlefield, discard any number of creature cards.
// For each card discarded this way, put two +1/+1 counters on Mind Maggots.
this.addAbility(new EntersBattlefieldTriggeredAbility(new MindMaggotsEffect()));
-
}
- public MindMaggots(final MindMaggots card) {
+ private MindMaggots(final MindMaggots card) {
super(card);
}
@@ -51,10 +51,11 @@ class MindMaggotsEffect extends OneShotEffect {
MindMaggotsEffect() {
super(Outcome.BoostCreature);
- this.staticText = "discard any number of creature cards. For each card discarded this way, put two +1/+1 counters on {this}";
+ this.staticText = "discard any number of creature cards. " +
+ "For each card discarded this way, put two +1/+1 counters on {this}";
}
- MindMaggotsEffect(final MindMaggotsEffect effect) {
+ private MindMaggotsEffect(final MindMaggotsEffect effect) {
super(effect);
}
@@ -66,23 +67,17 @@ class MindMaggotsEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- int numToDiscard = controller.getAmount(0,
- controller.getHand().getCards(StaticFilters.FILTER_CARD_CREATURE, game).size(),
- "Discard how many creature cards?",
- game);
- TargetCardInHand target = new TargetCardInHand(numToDiscard, StaticFilters.FILTER_CARD_CREATURE);
- if (controller.choose(Outcome.Benefit, target, source.getSourceId(), game)) {
- for (UUID targetId : target.getTargets()) {
- Card card = game.getCard(targetId);
- if (card != null
- && controller.discard(card, source, game)) {
- new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)).apply(game, source);
- }
- }
- }
+ if (controller == null) {
+ return false;
+ }
+ TargetCard target = new TargetDiscard(0, Integer.MAX_VALUE, StaticFilters.FILTER_CARD_CREATURE, controller.getId());
+ controller.choose(outcome, controller.getHand(), target, game);
+ int counters = controller.discard(new CardsImpl(target.getTargets()), source, game).size();
+ Permanent permanent = game.getPermanent(source.getSourceId());
+ if (permanent == null || counters < 1) {
return true;
}
- return false;
+ permanent.addCounters(CounterType.P1P1.createInstance(counters), source, game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/m/MindWarp.java b/Mage.Sets/src/mage/cards/m/MindWarp.java
index afef657aebd..e67eddd1c41 100644
--- a/Mage.Sets/src/mage/cards/m/MindWarp.java
+++ b/Mage.Sets/src/mage/cards/m/MindWarp.java
@@ -1,21 +1,18 @@
-
package mage.cards.m;
import mage.abilities.Ability;
-import mage.abilities.dynamicvalue.DynamicValue;
-import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
+import mage.target.common.TargetCardInHand;
import java.util.UUID;
@@ -28,11 +25,11 @@ public final class MindWarp extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{3}{B}");
// Look at target player's hand and choose X cards from it. That player discards those cards.
- this.getSpellAbility().addEffect(new MindWarpEffect(ManacostVariableValue.instance));
+ this.getSpellAbility().addEffect(new MindWarpEffect());
this.getSpellAbility().addTarget(new TargetPlayer());
}
- public MindWarp(final MindWarp card) {
+ private MindWarp(final MindWarp card) {
super(card);
}
@@ -44,39 +41,27 @@ public final class MindWarp extends CardImpl {
class MindWarpEffect extends OneShotEffect {
- private final DynamicValue xValue;
-
- public MindWarpEffect(DynamicValue xValue) {
+ MindWarpEffect() {
super(Outcome.Discard);
- this.xValue = xValue;
- staticText = "Look at target player's hand and choose X cards from it. That player discards those card.";
+ staticText = "Look at target player's hand and choose X cards from it. That player discards those cards.";
}
- public MindWarpEffect(final MindWarpEffect effect) {
+ private MindWarpEffect(final MindWarpEffect effect) {
super(effect);
- this.xValue = effect.xValue;
}
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(source.getFirstTarget());
Player you = game.getPlayer(source.getControllerId());
- if (targetPlayer != null && you != null) {
- int amountToDiscard = Math.min(
- xValue.calculate(game, source, this),
- targetPlayer.getHand().size()
- );
- you.lookAtCards("Discard", targetPlayer.getHand(), game);
- TargetCard target = new TargetCard(amountToDiscard, Zone.HAND, new FilterCard());
- target.setNotTarget(true);
- if (you.choose(Outcome.Benefit, targetPlayer.getHand(), target, game)) {
- Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
- return targetPlayer.discard(card, source, game);
-
- }
-
+ if (targetPlayer == null || you == null) {
+ return false;
}
- return false;
+ int amountToDiscard = source.getManaCostsToPay().getX();
+ TargetCard target = new TargetCardInHand(amountToDiscard, StaticFilters.FILTER_CARD_CARDS);
+ you.choose(outcome, targetPlayer.getHand(), target, game);
+ targetPlayer.discard(new CardsImpl(target.getTargets()), source, game);
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/m/Mindcrank.java b/Mage.Sets/src/mage/cards/m/Mindcrank.java
index 435ee718a66..f2610c32dc5 100644
--- a/Mage.Sets/src/mage/cards/m/Mindcrank.java
+++ b/Mage.Sets/src/mage/cards/m/Mindcrank.java
@@ -104,7 +104,7 @@ class MindcrankEffect extends OneShotEffect {
if (amount == null) {
amount = 0;
}
- targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, amount), Zone.GRAVEYARD, source, game);
+ targetPlayer.millCards(amount, source, game);
}
return true;
}
diff --git a/Mage.Sets/src/mage/cards/m/MindeyeDrake.java b/Mage.Sets/src/mage/cards/m/MindeyeDrake.java
index a2410f56b87..d693c35d37a 100644
--- a/Mage.Sets/src/mage/cards/m/MindeyeDrake.java
+++ b/Mage.Sets/src/mage/cards/m/MindeyeDrake.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -29,7 +29,7 @@ public final class MindeyeDrake extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Mindeye Drake dies, target player puts the top five cards of their library into their graveyard.
- Ability ability = new DiesTriggeredAbility(new PutLibraryIntoGraveTargetEffect(5));
+ Ability ability = new DiesSourceTriggeredAbility(new PutLibraryIntoGraveTargetEffect(5));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/MindsDesire.java b/Mage.Sets/src/mage/cards/m/MindsDesire.java
index eea1c4c7fae..d5cf67afd69 100644
--- a/Mage.Sets/src/mage/cards/m/MindsDesire.java
+++ b/Mage.Sets/src/mage/cards/m/MindsDesire.java
@@ -1,23 +1,19 @@
package mage.cards.m;
import mage.abilities.Ability;
-import mage.abilities.effects.AsThoughEffectImpl;
-import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.StormAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
-import mage.target.targetpointer.FixedTargets;
-import mage.util.CardUtil;
import java.util.UUID;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
+import mage.constants.TargetController;
/**
* @author emerald000
@@ -65,66 +61,9 @@ class MindsDesireEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.shuffleLibrary(source, game);
- Card card = controller.getLibrary().getFromTop(game);
- if (card != null) {
- UUID exileId = CardUtil.getExileZoneId(controller.getId().toString() + "-" + game.getState().getTurnNum() + "-" + MindsDesire.class.toString(), game);
- String exileName = "Mind's Desire free cast on " + game.getState().getTurnNum() + " turn for " + controller.getName();
- game.getExile().createZone(exileId, exileName).setCleanupOnEndTurn(true);
- if (controller.moveCardsToExile(card, source, game, true, exileId, exileName)) {
- ContinuousEffect effect = new MindsDesireCastFromExileEffect();
- effect.setTargetPointer(new FixedTargets(game.getExile().getExileZone(exileId).getCards(game), game));
- game.addEffect(effect, source);
- }
- }
- return true;
+ return PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(game, source, controller.getLibrary().getFromTop(game),
+ TargetController.YOU, Duration.EndOfTurn, true);
}
return false;
}
-}
-
-class MindsDesireCastFromExileEffect extends AsThoughEffectImpl {
-
- MindsDesireCastFromExileEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
- staticText = "you may play that card without paying its mana cost";
- }
-
- MindsDesireCastFromExileEffect(final MindsDesireCastFromExileEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public MindsDesireCastFromExileEffect copy() {
- return new MindsDesireCastFromExileEffect(this);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- return applies(objectId, null, source, game, affectedControllerId);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
- Card cardToCheck = game.getCard(objectId);
- objectId = CardUtil.getMainCardId(game, objectId); // for split cards
-
- if (!isAbilityAppliedForAlternateCast(cardToCheck, affectedAbility, playerId, source)) {
- return false;
- }
-
- Player controller = game.getPlayer(cardToCheck.getOwnerId());
- if (controller != null
- && getTargetPointer().getTargets(game, source).contains(objectId)) {
- controller.setCastSourceIdWithAlternateMana(affectedAbility.getSourceId(), null, affectedAbility.getCosts());
- return true;
- }
-
-
- return false;
- }
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/m/Mindshrieker.java b/Mage.Sets/src/mage/cards/m/Mindshrieker.java
index b8effb0479e..ad0be568073 100644
--- a/Mage.Sets/src/mage/cards/m/Mindshrieker.java
+++ b/Mage.Sets/src/mage/cards/m/Mindshrieker.java
@@ -1,20 +1,24 @@
package mage.cards.m;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
-import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.FlyingAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.Objects;
import java.util.UUID;
/**
@@ -34,10 +38,9 @@ public final class Mindshrieker extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// {2}: Target player puts the top card of their library into their graveyard. Mindshrieker gets +X/+X until end of turn, where X is that card's converted mana cost.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MindshriekerEffect(), new ManaCostsImpl("{2}"));
+ Ability ability = new SimpleActivatedAbility(new MindshriekerEffect(), new GenericManaCost(2));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
-
}
public Mindshrieker(final Mindshrieker card) {
@@ -52,30 +55,31 @@ public final class Mindshrieker extends CardImpl {
class MindshriekerEffect extends OneShotEffect {
- public MindshriekerEffect() {
+ MindshriekerEffect() {
super(Outcome.Detriment);
- staticText = "Target player puts the top card of their library into their graveyard. {this} gets +X/+X until end of turn, where X is that card's converted mana cost";
+ staticText = "Target player mills a card. {this} gets +X/+X until end of turn, " +
+ "where X is the milled card's converted mana cost";
}
- public MindshriekerEffect(final MindshriekerEffect effect) {
+ private MindshriekerEffect(final MindshriekerEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(source.getFirstTarget());
- if (targetPlayer != null) {
- if (targetPlayer.getLibrary().hasCards()) {
- Card card = targetPlayer.getLibrary().getFromTop(game);
- if (card != null) {
- targetPlayer.moveCards(card, Zone.GRAVEYARD, source, game);
- int amount = card.getConvertedManaCost();
- if (amount > 0) {
- game.addEffect(new BoostSourceEffect(amount, amount, Duration.EndOfTurn), source);
- }
- }
- }
- return true;
+ if (targetPlayer == null) {
+ return false;
+ }
+ int totalCMC = targetPlayer
+ .millCards(1, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .mapToInt(MageObject::getConvertedManaCost)
+ .sum();
+ if (totalCMC > 0) {
+ game.addEffect(new BoostSourceEffect(totalCMC, totalCMC, Duration.EndOfTurn), source);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/m/Mindslicer.java b/Mage.Sets/src/mage/cards/m/Mindslicer.java
index 3d3bab1a093..160481b70c4 100644
--- a/Mage.Sets/src/mage/cards/m/Mindslicer.java
+++ b/Mage.Sets/src/mage/cards/m/Mindslicer.java
@@ -3,7 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.discard.DiscardHandAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class Mindslicer extends CardImpl {
this.toughness = new MageInt(3);
// When Mindslicer dies, each player discards their hand.
- this.addAbility(new DiesTriggeredAbility(new DiscardHandAllEffect(),false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DiscardHandAllEffect(),false));
}
public Mindslicer(final Mindslicer card) {
diff --git a/Mage.Sets/src/mage/cards/m/Mirari.java b/Mage.Sets/src/mage/cards/m/Mirari.java
index 7a209fa01ab..20482a095fd 100644
--- a/Mage.Sets/src/mage/cards/m/Mirari.java
+++ b/Mage.Sets/src/mage/cards/m/Mirari.java
@@ -79,13 +79,7 @@ class MirariTriggeredAbility extends TriggeredAbilityImpl {
if (event.getPlayerId().equals(this.getControllerId())) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (isControlledInstantOrSorcery(spell)) {
- for (Effect effect : getEffects()) {
- if (effect instanceof DoIfCostPaid) {
- for (Effect execEffect : ((DoIfCostPaid) effect).getExecutingEffects()) {
- execEffect.setTargetPointer(new FixedTarget(spell.getId()));
- }
- }
- }
+ getEffects().setTargetPointer(new FixedTarget(spell.getId()));
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/m/MirrorMadPhantasm.java b/Mage.Sets/src/mage/cards/m/MirrorMadPhantasm.java
index 34511c34805..5d8a5207f38 100644
--- a/Mage.Sets/src/mage/cards/m/MirrorMadPhantasm.java
+++ b/Mage.Sets/src/mage/cards/m/MirrorMadPhantasm.java
@@ -69,10 +69,7 @@ class MirrorMadPhantasmEffect extends OneShotEffect {
if (owner == null) {
return false;
}
- if (owner.moveCards(perm, Zone.LIBRARY, source, game)) {
- owner.shuffleLibrary(source, game);
- perm.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- owner.shuffleLibrary(source, game);
+ if (owner.shuffleCardsToLibrary(perm, game, source)) {
Cards cards = new CardsImpl();
Card phantasmCard = null;
for (Card card : owner.getLibrary().getCards(game)) {
diff --git a/Mage.Sets/src/mage/cards/m/MirrorOfFate.java b/Mage.Sets/src/mage/cards/m/MirrorOfFate.java
index bc8bd0e12fd..5eb29e5592d 100644
--- a/Mage.Sets/src/mage/cards/m/MirrorOfFate.java
+++ b/Mage.Sets/src/mage/cards/m/MirrorOfFate.java
@@ -67,42 +67,20 @@ class MirrorOfFateEffect extends OneShotEffect {
@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) {
return false;
}
-
+ // Choose up to seven face-up exiled cards you own
CardsImpl cards = new CardsImpl();
MirrorOfFateTarget targetExile = new MirrorOfFateTarget();
- if (player.choose(outcome, targetExile, source.getSourceId(), game)) {
- for (UUID cardId : targetExile.getTargets()) {
- Card card = game.getCard(cardId);
- if (card != null) {
- cards.add(card);
- }
- }
+ if (controller.choose(outcome, targetExile, source.getSourceId(), game)) {
+ cards.addAll(targetExile.getTargets());
}
-
- for (Card card : player.getLibrary().getCards(game)) {
- card.moveToExile(null, null, source.getSourceId(), game);
- }
-
- TargetCard target = new TargetCard(Zone.EXILED, new FilterCard("card to put on top of your library"));
- while (player.canRespond() && cards.size() > 1) {
- player.choose(Outcome.Neutral, cards, target, game);
- Card card = cards.get(target.getFirstTarget(), game);
- if (card != null) {
- cards.remove(card);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
- target.clearChosen();
- }
- if (cards.size() == 1) {
- Card card = cards.get(cards.iterator().next(), game);
- card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
- }
-
- return true;
+ // Exile all the cards from your library
+ controller.moveCards(new CardsImpl(controller.getLibrary().getCardList()), Zone.EXILED, source, game);
+ // put the chosen cards on top of your library"
+ return controller.putCardsOnTopOfLibrary(cards, game, source, true);
}
}
diff --git a/Mage.Sets/src/mage/cards/m/MirrorShield.java b/Mage.Sets/src/mage/cards/m/MirrorShield.java
index e2d4db1cde2..27d9368dc83 100644
--- a/Mage.Sets/src/mage/cards/m/MirrorShield.java
+++ b/Mage.Sets/src/mage/cards/m/MirrorShield.java
@@ -1,7 +1,7 @@
package mage.cards.m;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
@@ -44,7 +44,7 @@ public final class MirrorShield extends CardImpl {
ability.addEffect(new GainAbilityAttachedEffect(
HexproofAbility.getInstance(), AttachmentType.EQUIPMENT
).setText("and has hexproof"));
- ability.addEffect(new GainAbilityAttachedEffect(new BlocksOrBecomesBlockedTriggeredAbility(
+ ability.addEffect(new GainAbilityAttachedEffect(new BlocksOrBecomesBlockedSourceTriggeredAbility(
new DestroyTargetEffect(), filter, false, rule + "", true
), AttachmentType.EQUIPMENT).setText("and \"" + rule + "\""));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/m/Miscast.java b/Mage.Sets/src/mage/cards/m/Miscast.java
new file mode 100644
index 00000000000..1bfb7ff2ce6
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/Miscast.java
@@ -0,0 +1,34 @@
+package mage.cards.m;
+
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.common.CounterUnlessPaysEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.filter.StaticFilters;
+import mage.target.TargetSpell;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class Miscast extends CardImpl {
+
+ public Miscast(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}");
+
+ // Counter target instant or sorcery spell unless its controller pays {3}.
+ this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new GenericManaCost(3)));
+ this.getSpellAbility().addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY));
+ }
+
+ private Miscast(final Miscast card) {
+ super(card);
+ }
+
+ @Override
+ public Miscast copy() {
+ return new Miscast(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/m/MischievousChimera.java b/Mage.Sets/src/mage/cards/m/MischievousChimera.java
index 09bf177b4e3..0806c73797b 100644
--- a/Mage.Sets/src/mage/cards/m/MischievousChimera.java
+++ b/Mage.Sets/src/mage/cards/m/MischievousChimera.java
@@ -33,7 +33,7 @@ public final class MischievousChimera extends CardImpl {
Ability ability = new FirstSpellOpponentsTurnTriggeredAbility(
new DamagePlayersEffect(1, TargetController.OPPONENT), false
);
- ability.addEffect(new ScryEffect(1).setText("Scry 1"));
+ ability.addEffect(new ScryEffect(1, false));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/Mise.java b/Mage.Sets/src/mage/cards/m/Mise.java
index 221affc8fd5..b09b753876f 100644
--- a/Mage.Sets/src/mage/cards/m/Mise.java
+++ b/Mage.Sets/src/mage/cards/m/Mise.java
@@ -1,7 +1,5 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
@@ -13,16 +11,18 @@ import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
+import mage.util.CardUtil;
+
+import java.util.UUID;
/**
- *
* @author L_J
*/
public final class Mise extends CardImpl {
public Mise(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}");
+
// Choose a nonland card name, then reveal the top card of your library. If that card has the chosen name, you draw three cards.
this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME));
this.getSpellAbility().addEffect(new MiseEffect());
@@ -52,14 +52,13 @@ class MiseEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- Object object = game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (player != null && object instanceof String) {
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ if (player != null && cardName != null) {
Card card = player.getLibrary().getFromTop(game);
- String namedCard = (String) object;
CardsImpl cards = new CardsImpl(card);
if (card != null) {
player.revealCards("Mise", cards, game, true);
- if (card.getName().equals(namedCard)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
player.drawCards(3, source.getSourceId(), game);
}
}
diff --git a/Mage.Sets/src/mage/cards/m/MistcutterHydra.java b/Mage.Sets/src/mage/cards/m/MistcutterHydra.java
index 92fb0c947a8..6078203b18d 100644
--- a/Mage.Sets/src/mage/cards/m/MistcutterHydra.java
+++ b/Mage.Sets/src/mage/cards/m/MistcutterHydra.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect;
import mage.abilities.keyword.HasteAbility;
@@ -29,7 +29,7 @@ public final class MistcutterHydra extends CardImpl {
this.toughness = new MageInt(0);
// Mistcutter Hydra can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Haste
this.addAbility(HasteAbility.getInstance());
// protection from blue
diff --git a/Mage.Sets/src/mage/cards/m/MistmoonGriffin.java b/Mage.Sets/src/mage/cards/m/MistmoonGriffin.java
index 471aaa67535..98c2e472014 100644
--- a/Mage.Sets/src/mage/cards/m/MistmoonGriffin.java
+++ b/Mage.Sets/src/mage/cards/m/MistmoonGriffin.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.keyword.FlyingAbility;
@@ -34,7 +34,7 @@ public final class MistmoonGriffin extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Mistmoon Griffin dies, exile Mistmoon Griffin, then return the top creature card of your graveyard to the battlefield.
- Ability ability = new DiesTriggeredAbility(new ExileSourceEffect());
+ Ability ability = new DiesSourceTriggeredAbility(new ExileSourceEffect());
ability.addEffect(new MistmoonGriffinEffect());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/m/MistralSinger.java b/Mage.Sets/src/mage/cards/m/MistralSinger.java
new file mode 100644
index 00000000000..fb669618d95
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MistralSinger.java
@@ -0,0 +1,40 @@
+package mage.cards.m;
+
+import mage.MageInt;
+import mage.abilities.keyword.FlyingAbility;
+import mage.abilities.keyword.ProwessAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class MistralSinger extends CardImpl {
+
+ public MistralSinger(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
+
+ this.subtype.add(SubType.SIREN);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Prowess
+ this.addAbility(new ProwessAbility());
+ }
+
+ private MistralSinger(final MistralSinger card) {
+ super(card);
+ }
+
+ @Override
+ public MistralSinger copy() {
+ return new MistralSinger(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/m/MitoticSlime.java b/Mage.Sets/src/mage/cards/m/MitoticSlime.java
index 73b29d2cf01..1118a07e550 100644
--- a/Mage.Sets/src/mage/cards/m/MitoticSlime.java
+++ b/Mage.Sets/src/mage/cards/m/MitoticSlime.java
@@ -3,7 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class MitoticSlime extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new Ooze2Token(), 2), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new Ooze2Token(), 2), false));
}
public MitoticSlime(final MitoticSlime card) {
diff --git a/Mage.Sets/src/mage/cards/m/MogissWarhound.java b/Mage.Sets/src/mage/cards/m/MogissWarhound.java
index 3ac5c7cc259..76b79af5e0e 100644
--- a/Mage.Sets/src/mage/cards/m/MogissWarhound.java
+++ b/Mage.Sets/src/mage/cards/m/MogissWarhound.java
@@ -26,7 +26,7 @@ public final class MogissWarhound extends CardImpl {
public MogissWarhound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{1}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/m/Molderhulk.java b/Mage.Sets/src/mage/cards/m/Molderhulk.java
index 9f65632312c..9f38fec52ad 100644
--- a/Mage.Sets/src/mage/cards/m/Molderhulk.java
+++ b/Mage.Sets/src/mage/cards/m/Molderhulk.java
@@ -1,25 +1,28 @@
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
-import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
-import mage.constants.SubType;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AbilityWord;
import mage.constants.CardType;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.common.FilterLandCard;
import mage.target.common.TargetCardInYourGraveyard;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class Molderhulk extends CardImpl {
@@ -36,8 +39,11 @@ public final class Molderhulk extends CardImpl {
this.toughness = new MageInt(6);
// Undergrowth — This spell costs {1} less to cast for each creature card in your graveyard.
- Ability ability = new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_CREATURE));
+ DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
ability.setAbilityWord(AbilityWord.UNDERGROWTH);
+ ability.setRuleAtTheTop(true);
+ ability.addHint(new ValueHint("Creature card in your graveyard", xValue));
this.addAbility(ability);
// When Molderhulk enters the battlefield, return target land card from your graveyard to the battlefield.
diff --git a/Mage.Sets/src/mage/cards/m/MoldgrafMonstrosity.java b/Mage.Sets/src/mage/cards/m/MoldgrafMonstrosity.java
index 8cbb8e42715..90ee145c1c5 100644
--- a/Mage.Sets/src/mage/cards/m/MoldgrafMonstrosity.java
+++ b/Mage.Sets/src/mage/cards/m/MoldgrafMonstrosity.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect;
@@ -39,7 +39,7 @@ public final class MoldgrafMonstrosity extends CardImpl {
// When Moldgraf Monstrosity dies, exile it, then return two creature cards at random from your graveyard to the battlefield.
Effect effect = new ExileSourceEffect();
effect.setText("");
- DiesTriggeredAbility ability = new DiesTriggeredAbility(effect);
+ DiesSourceTriggeredAbility ability = new DiesSourceTriggeredAbility(effect);
ability.addEffect(new MoldgrafMonstrosityEffect());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/MoltenFirebird.java b/Mage.Sets/src/mage/cards/m/MoltenFirebird.java
index 81001ce6abc..d89a6837bcc 100644
--- a/Mage.Sets/src/mage/cards/m/MoltenFirebird.java
+++ b/Mage.Sets/src/mage/cards/m/MoltenFirebird.java
@@ -3,7 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
@@ -32,7 +32,7 @@ public final class MoltenFirebird extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Molten Firebird dies, return it to the battlefield under its owner’s control at the beginning of the next end step and you skip your next draw step.
- Ability ability = new DiesTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(
+ Ability ability = new DiesSourceTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect())));
ability.addEffect(new SkipNextDrawStepControllerEffect());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/m/MoltenPsyche.java b/Mage.Sets/src/mage/cards/m/MoltenPsyche.java
index 7d80268bf97..b3ef8785c67 100644
--- a/Mage.Sets/src/mage/cards/m/MoltenPsyche.java
+++ b/Mage.Sets/src/mage/cards/m/MoltenPsyche.java
@@ -73,7 +73,7 @@ class MoltenPsycheEffect extends OneShotEffect {
}
}
- game.applyEffects(); // so effects from creatures that were on the battlefield won't trigger from draw action
+ game.getState().processAction(game); // so effects from creatures that were on the battlefield won't trigger from draw action
for (UUID playerId : cardsToDraw.keySet()) {
Player player = game.getPlayer(playerId);
diff --git a/Mage.Sets/src/mage/cards/m/MomentumRumbler.java b/Mage.Sets/src/mage/cards/m/MomentumRumbler.java
index e8d8087f9f1..b6875666aa8 100644
--- a/Mage.Sets/src/mage/cards/m/MomentumRumbler.java
+++ b/Mage.Sets/src/mage/cards/m/MomentumRumbler.java
@@ -75,6 +75,6 @@ enum MomentumRumblerCondition implements Condition {
if (permanent == null) {
return false;
}
- return hasAbility == permanent.getAbilities(game).containsKey(FirstStrikeAbility.getInstance().getId());
+ return hasAbility == permanent.hasAbility(FirstStrikeAbility.getInstance(), game);
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/m/MongrelPack.java b/Mage.Sets/src/mage/cards/m/MongrelPack.java
index e2a0f56e40a..94d40ab16df 100644
--- a/Mage.Sets/src/mage/cards/m/MongrelPack.java
+++ b/Mage.Sets/src/mage/cards/m/MongrelPack.java
@@ -1,7 +1,5 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.ZoneChangeTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -13,18 +11,18 @@ import mage.constants.TurnPhase;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
-import mage.game.permanent.token.TokenImpl;
-import mage.game.permanent.token.Token;
+import mage.game.permanent.token.GreenDogToken;
+
+import java.util.UUID;
/**
- *
* @author North
*/
public final class MongrelPack extends CardImpl {
public MongrelPack(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
- this.subtype.add(SubType.HOUND);
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(1);
@@ -33,7 +31,7 @@ public final class MongrelPack extends CardImpl {
this.addAbility(new MongrelPackAbility());
}
- public MongrelPack(final MongrelPack card) {
+ private MongrelPack(final MongrelPack card) {
super(card);
}
@@ -45,11 +43,11 @@ public final class MongrelPack extends CardImpl {
class MongrelPackAbility extends ZoneChangeTriggeredAbility {
- public MongrelPackAbility() {
- super(Zone.BATTLEFIELD, Zone.GRAVEYARD, new CreateTokenEffect(new HoundToken(), 4), "When {this} dies during combat, ", false);
+ MongrelPackAbility() {
+ super(Zone.BATTLEFIELD, Zone.GRAVEYARD, new CreateTokenEffect(new GreenDogToken(), 4), "When {this} dies during combat, ", false);
}
- public MongrelPackAbility(MongrelPackAbility ability) {
+ private MongrelPackAbility(MongrelPackAbility ability) {
super(ability);
}
@@ -68,24 +66,3 @@ class MongrelPackAbility extends ZoneChangeTriggeredAbility {
return false;
}
}
-
-class HoundToken extends TokenImpl {
-
- public HoundToken() {
- super("Hound", "1/1 green Hound creature token");
- cardType.add(CardType.CREATURE);
- subtype.add(SubType.HOUND);
-
- color.setGreen(true);
- power = new MageInt(1);
- toughness = new MageInt(1);
- }
-
- public HoundToken(final HoundToken token) {
- super(token);
- }
-
- public HoundToken copy() {
- return new HoundToken(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/m/Monomania.java b/Mage.Sets/src/mage/cards/m/Monomania.java
index 8e27d39857c..86f4ac069ff 100644
--- a/Mage.Sets/src/mage/cards/m/Monomania.java
+++ b/Mage.Sets/src/mage/cards/m/Monomania.java
@@ -1,37 +1,35 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
+import mage.target.common.TargetDiscard;
+
+import java.util.UUID;
/**
- *
* @author nantuko
*/
public final class Monomania extends CardImpl {
public Monomania(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}{B}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}");
// Target player chooses a card in their hand and discards the rest.
this.getSpellAbility().addEffect(new MonomaniaEffect());
this.getSpellAbility().addTarget(new TargetPlayer());
}
- public Monomania(final Monomania card) {
+ private Monomania(final Monomania card) {
super(card);
}
@@ -45,41 +43,30 @@ class MonomaniaEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard("a card");
- public MonomaniaEffect() {
+ MonomaniaEffect() {
super(Outcome.Discard);
staticText = "Target player chooses a card in their hand and discards the rest";
}
- public MonomaniaEffect(final MonomaniaEffect effect) {
+ private MonomaniaEffect(final MonomaniaEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getFirstTarget());
- if (player != null) {
- TargetCard target = new TargetCard(Zone.HAND, filter);
- if (player.choose(Outcome.Detriment, player.getHand(), target, game)) {
- while (player.getHand().size() > 1) {
- for (UUID uuid : player.getHand()) {
- if (!uuid.equals(target.getFirstTarget())) {
- Card card = player.getHand().get(uuid, game);
- if (card != null) {
- player.discard(card, source, game);
- break;
- }
- }
- }
- }
- return true;
- }
+ if (player == null || player.getHand().isEmpty()) {
+ return false;
}
- return false;
+ TargetCard target = new TargetDiscard(player.getId());
+ player.choose(Outcome.Benefit, player.getHand(), target, game);
+ Cards cards = player.getHand().copy();
+ cards.removeIf(target.getTargets()::contains);
+ return !player.discard(cards, source, game).isEmpty();
}
@Override
public MonomaniaEffect copy() {
return new MonomaniaEffect(this);
}
-
}
diff --git a/Mage.Sets/src/mage/cards/m/MonstrousHound.java b/Mage.Sets/src/mage/cards/m/MonstrousHound.java
index cdebb8caa74..1eba97be678 100644
--- a/Mage.Sets/src/mage/cards/m/MonstrousHound.java
+++ b/Mage.Sets/src/mage/cards/m/MonstrousHound.java
@@ -26,7 +26,7 @@ public final class MonstrousHound extends CardImpl {
public MonstrousHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
diff --git a/Mage.Sets/src/mage/cards/m/MoonEatingDog.java b/Mage.Sets/src/mage/cards/m/MoonEatingDog.java
index 1467030f595..d5d2a004f16 100644
--- a/Mage.Sets/src/mage/cards/m/MoonEatingDog.java
+++ b/Mage.Sets/src/mage/cards/m/MoonEatingDog.java
@@ -30,7 +30,7 @@ public final class MoonEatingDog extends CardImpl {
public MoonEatingDog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/m/MortisDogs.java b/Mage.Sets/src/mage/cards/m/MortisDogs.java
index 310a8b88676..452a6319c59 100644
--- a/Mage.Sets/src/mage/cards/m/MortisDogs.java
+++ b/Mage.Sets/src/mage/cards/m/MortisDogs.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
@@ -24,7 +24,7 @@ public final class MortisDogs extends CardImpl {
public MortisDogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
@@ -32,7 +32,7 @@ public final class MortisDogs extends CardImpl {
// Whenever Mortis Dogs attacks, it gets +2/+0 until end of turn.
this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(2, 0, Duration.EndOfTurn), false));
// When Mortis Dogs dies, target player loses life equal to its power.
- Ability ability = new DiesTriggeredAbility(new LoseLifeTargetEffect(new SourcePermanentPowerCount(false)));
+ Ability ability = new DiesSourceTriggeredAbility(new LoseLifeTargetEffect(new SourcePermanentPowerCount(false)));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/MortusStrider.java b/Mage.Sets/src/mage/cards/m/MortusStrider.java
index 664bd3ea854..fb7cd29490b 100644
--- a/Mage.Sets/src/mage/cards/m/MortusStrider.java
+++ b/Mage.Sets/src/mage/cards/m/MortusStrider.java
@@ -3,7 +3,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class MortusStrider extends CardImpl {
this.toughness = new MageInt(1);
// When Mortus Strider dies, return it to its owner's hand.
- this.addAbility(new DiesTriggeredAbility(new ReturnToHandSourceEffect(false)));
+ this.addAbility(new DiesSourceTriggeredAbility(new ReturnToHandSourceEffect(false)));
}
public MortusStrider(final MortusStrider card) {
diff --git a/Mage.Sets/src/mage/cards/m/Mossdog.java b/Mage.Sets/src/mage/cards/m/Mossdog.java
index 6f3bff28272..b052767d072 100644
--- a/Mage.Sets/src/mage/cards/m/Mossdog.java
+++ b/Mage.Sets/src/mage/cards/m/Mossdog.java
@@ -24,7 +24,7 @@ public final class Mossdog extends CardImpl {
public Mossdog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}");
this.subtype.add(SubType.PLANT);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/m/MouseDroid.java b/Mage.Sets/src/mage/cards/m/MouseDroid.java
index 1d911de6687..f3ee4dbd2fe 100644
--- a/Mage.Sets/src/mage/cards/m/MouseDroid.java
+++ b/Mage.Sets/src/mage/cards/m/MouseDroid.java
@@ -2,7 +2,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.RepairAbility;
import mage.constants.SubType;
@@ -24,7 +24,7 @@ public final class MouseDroid extends CardImpl {
this.toughness = new MageInt(1);
// When Mouse Droid dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1)));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)));
// Repair 3
this.addAbility(new RepairAbility(3));
diff --git a/Mage.Sets/src/mage/cards/m/MowuLoyalCompanion.java b/Mage.Sets/src/mage/cards/m/MowuLoyalCompanion.java
index 946b515178e..03ec484dcc9 100644
--- a/Mage.Sets/src/mage/cards/m/MowuLoyalCompanion.java
+++ b/Mage.Sets/src/mage/cards/m/MowuLoyalCompanion.java
@@ -25,7 +25,7 @@ public final class MowuLoyalCompanion extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.addSuperType(SuperType.LEGENDARY);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/m/MoxAmber.java b/Mage.Sets/src/mage/cards/m/MoxAmber.java
index ae6d86bd9dc..83093f734de 100644
--- a/Mage.Sets/src/mage/cards/m/MoxAmber.java
+++ b/Mage.Sets/src/mage/cards/m/MoxAmber.java
@@ -1,7 +1,5 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.abilities.mana.AnyColorPermanentTypesManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -11,24 +9,25 @@ import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
+import java.util.UUID;
+
/**
- *
* @author CountAndromalius
*/
public final class MoxAmber extends CardImpl {
public MoxAmber(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{0}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{0}");
addSuperType(SuperType.LEGENDARY);
- // {tap}: Add one mana pool of any color among legendary creatures and planeswalkers you control.
+ // {T}: Add one mana pool of any color among legendary creatures and planeswalkers you control.
FilterPermanent filter = new FilterPermanent("legendary creatures and planeswalkers");
filter.add(Predicates.or(
Predicates.and(
- CardType.CREATURE.getPredicate(),
- SuperType.LEGENDARY.getPredicate()
+ CardType.CREATURE.getPredicate(),
+ SuperType.LEGENDARY.getPredicate()
),
- CardType.PLANESWALKER.getPredicate())
+ CardType.PLANESWALKER.getPredicate())
);
this.addAbility(new AnyColorPermanentTypesManaAbility(TargetController.YOU, filter));
}
diff --git a/Mage.Sets/src/mage/cards/m/MudbuttonTorchrunner.java b/Mage.Sets/src/mage/cards/m/MudbuttonTorchrunner.java
index 577e64980d1..07f76c18f04 100644
--- a/Mage.Sets/src/mage/cards/m/MudbuttonTorchrunner.java
+++ b/Mage.Sets/src/mage/cards/m/MudbuttonTorchrunner.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class MudbuttonTorchrunner extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// When Mudbutton Torchrunner dies, it deals 3 damage to any target.
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(3, "it"), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(3, "it"), false);
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java b/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java
index 257e555abfa..6271916674b 100644
--- a/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java
+++ b/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java
@@ -1,8 +1,5 @@
-
package mage.cards.m;
-import java.util.Objects;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Abilities;
import mage.abilities.Ability;
@@ -20,8 +17,10 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicate;
import mage.game.Game;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author anonymous
*/
public final class MuragandaPetroglyphs extends CardImpl {
@@ -54,6 +53,12 @@ public final class MuragandaPetroglyphs extends CardImpl {
class NoAbilityPredicate implements Predicate {
+ // Muraganda Petroglyphs gives a bonus only to creatures that have no rules text at all. This includes true vanilla
+ // creatures (such as Grizzly Bears), face-down creatures, many tokens, and creatures that have lost their abilities
+ // (due to Ovinize, for example). Any ability of any kind, whether or not the ability functions in the on the
+ // battlefield zone, including things like “Cycling {2}” means the creature doesn’t get the bonus.
+ // (2007-05-01)
+
@Override
public boolean apply(MageObject input, Game game) {
boolean isFaceDown = false;
@@ -65,8 +70,20 @@ class NoAbilityPredicate implements Predicate {
abilities = input.getAbilities();
}
if (isFaceDown) {
+ // Some Auras and Equipment grant abilities to creatures, meaning the affected creature would no longer
+ // get the +2/+2 bonus. For example, Flight grants flying to the enchanted creature. Other Auras and
+ // Equipment do not, meaning the affected creature would continue to get the +2/+2 bonus. For example,
+ // Dehydration states something now true about the enchanted creature, but doesn’t give it any abilities.
+ // Auras and Equipment that grant abilities will use the words “gains” or “has,” and they’ll list a keyword
+ // ability or an ability in quotation marks.
+ // (2007-05-01)
+
for (Ability ability : abilities) {
- if (!ability.getSourceId().equals(input.getId()) && !ability.getClass().equals(JohanVigilanceAbility.class)) {
+ if (ability.getWorksFaceDown()) {
+ // inner face down abilities like turn up and becomes creature
+ continue;
+ }
+ if (!Objects.equals(ability.getClass(), SpellAbility.class) && !ability.getClass().equals(JohanVigilanceAbility.class)) {
return false;
}
}
diff --git a/Mage.Sets/src/mage/cards/m/MurderousRider.java b/Mage.Sets/src/mage/cards/m/MurderousRider.java
index 7e7864389f9..cc42e69eaa1 100644
--- a/Mage.Sets/src/mage/cards/m/MurderousRider.java
+++ b/Mage.Sets/src/mage/cards/m/MurderousRider.java
@@ -1,7 +1,7 @@
package mage.cards.m;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.abilities.keyword.LifelinkAbility;
@@ -30,7 +30,7 @@ public final class MurderousRider extends AdventureCard {
this.addAbility(LifelinkAbility.getInstance());
// When Murderous Rider dies, put it on the bottom of its owner's library.
- this.addAbility(new DiesTriggeredAbility(new PutOnLibrarySourceEffect(
+ this.addAbility(new DiesSourceTriggeredAbility(new PutOnLibrarySourceEffect(
false, "put it on the bottom of its owner's library"
), false));
diff --git a/Mage.Sets/src/mage/cards/m/MuxusGoblinGrandee.java b/Mage.Sets/src/mage/cards/m/MuxusGoblinGrandee.java
new file mode 100644
index 00000000000..ca54830561e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MuxusGoblinGrandee.java
@@ -0,0 +1,115 @@
+package mage.cards.m;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
+import mage.constants.*;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.permanent.AnotherPredicate;
+import mage.game.Game;
+import mage.players.Player;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class MuxusGoblinGrandee extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledPermanent(SubType.GOBLIN);
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ }
+
+ private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
+
+ public MuxusGoblinGrandee(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.GOBLIN);
+ this.subtype.add(SubType.NOBLE);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(4);
+
+ // When Muxus, Goblin Grandee enters the battlefield, reveal the top six cards of your library. Put all Goblin creature cards with converted mana cost 5 or less from among them onto the battlefield and the rest on the bottom of your library in a random order.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new MuxusGoblinGrandeeEffect()));
+
+ // Whenever Muxus attacks, it gets +1/+1 until end of turn for each other Goblin you control.
+ this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(
+ xValue, xValue, Duration.EndOfTurn
+ ).setText("it gets +1/+1 until end of turn for each other Goblin you control"), false));
+ }
+
+ private MuxusGoblinGrandee(final MuxusGoblinGrandee card) {
+ super(card);
+ }
+
+ @Override
+ public MuxusGoblinGrandee copy() {
+ return new MuxusGoblinGrandee(this);
+ }
+}
+
+class MuxusGoblinGrandeeEffect extends OneShotEffect {
+
+ MuxusGoblinGrandeeEffect() {
+ super(Outcome.Benefit);
+ staticText = "reveal the top six cards of your library. " +
+ "Put all Goblin creature cards with converted mana cost 5 or less " +
+ "from among them onto the battlefield and the rest on the bottom of your library in a random order.";
+ }
+
+ private MuxusGoblinGrandeeEffect(final MuxusGoblinGrandeeEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public MuxusGoblinGrandeeEffect copy() {
+ return new MuxusGoblinGrandeeEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null) {
+ return false;
+ }
+ Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 6));
+ player.revealCards(source, cards, game);
+ Cards toBattlfield = new CardsImpl();
+ Cards toBottom = new CardsImpl();
+ cards.getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .forEach(card -> {
+ if (card.isCreature()
+ && card.hasSubtype(SubType.GOBLIN, game)
+ && card.getConvertedManaCost() <= 5) {
+ toBattlfield.add(card);
+ } else {
+ toBottom.add(card);
+ }
+ });
+ player.moveCards(toBattlfield, Zone.BATTLEFIELD, source, game);
+ // need to account for effects like Grafdigger's Cage
+ toBattlfield
+ .stream()
+ .filter(uuid -> game.getState().getZone(uuid) == Zone.LIBRARY)
+ .forEach(toBottom::add);
+ player.putCardsOnBottomOfLibrary(toBottom, game, source, false);
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/m/MycosynthLattice.java b/Mage.Sets/src/mage/cards/m/MycosynthLattice.java
index 61ac8b0fae8..7053ad1eab7 100644
--- a/Mage.Sets/src/mage/cards/m/MycosynthLattice.java
+++ b/Mage.Sets/src/mage/cards/m/MycosynthLattice.java
@@ -8,6 +8,7 @@ import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.AsThoughManaEffect;
import mage.abilities.effects.ContinuousEffectImpl;
+import mage.abilities.hint.StaticHint;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -34,7 +35,9 @@ public final class MycosynthLattice extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new EverythingIsColorlessEffect()));
// Players may spend mana as though it were mana of any color.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ManaCanBeSpentAsAnyColorEffect()));
+ Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ManaCanBeSpentAsAnyColorEffect());
+ ability.addHint(new StaticHint("(XMage hint: You can use floating mana by clicking on the related symbol of the needed mana type in your mana pool player area.)"));
+ this.addAbility(ability);
}
public MycosynthLattice(final MycosynthLattice card) {
diff --git a/Mage.Sets/src/mage/cards/m/MycosynthWellspring.java b/Mage.Sets/src/mage/cards/m/MycosynthWellspring.java
index a79e7bf8126..bcf4918447e 100644
--- a/Mage.Sets/src/mage/cards/m/MycosynthWellspring.java
+++ b/Mage.Sets/src/mage/cards/m/MycosynthWellspring.java
@@ -1,7 +1,7 @@
package mage.cards.m;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.CardImpl;
@@ -24,7 +24,7 @@ public final class MycosynthWellspring extends CardImpl {
// When Mycosynth Wellspring enters the battlefield or is put into a graveyard from the battlefield,
// you may search your library for a basic land card, reveal it, put it into your hand, then shuffle your library.
this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true, true), true));
- this.addAbility(new DiesTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true, true), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true, true), true));
}
public MycosynthWellspring(final MycosynthWellspring card) {
diff --git a/Mage.Sets/src/mage/cards/m/MyojinOfCleansingFire.java b/Mage.Sets/src/mage/cards/m/MyojinOfCleansingFire.java
index 6bad3165ae0..f3da7615d1a 100644
--- a/Mage.Sets/src/mage/cards/m/MyojinOfCleansingFire.java
+++ b/Mage.Sets/src/mage/cards/m/MyojinOfCleansingFire.java
@@ -6,7 +6,7 @@ import mage.MageInt;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@@ -48,7 +48,7 @@ public final class MyojinOfCleansingFire extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Cleansing Fire enters the battlefield with a divinity counter on it if you cast it from your hand.
- this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourceCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
+ this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourcePermanentCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Cleansing Fire is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));
diff --git a/Mage.Sets/src/mage/cards/m/MyojinOfInfiniteRage.java b/Mage.Sets/src/mage/cards/m/MyojinOfInfiniteRage.java
index 0c664bb6c52..f217d6ca29d 100644
--- a/Mage.Sets/src/mage/cards/m/MyojinOfInfiniteRage.java
+++ b/Mage.Sets/src/mage/cards/m/MyojinOfInfiniteRage.java
@@ -6,7 +6,7 @@ import mage.MageInt;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@@ -42,7 +42,7 @@ public final class MyojinOfInfiniteRage extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Infinite Rage enters the battlefield with a divinity counter on it if you cast it from your hand.
- this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourceCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
+ this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourcePermanentCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Infinite Rage is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));
diff --git a/Mage.Sets/src/mage/cards/m/MyojinOfLifesWeb.java b/Mage.Sets/src/mage/cards/m/MyojinOfLifesWeb.java
index a9a628b5edb..3f5403b25e2 100644
--- a/Mage.Sets/src/mage/cards/m/MyojinOfLifesWeb.java
+++ b/Mage.Sets/src/mage/cards/m/MyojinOfLifesWeb.java
@@ -7,7 +7,7 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@@ -43,7 +43,7 @@ public final class MyojinOfLifesWeb extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Life's Web enters the battlefield with a divinity counter on it if you cast it from your hand.
- this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourceCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
+ this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourcePermanentCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Life's Web is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
diff --git a/Mage.Sets/src/mage/cards/m/MyojinOfNightsReach.java b/Mage.Sets/src/mage/cards/m/MyojinOfNightsReach.java
index 9f6f424fd3c..dee0e164577 100644
--- a/Mage.Sets/src/mage/cards/m/MyojinOfNightsReach.java
+++ b/Mage.Sets/src/mage/cards/m/MyojinOfNightsReach.java
@@ -1,13 +1,11 @@
-
package mage.cards.m;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@@ -16,7 +14,6 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.IndestructibleAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@@ -25,13 +22,15 @@ import mage.game.Game;
import mage.players.Player;
import mage.watchers.common.CastFromHandWatcher;
+import java.util.UUID;
+
/**
* @author LevelX
*/
public final class MyojinOfNightsReach extends CardImpl {
public MyojinOfNightsReach(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{B}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}{B}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.SPIRIT);
@@ -41,7 +40,7 @@ public final class MyojinOfNightsReach extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Night's Reach enters the battlefield with a divinity counter on it if you cast it from your hand.
- this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourceCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
+ this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourcePermanentCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Night's Reach is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));
@@ -50,7 +49,7 @@ public final class MyojinOfNightsReach extends CardImpl {
this.addAbility(ability);
}
- public MyojinOfNightsReach(final MyojinOfNightsReach card) {
+ private MyojinOfNightsReach(final MyojinOfNightsReach card) {
super(card);
}
@@ -61,12 +60,13 @@ public final class MyojinOfNightsReach extends CardImpl {
}
class MyojinOfNightsReachEffect extends OneShotEffect {
- public MyojinOfNightsReachEffect() {
+
+ MyojinOfNightsReachEffect() {
super(Outcome.Discard);
staticText = "Each opponent discards their hand";
}
- public MyojinOfNightsReachEffect(final MyojinOfNightsReachEffect effect) {
+ private MyojinOfNightsReachEffect(final MyojinOfNightsReachEffect effect) {
super(effect);
}
@@ -74,10 +74,8 @@ class MyojinOfNightsReachEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
Player opponent = game.getPlayer(opponentId);
- if(opponent != null) {
- for (Card c : opponent.getHand().getCards(game)) {
- opponent.discard(c, source, game);
- }
+ if (opponent != null) {
+ opponent.discard(opponent.getHand(), source, game);
}
}
return true;
@@ -87,5 +85,4 @@ class MyojinOfNightsReachEffect extends OneShotEffect {
public MyojinOfNightsReachEffect copy() {
return new MyojinOfNightsReachEffect(this);
}
-
}
diff --git a/Mage.Sets/src/mage/cards/m/MyojinOfSeeingWinds.java b/Mage.Sets/src/mage/cards/m/MyojinOfSeeingWinds.java
index a2ffdec4737..319780ad6bb 100644
--- a/Mage.Sets/src/mage/cards/m/MyojinOfSeeingWinds.java
+++ b/Mage.Sets/src/mage/cards/m/MyojinOfSeeingWinds.java
@@ -7,7 +7,7 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@@ -45,7 +45,7 @@ public final class MyojinOfSeeingWinds extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Seeing Winds enters the battlefield with a divinity counter on it if you cast it from your hand.
- this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourceCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
+ this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), CastFromHandSourcePermanentCondition.instance, ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Seeing Winds is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));
diff --git a/Mage.Sets/src/mage/cards/m/MyrMoonvessel.java b/Mage.Sets/src/mage/cards/m/MyrMoonvessel.java
index b25556c35aa..b31ea7095fd 100644
--- a/Mage.Sets/src/mage/cards/m/MyrMoonvessel.java
+++ b/Mage.Sets/src/mage/cards/m/MyrMoonvessel.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.Mana;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -21,7 +21,7 @@ public final class MyrMoonvessel extends CardImpl {
this.subtype.add(SubType.MYR);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
- this.addAbility(new DiesTriggeredAbility(new BasicManaEffect(Mana.ColorlessMana(1))));
+ this.addAbility(new DiesSourceTriggeredAbility(new BasicManaEffect(Mana.ColorlessMana(1))));
}
public MyrMoonvessel(final MyrMoonvessel card) {
diff --git a/Mage.Sets/src/mage/cards/m/MyrRetriever.java b/Mage.Sets/src/mage/cards/m/MyrRetriever.java
index 5d0560a459c..2bb166aa7cc 100644
--- a/Mage.Sets/src/mage/cards/m/MyrRetriever.java
+++ b/Mage.Sets/src/mage/cards/m/MyrRetriever.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.cards.CardImpl;
@@ -36,7 +36,7 @@ public final class MyrRetriever extends CardImpl {
// When Myr Retriever dies, return another target artifact card from your graveyard to your hand.
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
effect.setText("return another target artifact card from your graveyard to your hand");
- Ability ability = new DiesTriggeredAbility(effect);
+ Ability ability = new DiesSourceTriggeredAbility(effect);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/m/MyrSire.java b/Mage.Sets/src/mage/cards/m/MyrSire.java
index 2d13b14161c..80b28b593c9 100644
--- a/Mage.Sets/src/mage/cards/m/MyrSire.java
+++ b/Mage.Sets/src/mage/cards/m/MyrSire.java
@@ -4,7 +4,7 @@ package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class MyrSire extends CardImpl {
this.subtype.add(SubType.MYR);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new MyrToken())));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new MyrToken())));
}
public MyrSire (final MyrSire card) {
diff --git a/Mage.Sets/src/mage/cards/m/MysticSkyfish.java b/Mage.Sets/src/mage/cards/m/MysticSkyfish.java
new file mode 100644
index 00000000000..9c75a23b5c6
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/m/MysticSkyfish.java
@@ -0,0 +1,41 @@
+package mage.cards.m;
+
+import mage.MageInt;
+import mage.abilities.common.DrawSecondCardTriggeredAbility;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class MysticSkyfish extends CardImpl {
+
+ public MysticSkyfish(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
+
+ this.subtype.add(SubType.FISH);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(1);
+
+ // Whenever you draw your second card each turn, Mystic Skyfish gains flying until end of turn.
+ this.addAbility(new DrawSecondCardTriggeredAbility(
+ new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), false)
+ );
+ }
+
+ private MysticSkyfish(final MysticSkyfish card) {
+ super(card);
+ }
+
+ @Override
+ public MysticSkyfish copy() {
+ return new MysticSkyfish(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/m/MysticalDispute.java b/Mage.Sets/src/mage/cards/m/MysticalDispute.java
index f2c290d95e0..61c8d087759 100644
--- a/Mage.Sets/src/mage/cards/m/MysticalDispute.java
+++ b/Mage.Sets/src/mage/cards/m/MysticalDispute.java
@@ -28,7 +28,7 @@ public final class MysticalDispute extends CardImpl {
// This spell costs {2} less to cast if it targets a blue spell.
this.addAbility(new SimpleStaticAbility(
- Zone.STACK, new SpellCostReductionSourceEffect(2, MysticalDisputeCondition.instance)
+ Zone.ALL, new SpellCostReductionSourceEffect(2, MysticalDisputeCondition.instance).setCanWorksOnStackOnly(true)
).setRuleAtTheTop(true));
// Counter target spell unless its controller pays {3}.
diff --git a/Mage.Sets/src/mage/cards/m/MythUnbound.java b/Mage.Sets/src/mage/cards/m/MythUnbound.java
index 08e62af7f6c..0b2e0ea26d8 100644
--- a/Mage.Sets/src/mage/cards/m/MythUnbound.java
+++ b/Mage.Sets/src/mage/cards/m/MythUnbound.java
@@ -77,10 +77,8 @@ class MythUnboundCostReductionEffect extends CostModificationEffectImpl {
if (spellAbility != null) {
CommanderPlaysCountWatcher watcher = game.getState().getWatcher(CommanderPlaysCountWatcher.class);
int castCount = watcher.getPlaysCount(abilityToModify.getSourceId());
- if (castCount > 0) {
- CardUtil.reduceCost(spellAbility, castCount);
- return true;
- }
+ CardUtil.reduceCost(spellAbility, castCount);
+ return true;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/m/MythosOfSnapdax.java b/Mage.Sets/src/mage/cards/m/MythosOfSnapdax.java
index 797e9b0d961..d8dd2294d6f 100644
--- a/Mage.Sets/src/mage/cards/m/MythosOfSnapdax.java
+++ b/Mage.Sets/src/mage/cards/m/MythosOfSnapdax.java
@@ -40,6 +40,7 @@ public class MythosOfSnapdax extends CardImpl {
super(card);
}
+ @Override
public MythosOfSnapdax copy() {
return new MythosOfSnapdax(this);
}
@@ -113,10 +114,8 @@ class MythosOfSnapdaxEffect extends OneShotEffect {
}
}
- for (Iterator iterator = game.getBattlefield().getActivePermanents(
- StaticFilters.FILTER_PERMANENT_NON_LAND, source.getControllerId(), game
- ).iterator(); iterator.hasNext(); ) {
- Permanent permanent = iterator.next();
+ for (Permanent permanent : game.getBattlefield().getActivePermanents(
+ StaticFilters.FILTER_PERMANENT_NON_LAND, source.getControllerId(), game)) {
if (permanent == null || toKeep.contains(permanent.getId())) {
continue;
}
diff --git a/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java b/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java
index be2690ceb58..bc03ebc017d 100644
--- a/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java
+++ b/Mage.Sets/src/mage/cards/n/NabanDeanOfIteration.java
@@ -1,24 +1,24 @@
package mage.cards.n;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
-import mage.constants.SubType;
-import mage.constants.SuperType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.SubType;
+import mage.constants.SuperType;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent;
import mage.game.events.NumberOfTriggersEvent;
+import java.util.UUID;
+
/**
*
* @author TheElk801
@@ -35,7 +35,7 @@ public final class NabanDeanOfIteration extends CardImpl {
this.toughness = new MageInt(1);
// If a Wizard entering the battlefield under your control causes a triggered ability of a permanent you control to trigger, that ability triggers an additional time.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NabanDeanOfIterationEffect()));
+ this.addAbility(new SimpleStaticAbility(new NabanDeanOfIterationEffect()));
}
public NabanDeanOfIteration(final NabanDeanOfIteration card) {
@@ -84,9 +84,7 @@ class NabanDeanOfIterationEffect extends ReplacementEffectImpl {
// Only for entering artifacts or creatures
if (entersTheBattlefieldEvent.getTarget().hasSubtype(SubType.WIZARD, game)) {
// Only for triggers of permanents
- if (game.getPermanent(numberOfTriggersEvent.getSourceId()) != null) {
- return true;
- }
+ return game.getPermanent(numberOfTriggersEvent.getSourceId()) != null;
}
}
}
diff --git a/Mage.Sets/src/mage/cards/n/NacatlWarPride.java b/Mage.Sets/src/mage/cards/n/NacatlWarPride.java
index 0bf4c1f9a20..3cb3c031b4c 100644
--- a/Mage.Sets/src/mage/cards/n/NacatlWarPride.java
+++ b/Mage.Sets/src/mage/cards/n/NacatlWarPride.java
@@ -23,9 +23,11 @@ import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
-import mage.game.permanent.token.EmptyToken;
import mage.target.targetpointer.FixedTargets;
-import mage.util.CardUtil;
+import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
+import mage.players.Player;
+import mage.target.targetpointer.FixedTarget;
+import mage.watchers.common.CreatureAttackedWhichPlayerWatcher;
/**
*
@@ -45,7 +47,10 @@ public final class NacatlWarPride extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MustBeBlockedByAtLeastOneSourceEffect(Duration.WhileOnBattlefield)));
// Whenever Nacatl War-Pride attacks, create X tokens that are copies of Nacatl War-Pride tapped and attacking, where X is the number of creatures defending player controls. Exile the tokens at the beginning of the next end step.
- this.addAbility(new AttacksTriggeredAbility(new NacatlWarPrideEffect(), false));
+ Ability ability = new AttacksTriggeredAbility(new NacatlWarPrideEffect(), false);
+ ability.addWatcher(new CreatureAttackedWhichPlayerWatcher());
+ this.addAbility(ability);
+
}
public NacatlWarPride(final NacatlWarPride card) {
@@ -62,7 +67,7 @@ class NacatlWarPrideEffect extends OneShotEffect {
public NacatlWarPrideEffect() {
super(Outcome.Benefit);
- this.staticText = "create X tokens that are copies of Nacatl War-Pride tapped and attacking, where X is the number of creatures defending player controls. Exile the tokens at the beginning of the next end step.";
+ this.staticText = "create X tokens that are copies of {this} tapped and attacking, where X is the number of creatures defending player controls. Exile the tokens at the beginning of the next end step";
}
public NacatlWarPrideEffect(final NacatlWarPrideEffect effect) {
@@ -76,13 +81,16 @@ class NacatlWarPrideEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Permanent origNactalWarPride = game.getPermanent(source.getSourceId());
+ Permanent origNactalWarPride = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (origNactalWarPride == null) {
return false;
}
+
+ CreatureAttackedWhichPlayerWatcher PlayerAttackedWatcher = game.getState().getWatcher(CreatureAttackedWhichPlayerWatcher.class);
// Count the number of creatures attacked opponent controls
- UUID defenderId = game.getCombat().getDefendingPlayerId(origNactalWarPride.getId(), game);
+ UUID defenderId = PlayerAttackedWatcher.getPlayerAttackedThisTurnByCreature(source.getSourceId());
+
int count = 0;
if (defenderId != null) {
count = game.getBattlefield().countAll(new FilterControlledCreaturePermanent(), defenderId, game);
@@ -92,24 +100,17 @@ class NacatlWarPrideEffect extends OneShotEffect {
return false;
}
- List copies = new ArrayList<>();
- for (int i = 0; i < count; i++) {
- EmptyToken token = new EmptyToken();
- CardUtil.copyTo(token).from(origNactalWarPride);
- token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId(), true, true);
-
- for (UUID tokenId : token.getLastAddedTokenIds()) { // by cards like Doubling Season multiple tokens can be added to the battlefield
- Permanent tokenPermanent = game.getPermanent(tokenId);
- if (tokenPermanent != null) {
- copies.add(tokenPermanent);
- }
- }
- }
-
+ List copies = new ArrayList<>();
+ Player controller = game.getPlayer(source.getControllerId());
+ CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(controller.getId(), null, false, count, true, true);
+ effect.setTargetPointer(new FixedTarget(origNactalWarPride, game));
+ effect.apply(game, source);
+ copies.addAll(effect.getAddedPermanent());
+
if (!copies.isEmpty()) {
FixedTargets fixedTargets = new FixedTargets(copies, game);
ExileTargetEffect exileEffect = new ExileTargetEffect();
- exileEffect.setTargetPointer(fixedTargets);
+ exileEffect.setTargetPointer(fixedTargets).setText("exile the tokens");
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect), source);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/n/NantukoCultivator.java b/Mage.Sets/src/mage/cards/n/NantukoCultivator.java
index f284e81d74a..1372acb7b24 100644
--- a/Mage.Sets/src/mage/cards/n/NantukoCultivator.java
+++ b/Mage.Sets/src/mage/cards/n/NantukoCultivator.java
@@ -1,42 +1,41 @@
-
package mage.cards.n;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.counters.CounterType;
-import mage.filter.common.FilterLandCard;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
-/**
- *
- * @author LoneFox
+import java.util.UUID;
+/**
+ * @author LoneFox
*/
public final class NantukoCultivator extends CardImpl {
public NantukoCultivator(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
this.subtype.add(SubType.INSECT);
this.subtype.add(SubType.DRUID);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// When Nantuko Cultivator enters the battlefield, you may discard any number of land cards. Put that many +1/+1 counters on Nantuko Cultivator and draw that many cards.
- this.addAbility(new EntersBattlefieldTriggeredAbility(new NantukoCultivatorEffect(), true));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new NantukoCultivatorEffect()));
}
- public NantukoCultivator(final NantukoCultivator card) {
+ private NantukoCultivator(final NantukoCultivator card) {
super(card);
}
@@ -48,40 +47,38 @@ public final class NantukoCultivator extends CardImpl {
class NantukoCultivatorEffect extends OneShotEffect {
- public NantukoCultivatorEffect() {
+ NantukoCultivatorEffect() {
super(Outcome.BoostCreature);
- staticText = "you may discard any number of land cards. Put that many +1/+1 counters on {this} and draw that many cards.";
+ staticText = "you may discard any number of land cards. " +
+ "Put that many +1/+1 counters on {this} and draw that many cards.";
+ }
+
+ private NantukoCultivatorEffect(final NantukoCultivatorEffect effect) {
+ super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- if(player != null) {
- TargetCardInHand toDiscard = new TargetCardInHand(0, Integer.MAX_VALUE, new FilterLandCard());
- if(player.chooseTarget(Outcome.Discard, toDiscard, source, game)) {
- int count = 0;
- for(UUID targetId: toDiscard.getTargets()) {
- player.discard(game.getCard(targetId), source, game);
- count++;
- }
- Permanent permanent = game.getPermanent(source.getSourceId());
- if(permanent != null) {
- permanent.addCounters(CounterType.P1P1.createInstance(count), source, game);
- }
- player.drawCards(count, source.getSourceId(), game);
- }
- return true;
+ if (player == null || player.getHand().count(StaticFilters.FILTER_CARD_LAND, game) < 1) {
+ return false;
}
- return false;
- }
-
- public NantukoCultivatorEffect(final NantukoCultivatorEffect effect) {
- super(effect);
+ TargetCardInHand toDiscard = new TargetCardInHand(0, Integer.MAX_VALUE, StaticFilters.FILTER_CARD_LAND);
+ player.chooseTarget(Outcome.AIDontUseIt, toDiscard, source, game);
+ int count = player.discard(new CardsImpl(toDiscard.getTargets()), source, game).size();
+ if (count < 1) {
+ return false;
+ }
+ Permanent permanent = game.getPermanent(source.getSourceId());
+ if (permanent != null) {
+ permanent.addCounters(CounterType.P1P1.createInstance(count), source, game);
+ }
+ player.drawCards(count, source.getSourceId(), game);
+ return true;
}
@Override
public NantukoCultivatorEffect copy() {
return new NantukoCultivatorEffect(this);
}
-
}
diff --git a/Mage.Sets/src/mage/cards/n/NarsetEnlightenedMaster.java b/Mage.Sets/src/mage/cards/n/NarsetEnlightenedMaster.java
index 8301068ad25..195dea2f7b6 100644
--- a/Mage.Sets/src/mage/cards/n/NarsetEnlightenedMaster.java
+++ b/Mage.Sets/src/mage/cards/n/NarsetEnlightenedMaster.java
@@ -116,13 +116,9 @@ class NarsetEnlightenedMasterCastFromExileEffect extends AsThoughEffectImpl {
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (objectId.equals(getTargetPointer().getFirst(game, source))
&& affectedControllerId.equals(source.getControllerId())) {
- Card card = game.getCard(objectId);
- if (card != null) {
- Player player = game.getPlayer(affectedControllerId);
- if (player != null) {
- player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
- return true;
- }
+ Player player = game.getPlayer(affectedControllerId);
+ if (player != null) {
+ return allowCardToPlayWithoutMana(objectId, source, affectedControllerId, game);
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/n/NarsetOfTheAncientWay.java b/Mage.Sets/src/mage/cards/n/NarsetOfTheAncientWay.java
index 336202caa96..1ef622e1c1e 100644
--- a/Mage.Sets/src/mage/cards/n/NarsetOfTheAncientWay.java
+++ b/Mage.Sets/src/mage/cards/n/NarsetOfTheAncientWay.java
@@ -3,25 +3,26 @@ package mage.cards.n;
import mage.ConditionalMana;
import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.SpellAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.costs.Cost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.GetEmblemEffect;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.abilities.mana.conditional.ManaCondition;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.ChoiceColor;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.SuperType;
import mage.game.Game;
import mage.game.command.emblems.NarsetOfTheAncientWayEmblem;
-import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.common.TargetCreatureOrPlaneswalker;
@@ -141,41 +142,12 @@ class NarsetOfTheAncientWayDrawEffect extends OneShotEffect {
if (card == null || card.isLand()) {
return false;
}
- game.addDelayedTriggeredAbility(new NarsetOfTheAncientWayReflexiveTriggeredAbility(card.getConvertedManaCost()), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class NarsetOfTheAncientWayReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- NarsetOfTheAncientWayReflexiveTriggeredAbility(int cmc) {
- super(new DamageTargetEffect(cmc), Duration.OneUse, true);
- this.addTarget(new TargetCreatureOrPlaneswalker());
- }
-
- private NarsetOfTheAncientWayReflexiveTriggeredAbility(final NarsetOfTheAncientWayReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public NarsetOfTheAncientWayReflexiveTriggeredAbility copy() {
- return new NarsetOfTheAncientWayReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "{this} deals damage to target creature or planeswalker " +
- "equal to the discarded card's converted mana cost";
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new DamageTargetEffect(card.getConvertedManaCost()), false, "{this} deals damage " +
+ "to target creature or planeswalker equal to the discarded card's converted mana cost"
+ );
+ ability.addTarget(new TargetCreatureOrPlaneswalker());
+ game.fireReflexiveTriggeredAbility(ability, source);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java b/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java
index 2b3ecb389c3..d9fe043d271 100644
--- a/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java
+++ b/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java
@@ -1,7 +1,5 @@
-
package mage.cards.n;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.condition.common.RaidCondition;
@@ -14,8 +12,9 @@ import mage.constants.TargetController;
import mage.target.common.TargetOpponent;
import mage.watchers.common.PlayerAttackedWatcher;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class NavigatorsRuin extends CardImpl {
@@ -25,14 +24,16 @@ public final class NavigatorsRuin extends CardImpl {
// Raid - At the beginning of your end step, if you attacked with a creature this turm, target opponent puts the top four cards of their library into their graveyard.
Ability ability = new ConditionalInterveningIfTriggeredAbility(
- new BeginningOfEndStepTriggeredAbility(new PutLibraryIntoGraveTargetEffect(4), TargetController.YOU, false),
- RaidCondition.instance,
- "Raid — At the beginning of your end step, if you attacked this turn, target opponent puts the top four cards of their library into their graveyard.");
+ new BeginningOfEndStepTriggeredAbility(
+ new PutLibraryIntoGraveTargetEffect(4), TargetController.YOU, false
+ ), RaidCondition.instance, "Raid — At the beginning of your end step, " +
+ "if you attacked this turn, target opponent mills four cards."
+ );
ability.addTarget(new TargetOpponent());
this.addAbility(ability, new PlayerAttackedWatcher());
}
- public NavigatorsRuin(final NavigatorsRuin card) {
+ private NavigatorsRuin(final NavigatorsRuin card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/n/NayaSojourners.java b/Mage.Sets/src/mage/cards/n/NayaSojourners.java
index 11b95f9cafc..a3b52564ead 100644
--- a/Mage.Sets/src/mage/cards/n/NayaSojourners.java
+++ b/Mage.Sets/src/mage/cards/n/NayaSojourners.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.CycleTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.CyclingAbility;
@@ -35,7 +35,7 @@ public final class NayaSojourners extends CardImpl {
// When you cycle Naya Sojourners or it dies, you may put a +1/+1 counter on target creature.
Ability ability1 = new CycleTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
- Ability ability2 = new DiesTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
+ Ability ability2 = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
ability1.addTarget(new TargetCreaturePermanent());
ability2.addTarget(new TargetCreaturePermanent());
this.addAbility(ability1);
diff --git a/Mage.Sets/src/mage/cards/n/NebelgastHerald.java b/Mage.Sets/src/mage/cards/n/NebelgastHerald.java
index 833bae9953b..115a9c4d257 100644
--- a/Mage.Sets/src/mage/cards/n/NebelgastHerald.java
+++ b/Mage.Sets/src/mage/cards/n/NebelgastHerald.java
@@ -1,10 +1,9 @@
package mage.cards.n;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.FlyingAbility;
@@ -12,39 +11,35 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.TargetController;
-import mage.constants.Zone;
-import mage.filter.common.FilterCreaturePermanent;
-import mage.target.common.TargetCreaturePermanent;
+import mage.filter.FilterPermanent;
+import mage.target.common.TargetOpponentsCreaturePermanent;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class NebelgastHerald extends CardImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("{this} or another Spirit");
- private static final FilterCreaturePermanent filterTarget = new FilterCreaturePermanent("creature an opponent controls");
-
- static {
- filter.add(TargetController.YOU.getControllerPredicate());
- filter.add(SubType.SPIRIT.getPredicate());
- filterTarget.add(TargetController.OPPONENT.getControllerPredicate());
- }
+ private static final FilterPermanent filter = new FilterPermanent(SubType.SPIRIT, "Spirit");
public NebelgastHerald(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add(SubType.SPIRIT);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// Flash
this.addAbility(FlashAbility.getInstance());
+
// Flying
this.addAbility(FlyingAbility.getInstance());
+
// Whenever Nebelgast Herald or another Spirit enters the battlefield under your control, tap target creature an opponent controls.
- Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new TapTargetEffect(), filter, false);
- ability.addTarget(new TargetCreaturePermanent(filterTarget));
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new TapTargetEffect(), filter, false, true
+ );
+ ability.addTarget(new TargetOpponentsCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java b/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java
index e1ba7288f1c..7eee5eec448 100644
--- a/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java
+++ b/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java
@@ -66,30 +66,28 @@ class NebuchadnezzarEffect extends OneShotEffect {
Player opponent = game.getPlayer(targetPointer.getFirst(game, source));
MageObject sourceObject = game.getObject(source.getSourceId());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (opponent != null && sourceObject != null && !cardName.isEmpty()) {
- int costX = source.getManaCostsToPay().getX();
- if (costX > 0 && !opponent.getHand().isEmpty()) {
- Cards cards = new CardsImpl();
- while (costX > 0) {
- Card card = opponent.getHand().getRandom(game);
- if (!cards.contains(card.getId())) {
- cards.add(card);
- costX--;
- }
- if (opponent.getHand().size() <= cards.size()) {
- break;
- }
- }
- opponent.revealCards(sourceObject.getIdName(), cards, game);
- for (Card cardToDiscard : cards.getCards(game)) {
- if (cardToDiscard.getName().equals(cardName)) {
- opponent.discard(cardToDiscard, source, game);
- }
- }
- }
+ if (opponent == null || sourceObject == null || cardName.isEmpty()) {
+ return false;
+ }
+ int costX = source.getManaCostsToPay().getX();
+ if (costX <= 0 || opponent.getHand().isEmpty()) {
return true;
}
- return false;
+ Cards cards = new CardsImpl();
+ while (costX > 0) {
+ Card card = opponent.getHand().getRandom(game);
+ if (!cards.contains(card.getId())) {
+ cards.add(card);
+ costX--;
+ }
+ if (opponent.getHand().size() <= cards.size()) {
+ break;
+ }
+ }
+ opponent.revealCards(sourceObject.getIdName(), cards, game);
+ cards.removeIf(uuid -> !cardName.equals(game.getCard(uuid).getName()));
+ opponent.discard(cards, source, game);
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/n/NecromanticSummons.java b/Mage.Sets/src/mage/cards/n/NecromanticSummons.java
index 772ec918db8..ef4c4f2ea1e 100644
--- a/Mage.Sets/src/mage/cards/n/NecromanticSummons.java
+++ b/Mage.Sets/src/mage/cards/n/NecromanticSummons.java
@@ -1,4 +1,3 @@
-
package mage.cards.n;
import java.util.UUID;
@@ -34,8 +33,11 @@ public final class NecromanticSummons extends CardImpl {
this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect());
this.getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard")));
- // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, that creature enters the battlefield with two additional +1/+1 counters on it.
- this.getSpellAbility().addEffect(new InfoEffect("\"
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, that creature enters the battlefield with two additional +1/+1 counters on it\""));
+ // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard,
+ // that creature enters the battlefield with two additional +1/+1 counters on it.
+ this.getSpellAbility().addEffect(new InfoEffect("
Spell mastery — If there are two or more "
+ + "instant and/or sorcery cards in your graveyard, that creature enters the "
+ + "battlefield with two additional +1/+1 counters on it."));
}
public NecromanticSummons(final NecromanticSummons card) {
diff --git a/Mage.Sets/src/mage/cards/n/Necromentia.java b/Mage.Sets/src/mage/cards/n/Necromentia.java
new file mode 100644
index 00000000000..888d90311df
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/n/Necromentia.java
@@ -0,0 +1,127 @@
+package mage.cards.n;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.ChooseACardNameEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+import mage.filter.predicate.mageobject.NamePredicate;
+import mage.game.Game;
+import mage.game.permanent.token.Token;
+import mage.game.permanent.token.ZombieToken;
+import mage.players.Player;
+import mage.target.TargetCard;
+import mage.target.common.TargetCardInLibrary;
+import mage.target.common.TargetOpponent;
+
+import java.util.HashSet;
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class Necromentia extends CardImpl {
+
+ public Necromentia(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{B}");
+
+ // Choose a card name other than a basic land card name. Search target opponent's graveyard, hand, and library for any number of cards with that name and exile them. That player shuffles their library, then creates a 2/2 black Zombie creature token for each card exiled from their hand this way.
+ this.getSpellAbility().addEffect(
+ new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NOT_BASIC_LAND_NAME)
+ );
+ this.getSpellAbility().addEffect(new NecromentiaEffect());
+ this.getSpellAbility().addTarget(new TargetOpponent());
+ }
+
+ private Necromentia(final Necromentia card) {
+ super(card);
+ }
+
+ @Override
+ public Necromentia copy() {
+ return new Necromentia(this);
+ }
+}
+
+class NecromentiaEffect extends OneShotEffect {
+
+ NecromentiaEffect() {
+ super(Outcome.Benefit);
+ staticText = "Search target opponent's graveyard, hand, and library for any number of cards with that name and exile them. That player shuffles their library, then creates a 2/2 black Zombie creature token for each card exiled from their hand this way";
+ }
+
+ private NecromentiaEffect(NecromentiaEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public NecromentiaEffect copy() {
+ return new NecromentiaEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ Player controller = game.getPlayer(source.getControllerId());
+ if (cardName != null && controller != null) {
+ FilterCard filter = new FilterCard("card named " + cardName);
+ filter.add(new NamePredicate(cardName));
+ Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
+
+ // cards in Graveyard
+ int cardsCount = (cardName.isEmpty() ? 0 : targetPlayer.getGraveyard().count(filter, game));
+ if (cardsCount > 0) {
+ filter.setMessage("card named " + cardName + " in the graveyard of " + targetPlayer.getName());
+ TargetCard target = new TargetCard(0, cardsCount, Zone.GRAVEYARD, filter);
+ if (controller.choose(Outcome.Exile, targetPlayer.getGraveyard(), target, game)) {
+ controller.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game);
+ }
+ }
+
+ // cards in Hand
+ int numberOfCardsExiledFromHand = 0;
+ cardsCount = (cardName.isEmpty() ? 0 : targetPlayer.getHand().count(filter, game));
+ if (cardsCount > 0) {
+ filter.setMessage("card named " + cardName + " in the hand of " + targetPlayer.getName());
+ TargetCard target = new TargetCard(0, cardsCount, Zone.HAND, filter);
+ if (controller.choose(Outcome.Exile, targetPlayer.getHand(), target, game)) {
+ numberOfCardsExiledFromHand = target.getTargets().size();
+ controller.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game);
+ }
+ } else {
+ targetPlayer.revealCards(targetPlayer.getName() + "'s Hand", targetPlayer.getHand(), game);
+ }
+
+ // cards in Library
+ Cards cardsInLibrary = new CardsImpl();
+ cardsInLibrary.addAll(targetPlayer.getLibrary().getCards(game));
+ cardsCount = (cardName.isEmpty() ? 0 : cardsInLibrary.count(filter, game));
+ if (cardsCount > 0) {
+ filter.setMessage("card named " + cardName + " in the library of " + targetPlayer.getLogName());
+ TargetCardInLibrary targetLib = new TargetCardInLibrary(0, cardsCount, filter);
+ if (controller.choose(Outcome.Exile, cardsInLibrary, targetLib, game)) {
+ controller.moveCards(new CardsImpl(targetLib.getTargets()), Zone.EXILED, source, game);
+ }
+ } else {
+ targetPlayer.revealCards(targetPlayer.getName() + "'s Library", new CardsImpl(new HashSet<>(targetPlayer.getLibrary().getCards(game))), game);
+ }
+
+ targetPlayer.shuffleLibrary(source, game);
+
+ if (numberOfCardsExiledFromHand > 0) {
+ game.getState().applyEffects(game);
+ Token zombieToken = new ZombieToken();
+ zombieToken.putOntoBattlefield(numberOfCardsExiledFromHand, game, source.getId(), targetPlayer.getId());
+ }
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/n/Necropede.java b/Mage.Sets/src/mage/cards/n/Necropede.java
index 8819ff3e5ee..5ec4b67ac1a 100644
--- a/Mage.Sets/src/mage/cards/n/Necropede.java
+++ b/Mage.Sets/src/mage/cards/n/Necropede.java
@@ -5,7 +5,7 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.InfectAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class Necropede extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
this.addAbility(InfectAbility.getInstance());
- Ability ability = new DiesTriggeredAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()), true);
+ Ability ability = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()), true);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/n/NehebDreadhordeChampion.java b/Mage.Sets/src/mage/cards/n/NehebDreadhordeChampion.java
index 338608ef223..535dcff7a90 100644
--- a/Mage.Sets/src/mage/cards/n/NehebDreadhordeChampion.java
+++ b/Mage.Sets/src/mage/cards/n/NehebDreadhordeChampion.java
@@ -6,7 +6,9 @@ import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.TrampleAbility;
-import mage.cards.*;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
@@ -18,6 +20,7 @@ import mage.target.TargetCard;
import mage.target.common.TargetCardInHand;
import java.util.UUID;
+import java.util.stream.IntStream;
/**
* @author TheElk801
@@ -80,18 +83,12 @@ class NehebDreadhordeChampionEffect extends OneShotEffect {
if (!player.choose(outcome, target, source.getSourceId(), game)) {
return false;
}
- Cards cards = new CardsImpl(target.getTargets());
- int counter = 0;
+ int counter = player.discard(new CardsImpl(target.getTargets()), source, game).size();
Mana mana = new Mana();
- for (Card card : cards.getCards(game)) {
- if (player.discard(card, source, game)) {
- counter++;
- mana.increaseRed();
- }
- }
- if (counter == 0) {
+ if (counter < 1) {
return true;
}
+ IntStream.range(0, counter).forEach(x -> mana.increaseRed());
player.drawCards(counter, source.getSourceId(), game);
player.getManaPool().addMana(mana, game, source, true);
return true;
diff --git a/Mage.Sets/src/mage/cards/n/NekoTe.java b/Mage.Sets/src/mage/cards/n/NekoTe.java
index 3b056ae55c5..656ce23f3a6 100644
--- a/Mage.Sets/src/mage/cards/n/NekoTe.java
+++ b/Mage.Sets/src/mage/cards/n/NekoTe.java
@@ -6,6 +6,7 @@ import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToACreatureAttachedTriggeredAbility;
import mage.abilities.common.DealsDamageToAPlayerAttachedTriggeredAbility;
import mage.abilities.condition.common.SourceOnBattlefieldCondition;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
import mage.abilities.effects.ContinuousRuleModifyingEffect;
@@ -19,6 +20,7 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.Zone;
/**
*
@@ -33,7 +35,8 @@ public final class NekoTe extends CardImpl {
// Whenever equipped creature deals damage to a creature, tap that creature. That creature doesn't untap during its controller's untap step for as long as Neko-Te remains on the battlefield.
ContinuousRuleModifyingEffect skipUntapEffect = new DontUntapInControllersUntapStepTargetEffect(Duration.WhileOnBattlefield);
skipUntapEffect.setText("That creature doesn't untap during its controller's untap step for as long as {this} remains on the battlefield");
- ConditionalContinuousRuleModifyingEffect effect = new ConditionalContinuousRuleModifyingEffect(skipUntapEffect, SourceOnBattlefieldCondition.instance);
+ ConditionalContinuousRuleModifyingEffect effect = new ConditionalContinuousRuleModifyingEffect(skipUntapEffect,
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD));
Ability ability = new DealsDamageToACreatureAttachedTriggeredAbility(new TapTargetEffect("that creature"), false, "equipped creature", false, true);
ability.addEffect(effect);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/n/NemesisOfMortals.java b/Mage.Sets/src/mage/cards/n/NemesisOfMortals.java
index 45bcc9b02d3..4f96bbbc4c3 100644
--- a/Mage.Sets/src/mage/cards/n/NemesisOfMortals.java
+++ b/Mage.Sets/src/mage/cards/n/NemesisOfMortals.java
@@ -1,12 +1,14 @@
package mage.cards.n;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
-import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.MonstrosityAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -16,6 +18,8 @@ import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
+import java.util.UUID;
+
/**
* @author LevelX2
*/
@@ -29,8 +33,10 @@ public final class NemesisOfMortals extends CardImpl {
this.toughness = new MageInt(5);
// Nemesis of Mortals costs {1} less to cast for each creature card in your graveyard.
- Ability ability = new SimpleStaticAbility(Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_CREATURE));
+ DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
ability.setRuleAtTheTop(true);
+ ability.addHint(new ValueHint("Creature card in your graveyard", xValue));
this.addAbility(ability);
// {7}{G}{G}: Monstrosity 5. This ability costs {1} less to activate for each creature card in your graveyard.
diff --git a/Mage.Sets/src/mage/cards/n/NemesisOfReason.java b/Mage.Sets/src/mage/cards/n/NemesisOfReason.java
index e3dd3529c90..bb8296c7b67 100644
--- a/Mage.Sets/src/mage/cards/n/NemesisOfReason.java
+++ b/Mage.Sets/src/mage/cards/n/NemesisOfReason.java
@@ -2,7 +2,6 @@
package mage.cards.n;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
@@ -16,27 +15,26 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.targetpointer.FixedTarget;
+import java.util.UUID;
+
/**
- *
* @author Loki
*/
public final class NemesisOfReason extends CardImpl {
- public NemesisOfReason (UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{B}");
+ public NemesisOfReason(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{B}");
this.subtype.add(SubType.LEVIATHAN);
this.subtype.add(SubType.HORROR);
-
+
this.power = new MageInt(3);
this.toughness = new MageInt(7);
-
+
// Whenever Nemesis of Reason attacks, defending player puts the top ten cards of their library into their graveyard.
- Effect effect = new PutLibraryIntoGraveTargetEffect(10);
- effect.setText("defending player puts the top ten cards of their library into their graveyard");
- this.addAbility(new NemesisOfReasonTriggeredAbility(effect));
+ this.addAbility(new NemesisOfReasonTriggeredAbility(new PutLibraryIntoGraveTargetEffect(10)));
}
- public NemesisOfReason (final NemesisOfReason card) {
+ public NemesisOfReason(final NemesisOfReason card) {
super(card);
}
@@ -47,12 +45,12 @@ public final class NemesisOfReason extends CardImpl {
}
class NemesisOfReasonTriggeredAbility extends TriggeredAbilityImpl {
-
+
NemesisOfReasonTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect);
}
- NemesisOfReasonTriggeredAbility(final NemesisOfReasonTriggeredAbility ability) {
+ private NemesisOfReasonTriggeredAbility(final NemesisOfReasonTriggeredAbility ability) {
super(ability);
}
@@ -68,9 +66,9 @@ class NemesisOfReasonTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- if (event.getSourceId().equals(this.getSourceId()) ) {
+ if (event.getSourceId().equals(this.getSourceId())) {
UUID defenderId = game.getCombat().getDefendingPlayerId(this.getSourceId(), game);
- for (Effect effect : this.getEffects()) {
+ for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(defenderId));
}
return true;
@@ -80,6 +78,6 @@ class NemesisOfReasonTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever {this} attacks, defending player puts the top ten cards of their library into their graveyard.";
+ return "Whenever {this} attacks, defending player mills ten cards.";
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/n/Nevermore.java b/Mage.Sets/src/mage/cards/n/Nevermore.java
index 755bf786cd2..36557baebe2 100644
--- a/Mage.Sets/src/mage/cards/n/Nevermore.java
+++ b/Mage.Sets/src/mage/cards/n/Nevermore.java
@@ -1,6 +1,5 @@
package mage.cards.n;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
@@ -16,9 +15,11 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
+import mage.util.CardUtil;
+
+import java.util.UUID;
/**
- *
* @author BetaSteward_at_googlemail.com
*/
public final class Nevermore extends CardImpl {
@@ -70,9 +71,8 @@ class NevermoreEffect2 extends ContinuousRuleModifyingEffectImpl {
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.CAST_SPELL) {
MageObject object = game.getObject(event.getSourceId());
- if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) {
- return true;
- }
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ return CardUtil.haveSameNames(object, cardName, game);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/n/NeyithOfTheDireHunt.java b/Mage.Sets/src/mage/cards/n/NeyithOfTheDireHunt.java
new file mode 100644
index 00000000000..179dd36c891
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/n/NeyithOfTheDireHunt.java
@@ -0,0 +1,148 @@
+package mage.cards.n;
+
+import mage.MageInt;
+import mage.MageObjectReference;
+import mage.abilities.Ability;
+import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.BeginningOfCombatTriggeredAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.combat.MustBeBlockedByAtLeastOneTargetEffect;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.game.Controllable;
+import mage.game.Game;
+import mage.game.combat.CombatGroup;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.Collection;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class NeyithOfTheDireHunt extends CardImpl {
+
+ public NeyithOfTheDireHunt(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WARRIOR);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Whenever one or more creatures you control fight or become blocked, draw a card.
+ this.addAbility(new NeyithOfTheDireHuntTriggeredAbility());
+
+ // At the beginning of combat on your turn, you may pay {2}{R/G}. If you do, double target creature's power until end of turn. That creature must be blocked this combat if able.
+ Ability ability = new BeginningOfCombatTriggeredAbility(new DoIfCostPaid(
+ new NeyithOfTheDireHuntEffect(), new ManaCostsImpl<>("{2}{R/G}")
+ ), TargetController.YOU, false);
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ }
+
+ private NeyithOfTheDireHunt(final NeyithOfTheDireHunt card) {
+ super(card);
+ }
+
+ @Override
+ public NeyithOfTheDireHunt copy() {
+ return new NeyithOfTheDireHunt(this);
+ }
+}
+
+// TODO: this needs to work with cards like Choking Vines
+class NeyithOfTheDireHuntTriggeredAbility extends TriggeredAbilityImpl {
+
+ NeyithOfTheDireHuntTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1));
+ }
+
+ private NeyithOfTheDireHuntTriggeredAbility(final NeyithOfTheDireHuntTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.BATCH_FIGHT
+ || event.getType() == GameEvent.EventType.DECLARED_BLOCKERS;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ switch (event.getType()) {
+ case BATCH_FIGHT:
+ Object value = game.getState().getValue("batchFight_" + event.getData());
+ if (!(value instanceof Set)) {
+ return false;
+ }
+ Set permanents = (Set) value;
+ return permanents
+ .stream()
+ .map(mor -> mor.getPermanentOrLKIBattlefield(game))
+ .filter(Objects::nonNull)
+ .map(Controllable::getControllerId)
+ .anyMatch(this.getControllerId()::equals);
+ case DECLARED_BLOCKERS:
+ return game.getCombat()
+ .getBlockingGroups()
+ .stream()
+ .map(CombatGroup::getAttackers)
+ .flatMap(Collection::stream)
+ .map(game::getControllerId)
+ .anyMatch(this.getControllerId()::equals);
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public NeyithOfTheDireHuntTriggeredAbility copy() {
+ return new NeyithOfTheDireHuntTriggeredAbility(this);
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever one or more creatures you control fight or become blocked, draw a card.";
+ }
+}
+
+class NeyithOfTheDireHuntEffect extends OneShotEffect {
+
+ NeyithOfTheDireHuntEffect() {
+ super(Outcome.Benefit);
+ staticText = "double target creature's power until end of turn. " +
+ "That creature must be blocked this combat if able";
+ }
+
+ private NeyithOfTheDireHuntEffect(final NeyithOfTheDireHuntEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public NeyithOfTheDireHuntEffect copy() {
+ return new NeyithOfTheDireHuntEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanent(source.getFirstTarget());
+ if (permanent == null) {
+ return false;
+ }
+ int power = permanent.getPower().getValue();
+ game.addEffect(new BoostTargetEffect(power, 0, Duration.EndOfTurn), source);
+ game.addEffect(new MustBeBlockedByAtLeastOneTargetEffect(Duration.EndOfCombat), source);
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/n/NezahalPrimalTide.java b/Mage.Sets/src/mage/cards/n/NezahalPrimalTide.java
index 3a28e370c3f..4332784352f 100644
--- a/Mage.Sets/src/mage/cards/n/NezahalPrimalTide.java
+++ b/Mage.Sets/src/mage/cards/n/NezahalPrimalTide.java
@@ -3,7 +3,7 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SpellCastOpponentTriggeredAbility;
@@ -47,7 +47,7 @@ public final class NezahalPrimalTide extends CardImpl {
this.toughness = new MageInt(7);
// Nezahal, Primal Tide can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// You have no maximum hand size.
Effect effect = new MaximumHandSizeControllerEffect(Integer.MAX_VALUE, Duration.WhileOnBattlefield, MaximumHandSizeControllerEffect.HandSizeModification.SET);
diff --git a/Mage.Sets/src/mage/cards/n/NiambiEsteemedSpeaker.java b/Mage.Sets/src/mage/cards/n/NiambiEsteemedSpeaker.java
new file mode 100644
index 00000000000..515650dbab4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/n/NiambiEsteemedSpeaker.java
@@ -0,0 +1,109 @@
+package mage.cards.n;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.DiscardTargetCost;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.ReturnToHandTargetEffect;
+import mage.abilities.keyword.FlashAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.filter.FilterCard;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.permanent.AnotherPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetCardInHand;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class NiambiEsteemedSpeaker extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterControlledCreaturePermanent("another target creature you control");
+ private static final FilterCard filter2 = new FilterCard("a legendary card");
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ filter2.add(SuperType.LEGENDARY.getPredicate());
+ }
+
+ public NiambiEsteemedSpeaker(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{U}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // Flash
+ this.addAbility(FlashAbility.getInstance());
+
+ // When Niambi, Esteemed Speaker enters the battlefield, you may return another target creature you control to its owner's hand. If you do, you gain life equal to that creature's converted mana cost.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true);
+ ability.addEffect(new NiambiEsteemedSpeakerEffect());
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(ability);
+
+ // {1}{W}{U}, {T}, Discard a legendary card: Draw two cards.
+ ability = new SimpleActivatedAbility(
+ new DrawCardSourceControllerEffect(2), new ManaCostsImpl("{1}{W}{U}")
+ );
+ ability.addCost(new TapSourceCost());
+ ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter2)));
+ this.addAbility(ability);
+ }
+
+ private NiambiEsteemedSpeaker(final NiambiEsteemedSpeaker card) {
+ super(card);
+ }
+
+ @Override
+ public NiambiEsteemedSpeaker copy() {
+ return new NiambiEsteemedSpeaker(this);
+ }
+}
+
+class NiambiEsteemedSpeakerEffect extends OneShotEffect {
+
+ NiambiEsteemedSpeakerEffect() {
+ super(Outcome.Benefit);
+ staticText = "If you do, you gain life equal to that creature's converted mana cost.";
+ }
+
+ private NiambiEsteemedSpeakerEffect(final NiambiEsteemedSpeakerEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public NiambiEsteemedSpeakerEffect copy() {
+ return new NiambiEsteemedSpeakerEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanentOrLKIBattlefield(source.getFirstTarget());
+ Player player = game.getPlayer(source.getControllerId());
+ if (permanent == null || player == null) {
+ return false;
+ }
+ return permanent.getConvertedManaCost() > 0
+ && player.gainLife(permanent.getConvertedManaCost(), game, source) > 0;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/n/NicolBolasGodPharaoh.java b/Mage.Sets/src/mage/cards/n/NicolBolasGodPharaoh.java
index 476f219ad1c..9fdcb6b28f1 100644
--- a/Mage.Sets/src/mage/cards/n/NicolBolasGodPharaoh.java
+++ b/Mage.Sets/src/mage/cards/n/NicolBolasGodPharaoh.java
@@ -21,11 +21,12 @@ import mage.target.Target;
import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetOpponent;
-import mage.target.targetpointer.FixedTarget;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
+import mage.target.targetpointer.FixedTarget;
/**
* @author Will
@@ -168,9 +169,8 @@ class NicolBolasGodPharaohPlusTwoEffect extends OneShotEffect {
if (card.isLand()) {
continue;
}
- ContinuousEffect effect = new NicolBolasGodPharaohFromExileEffect();
- effect.setTargetPointer(new FixedTarget(card.getId(),
- game.getState().getZoneChangeCounter(card.getId())));
+ ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, TargetController.YOU, Duration.EndOfTurn, true);
+ effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source);
break;
} while (library.hasCards()
@@ -178,48 +178,3 @@ class NicolBolasGodPharaohPlusTwoEffect extends OneShotEffect {
return true;
}
}
-
-class NicolBolasGodPharaohFromExileEffect extends AsThoughEffectImpl {
-
- NicolBolasGodPharaohFromExileEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
- staticText = "You may cast card from exile";
- }
-
- private NicolBolasGodPharaohFromExileEffect(final NicolBolasGodPharaohFromExileEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public NicolBolasGodPharaohFromExileEffect copy() {
- return new NicolBolasGodPharaohFromExileEffect(this);
- }
-
- @Override
- public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
- if (sourceId == null
- || !sourceId.equals(getTargetPointer().getFirst(game, source))
- || !affectedControllerId.equals(source.getControllerId())) {
- return false;
- }
- Card card = game.getCard(sourceId);
- if (card == null
- || game.getState().getZone(sourceId) != Zone.EXILED) {
- return false;
- }
- Player controller = game.getPlayer(affectedControllerId);
- if (controller == null) {
- return false;
- }
- controller.setCastSourceIdWithAlternateMana(
- sourceId,
- null,
- card.getSpellAbility().getCosts());
- return true;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/n/NightSoil.java b/Mage.Sets/src/mage/cards/n/NightSoil.java
index 7817ea9b166..4e72c20f7e3 100644
--- a/Mage.Sets/src/mage/cards/n/NightSoil.java
+++ b/Mage.Sets/src/mage/cards/n/NightSoil.java
@@ -1,7 +1,5 @@
-
package mage.cards.n;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.ExileFromGraveCost;
@@ -15,19 +13,19 @@ import mage.filter.common.FilterCreatureCard;
import mage.game.permanent.token.SaprolingToken;
import mage.target.common.TargetCardInASingleGraveyard;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class NightSoil extends CardImpl {
public NightSoil(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}{G}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}{G}");
// {1}, Exile two creature cards from a single graveyard: Create a 1/1 green Saproling creature token.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SaprolingToken()), new GenericManaCost(1));
- ability.addCost(new ExileFromGraveCost(new TargetCardInASingleGraveyard(2,2, new FilterCreatureCard("two creature cards from a single graveyard"))));
+ ability.addCost(new ExileFromGraveCost(new TargetCardInASingleGraveyard(2, 2, new FilterCreatureCard("two creature cards"))));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/n/NightscapeFamiliar.java b/Mage.Sets/src/mage/cards/n/NightscapeFamiliar.java
index ad4ec58da7e..2a7ae10e1dc 100644
--- a/Mage.Sets/src/mage/cards/n/NightscapeFamiliar.java
+++ b/Mage.Sets/src/mage/cards/n/NightscapeFamiliar.java
@@ -1,7 +1,5 @@
-
package mage.cards.n;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleActivatedAbility;
@@ -18,8 +16,9 @@ import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class NightscapeFamiliar extends CardImpl {
@@ -33,7 +32,7 @@ public final class NightscapeFamiliar extends CardImpl {
}
public NightscapeFamiliar(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(1);
@@ -41,6 +40,7 @@ public final class NightscapeFamiliar extends CardImpl {
// Blue spells and red spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
+
// {1}{B}: Regenerate Nightscape Familiar.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{1}{B}")));
}
diff --git a/Mage.Sets/src/mage/cards/n/Nightsnare.java b/Mage.Sets/src/mage/cards/n/Nightsnare.java
index a0326c9f49f..e0535648e96 100644
--- a/Mage.Sets/src/mage/cards/n/Nightsnare.java
+++ b/Mage.Sets/src/mage/cards/n/Nightsnare.java
@@ -52,32 +52,27 @@ class NightsnareDiscardEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
Player controller = game.getPlayer(source.getControllerId());
- if (player != null && controller != null) {
- if (!player.getHand().isEmpty()) {
- Cards revealedCards = new CardsImpl();
- revealedCards.addAll(player.getHand());
- Card sourceCard = game.getCard(source.getSourceId());
- player.revealCards(sourceCard != null ? sourceCard.getIdName() : "Discard", revealedCards, game);
- // You may choose a nonland card from it.
- if (controller.chooseUse(outcome, "Choose a a card to discard? (Otherwise " + player.getLogName() + " has to discard 2 cards).", source, game)) {
- TargetCard target = new TargetCard(1, Zone.HAND, new FilterNonlandCard());
- if (controller.choose(Outcome.Benefit, revealedCards, target, game)) {
- for (UUID targetId : target.getTargets()) {
- Card card = revealedCards.get(targetId, game);
- player.discard(card, source, game);
-
- }
- }
-
- } else {
- player.discard(2, false, source, game);
- }
- }
- return true;
-
+ if (player == null || controller == null) {
+ return false;
}
- return false;
-
+ if (player.getHand().isEmpty()) {
+ return true;
+ }
+ Cards revealedCards = new CardsImpl();
+ revealedCards.addAll(player.getHand());
+ Card sourceCard = game.getCard(source.getSourceId());
+ player.revealCards(sourceCard != null ? sourceCard.getIdName() : "Discard", revealedCards, game);
+ // You may choose a nonland card from it.
+ if (!controller.chooseUse(outcome, "Choose a card to discard? (Otherwise " + player.getLogName() + " has to discard 2 cards).", source, game)) {
+ player.discard(2, false, source, game);
+ return true;
+ }
+ TargetCard target = new TargetCard(1, Zone.HAND, new FilterNonlandCard());
+ if (controller.choose(Outcome.Benefit, revealedCards, target, game)) {
+ Card card = revealedCards.get(target.getFirstTarget(), game);
+ player.discard(card, source, game);
+ }
+ return true;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/n/NihilSpellbomb.java b/Mage.Sets/src/mage/cards/n/NihilSpellbomb.java
index ecc51d332ae..e26f856ce80 100644
--- a/Mage.Sets/src/mage/cards/n/NihilSpellbomb.java
+++ b/Mage.Sets/src/mage/cards/n/NihilSpellbomb.java
@@ -2,7 +2,7 @@
package mage.cards.n;
import java.util.UUID;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
@@ -31,7 +31,7 @@ public final class NihilSpellbomb extends CardImpl {
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
// When Nihil Spellbomb is put into a graveyard from the battlefield, you may pay {B}. If you do, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{B}")), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{B}")), false));
}
public NihilSpellbomb(final NihilSpellbomb card) {
diff --git a/Mage.Sets/src/mage/cards/n/NihilisticGlee.java b/Mage.Sets/src/mage/cards/n/NihilisticGlee.java
index 5590c723168..5cd67d38c88 100644
--- a/Mage.Sets/src/mage/cards/n/NihilisticGlee.java
+++ b/Mage.Sets/src/mage/cards/n/NihilisticGlee.java
@@ -1,7 +1,5 @@
-
package mage.cards.n;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.common.HellbentCondition;
@@ -20,8 +18,9 @@ import mage.constants.CardType;
import mage.constants.Zone;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class NihilisticGlee extends CardImpl {
@@ -34,7 +33,7 @@ public final class NihilisticGlee extends CardImpl {
new LoseLifeTargetEffect(1),
new ManaCostsImpl("{2}{B}")
);
- ability.addEffect(new GainLifeEffect(1).setText("and you gain 1 life"));
+ ability.addEffect(new GainLifeEffect(1).concatBy("and"));
ability.addCost(new DiscardCardCost());
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/n/NimDevourer.java b/Mage.Sets/src/mage/cards/n/NimDevourer.java
index d386661b5c6..80c31583b95 100644
--- a/Mage.Sets/src/mage/cards/n/NimDevourer.java
+++ b/Mage.Sets/src/mage/cards/n/NimDevourer.java
@@ -1,59 +1,50 @@
-
package mage.cards.n;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.IsStepCondition;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalActivatedAbility;
-import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.PhaseStep;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.common.FilterControlledCreaturePermanent;
-import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledPermanent;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class NimDevourer extends CardImpl {
-
- private static final FilterControlledPermanent filter = new FilterControlledPermanent("artifact you control");
-
- static {
- filter.add(CardType.ARTIFACT.getPredicate());
- }
public NimDevourer(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(4);
this.toughness = new MageInt(1);
// Nim Devourer gets +1/+0 for each artifact you control.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(new PermanentsOnBattlefieldCount(filter), StaticValue.get(0), Duration.WhileOnBattlefield)));
-
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new BoostSourceEffect(ArtifactYouControlCount.instance, StaticValue.get(0), Duration.WhileOnBattlefield))
+ .addHint(ArtifactYouControlHint.instance)
+ );
+
// {B}{B}: Return Nim Devourer from your graveyard to the battlefield, then sacrifice a creature. Activate this ability only during your upkeep.
- Ability ability = new ConditionalActivatedAbility(Zone.GRAVEYARD,
- new ReturnSourceFromGraveyardToBattlefieldEffect(),
- new ManaCostsImpl("{B}{B}"),
+ Ability ability = new ConditionalActivatedAbility(Zone.GRAVEYARD,
+ new ReturnSourceFromGraveyardToBattlefieldEffect(),
+ new ManaCostsImpl("{B}{B}"),
new IsStepCondition(PhaseStep.UPKEEP), null);
ability.addEffect(new NimDevourerEffect());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/n/NimGrotesque.java b/Mage.Sets/src/mage/cards/n/NimGrotesque.java
index 03442660b89..63cb3360fbd 100644
--- a/Mage.Sets/src/mage/cards/n/NimGrotesque.java
+++ b/Mage.Sets/src/mage/cards/n/NimGrotesque.java
@@ -1,35 +1,37 @@
-
package mage.cards.n;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
+import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.common.FilterControlledArtifactPermanent;
+
+import java.util.UUID;
/**
- *
* @author Plopman
*/
public final class NimGrotesque extends CardImpl {
public NimGrotesque(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{B}");
this.subtype.add(SubType.ZOMBIE);
this.power = new MageInt(3);
this.toughness = new MageInt(6);
// Nim Grotesque gets +1/+0 for each artifact you control.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostSourceEffect(new PermanentsOnBattlefieldCount(new FilterControlledArtifactPermanent()), StaticValue.get(0), Duration.WhileOnBattlefield)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new BoostSourceEffect(ArtifactYouControlCount.instance, StaticValue.get(0), Duration.WhileOnBattlefield))
+ .addHint(ArtifactYouControlHint.instance)
+ );
}
public NimGrotesque(final NimGrotesque card) {
diff --git a/Mage.Sets/src/mage/cards/n/NineLives.java b/Mage.Sets/src/mage/cards/n/NineLives.java
new file mode 100644
index 00000000000..aa28b276483
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/n/NineLives.java
@@ -0,0 +1,127 @@
+package mage.cards.n;
+
+import mage.abilities.Ability;
+import mage.abilities.StateTriggeredAbility;
+import mage.abilities.common.LeavesBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.PreventionEffectImpl;
+import mage.abilities.effects.common.ExileSourceEffect;
+import mage.abilities.effects.common.LoseGameSourceControllerEffect;
+import mage.abilities.keyword.HexproofAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Zone;
+import mage.counters.CounterType;
+import mage.game.Game;
+import mage.game.events.DamageEvent;
+import mage.game.events.GameEvent;
+import mage.game.events.PreventDamageEvent;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+
+import java.util.UUID;
+
+/**
+ * @author arcox
+ */
+public final class NineLives extends CardImpl {
+
+ public NineLives(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}");
+
+ // Hexproof
+ this.addAbility(HexproofAbility.getInstance());
+
+ // If a source would deal damage to you, prevent that damage and put an incarnation counter on Nine Lives.
+ this.addAbility(new SimpleStaticAbility(new NineLivesPreventionEffect()));
+
+ // When there are nine or more incarnation counters on Nine Lives, exile it.
+ this.addAbility(new NineLivesStateTriggeredAbility());
+
+ // When Nine Lives leaves the battlefield, you lose the game.
+ this.addAbility(new LeavesBattlefieldTriggeredAbility(new LoseGameSourceControllerEffect(), false));
+ }
+
+ public NineLives(final NineLives card) {
+ super(card);
+ }
+
+ @Override
+ public NineLives copy() {
+ return new NineLives(this);
+ }
+}
+
+
+class NineLivesPreventionEffect extends PreventionEffectImpl {
+
+ public NineLivesPreventionEffect() {
+ super(Duration.WhileOnBattlefield);
+ staticText = "If a source would deal damage to you, prevent that damage and put an incarnation counter on {this}";
+ }
+
+ public NineLivesPreventionEffect(final NineLivesPreventionEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public NineLivesPreventionEffect copy() {
+ return new NineLivesPreventionEffect(this);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ GameEvent preventEvent = new PreventDamageEvent(source.getFirstTarget(), source.getSourceId(), source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage());
+ if (!game.replaceEvent(preventEvent)) {
+ int damage = event.getAmount();
+ Player player = game.getPlayer(source.getControllerId());
+ if (player != null) {
+ Permanent nineLives = source.getSourcePermanentIfItStillExists(game);
+ if (nineLives != null) {
+ nineLives.addCounters(CounterType.INCARNATION.createInstance(1), source, game);
+ }
+ }
+ event.setAmount(0);
+ game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), damage));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (super.applies(event, source, game)) {
+ return event.getTargetId().equals(source.getControllerId());
+ }
+ return false;
+ }
+}
+
+
+class NineLivesStateTriggeredAbility extends StateTriggeredAbility {
+
+ public NineLivesStateTriggeredAbility() {
+ super(Zone.BATTLEFIELD, new ExileSourceEffect());
+ }
+
+ public NineLivesStateTriggeredAbility(final NineLivesStateTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public NineLivesStateTriggeredAbility copy() {
+ return new NineLivesStateTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ Permanent permanent = game.getPermanent(getSourceId());
+ return permanent != null && permanent.getCounters(game).getCount(CounterType.INCARNATION) >= 9;
+ }
+
+ @Override
+ public String getRule() {
+ return "When there are nine or more incarnation counters on {this}, exile it.";
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/n/NivMizzetParun.java b/Mage.Sets/src/mage/cards/n/NivMizzetParun.java
index 8cfccd5137c..eabca9b30c2 100644
--- a/Mage.Sets/src/mage/cards/n/NivMizzetParun.java
+++ b/Mage.Sets/src/mage/cards/n/NivMizzetParun.java
@@ -3,7 +3,7 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.DrawCardControllerTriggeredAbility;
import mage.abilities.common.SpellCastAllTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -33,7 +33,7 @@ public final class NivMizzetParun extends CardImpl {
this.toughness = new MageInt(5);
// This spell can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Flying
this.addAbility(FlyingAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/n/NobleBenefactor.java b/Mage.Sets/src/mage/cards/n/NobleBenefactor.java
index d223291a3ca..7abb0ccf4bb 100644
--- a/Mage.Sets/src/mage/cards/n/NobleBenefactor.java
+++ b/Mage.Sets/src/mage/cards/n/NobleBenefactor.java
@@ -3,7 +3,7 @@ package mage.cards.n;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
@@ -33,7 +33,7 @@ public final class NobleBenefactor extends CardImpl {
this.toughness = new MageInt(2);
// When Noble Benefactor dies, each player may search their library for a card and put that card into their hand. Then each player who searched their library this way shuffles it.
- this.addAbility(new DiesTriggeredAbility(new NobleBenefactorEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new NobleBenefactorEffect()));
}
public NobleBenefactor(final NobleBenefactor card) {
diff --git a/Mage.Sets/src/mage/cards/n/NocturnalFeeder.java b/Mage.Sets/src/mage/cards/n/NocturnalFeeder.java
new file mode 100644
index 00000000000..6f1dd06950b
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/n/NocturnalFeeder.java
@@ -0,0 +1,46 @@
+package mage.cards.n;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DiesSourceTriggeredAbility;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.common.LoseLifeOpponentsEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class NocturnalFeeder extends CardImpl {
+
+ public NocturnalFeeder(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
+
+ this.subtype.add(SubType.VAMPIRE);
+ this.subtype.add(SubType.ROGUE);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // When Nocturnal Feeder dies, each opponent loses 2 life and you gain 2 life.
+ Ability ability = new DiesSourceTriggeredAbility(new LoseLifeOpponentsEffect(2));
+ ability.addEffect(new GainLifeEffect(2).concatBy("and"));
+ this.addAbility(ability);
+ }
+
+ private NocturnalFeeder(final NocturnalFeeder card) {
+ super(card);
+ }
+
+ @Override
+ public NocturnalFeeder copy() {
+ return new NocturnalFeeder(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/n/NogginWhack.java b/Mage.Sets/src/mage/cards/n/NogginWhack.java
index 5aa88225c42..f7627b55266 100644
--- a/Mage.Sets/src/mage/cards/n/NogginWhack.java
+++ b/Mage.Sets/src/mage/cards/n/NogginWhack.java
@@ -1,19 +1,12 @@
-
package mage.cards.n;
-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.CardImpl;
-import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
+import mage.cards.*;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
@@ -21,14 +14,16 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
+import java.util.List;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class NogginWhack extends CardImpl {
public NogginWhack(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.TRIBAL,CardType.SORCERY},"{2}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.TRIBAL, CardType.SORCERY}, "{2}{B}{B}");
this.subtype.add(SubType.ROGUE);
@@ -40,7 +35,7 @@ public final class NogginWhack extends CardImpl {
}
- public NogginWhack(final NogginWhack card) {
+ private NogginWhack(final NogginWhack card) {
super(card);
}
@@ -52,12 +47,12 @@ public final class NogginWhack extends CardImpl {
class NogginWhackEffect extends OneShotEffect {
- public NogginWhackEffect() {
+ NogginWhackEffect() {
super(Outcome.Benefit);
this.staticText = "Target player reveals three cards from their hand. You choose two of them. That player discards those cards";
}
- public NogginWhackEffect(final NogginWhackEffect effect) {
+ private NogginWhackEffect(final NogginWhackEffect effect) {
super(effect);
}
@@ -71,40 +66,35 @@ class NogginWhackEffect extends OneShotEffect {
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());
- 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"));
-
- if (!revealedCards.isEmpty()) {
- targetPlayer.revealCards("Noggin Whack", revealedCards, game);
- controller.chooseTarget(Outcome.Exile, revealedCards, targetInHand, source, game);
- for (UUID cardId : targetInHand.getTargets()) {
- Card card = game.getCard(cardId);
- if (card != null) {
- controller.discard(card, source, game);
- }
- }
- }
- return true;
+ if (controller == null || targetPlayer == null || sourceCard == null) {
+ return false;
}
- return false;
+ Cards cardsInHand = new CardsImpl();
+ cardsInHand.addAll(targetPlayer.getHand());
+
+ int count = Math.min(cardsInHand.size(), 3);
+
+ TargetCard target = new TargetCard(count, Zone.HAND, new FilterCard());
+ 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"));
+
+ if (!revealedCards.isEmpty()) {
+ targetPlayer.revealCards(source, revealedCards, game);
+ controller.chooseTarget(Outcome.Exile, revealedCards, targetInHand, source, game);
+ targetPlayer.discard(new CardsImpl(targetInHand.getTargets()), source, game);
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/n/NorwoodWarrior.java b/Mage.Sets/src/mage/cards/n/NorwoodWarrior.java
index 5dcf344868c..d45ecb8603b 100644
--- a/Mage.Sets/src/mage/cards/n/NorwoodWarrior.java
+++ b/Mage.Sets/src/mage/cards/n/NorwoodWarrior.java
@@ -3,7 +3,7 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class NorwoodWarrior extends CardImpl {
// Whenever Norwood Warrior becomes blocked, it gets +1/+1 until end of turn.
Effect effect = new BoostSourceEffect(1, 1, Duration.EndOfTurn);
effect.setText("it gets +1/+1 until end of turn");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public NorwoodWarrior(final NorwoodWarrior card) {
diff --git a/Mage.Sets/src/mage/cards/n/NotOfThisWorld.java b/Mage.Sets/src/mage/cards/n/NotOfThisWorld.java
index 651ff4a65d7..edc5b0ed969 100644
--- a/Mage.Sets/src/mage/cards/n/NotOfThisWorld.java
+++ b/Mage.Sets/src/mage/cards/n/NotOfThisWorld.java
@@ -42,7 +42,9 @@ public final class NotOfThisWorld extends CardImpl {
this.getSpellAbility().addTarget(new TargetStackObject(filter));
// Not of This World costs {7} less to cast if it targets a spell or ability that targets a creature you control with power 7 or greater.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(7, NotOfThisWorldCondition.instance)));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL,
+ new SpellCostReductionSourceEffect(7, NotOfThisWorldCondition.instance).setCanWorksOnStackOnly(true))
+ );
}
private NotOfThisWorld(final NotOfThisWorld card) {
@@ -65,7 +67,6 @@ enum NotOfThisWorldCondition implements Condition {
filter.add(TargetController.YOU.getControllerPredicate());
}
-
@Override
public boolean apply(Game game, Ability source) {
StackObject sourceSpell = game.getStack().getStackObject(source.getSourceId());
diff --git a/Mage.Sets/src/mage/cards/n/NoxiousDragon.java b/Mage.Sets/src/mage/cards/n/NoxiousDragon.java
index 0d029e3ad18..eafd0ece77d 100644
--- a/Mage.Sets/src/mage/cards/n/NoxiousDragon.java
+++ b/Mage.Sets/src/mage/cards/n/NoxiousDragon.java
@@ -4,7 +4,7 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -38,7 +38,7 @@ public final class NoxiousDragon extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Noxious Dragon dies, you may destroy target creature with converted mana cost 3 or less.
- Ability ability = new DiesTriggeredAbility(new DestroyTargetEffect(), true);
+ Ability ability = new DiesSourceTriggeredAbility(new DestroyTargetEffect(), true);
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/n/NoxiousGhoul.java b/Mage.Sets/src/mage/cards/n/NoxiousGhoul.java
index c8bf3c0ffe1..1409bedb6f7 100644
--- a/Mage.Sets/src/mage/cards/n/NoxiousGhoul.java
+++ b/Mage.Sets/src/mage/cards/n/NoxiousGhoul.java
@@ -1,8 +1,7 @@
-
package mage.cards.n;
import mage.MageInt;
-import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -11,11 +10,7 @@ import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
-import mage.filter.predicate.ObjectSourcePlayer;
-import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.filter.predicate.Predicates;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
import java.util.UUID;
@@ -24,13 +19,11 @@ import java.util.UUID;
*/
public final class NoxiousGhoul extends CardImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
- private static final FilterPermanent filter2 = new FilterPermanent();
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("all non-Zombie creatures");
+ private static final FilterPermanent filter2 = new FilterPermanent(SubType.ZOMBIE, "Zombie");
static {
- filter.add(CardType.CREATURE.getPredicate());
filter.add(Predicates.not(SubType.ZOMBIE.getPredicate()));
- filter2.add(NoxiousGhoulPredicate.instance);
}
public NoxiousGhoul(UUID ownerId, CardSetInfo setInfo) {
@@ -41,14 +34,12 @@ public final class NoxiousGhoul extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Noxious Ghoul or another Zombie enters the battlefield, all non-Zombie creatures get -1/-1 until end of turn.
- this.addAbility(new EntersBattlefieldAllTriggeredAbility(
- new BoostAllEffect(-1, -1, Duration.EndOfTurn, filter, false),
- filter2, "Whenever {this} or another Zombie enters the battlefield, " +
- "all non-Zombie creatures get -1/-1 until end of turn."
- ));
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(new BoostAllEffect(
+ -1, -1, Duration.EndOfTurn, filter, false
+ ), filter2, false, true));
}
- public NoxiousGhoul(final NoxiousGhoul card) {
+ private NoxiousGhoul(final NoxiousGhoul card) {
super(card);
}
@@ -57,13 +48,3 @@ public final class NoxiousGhoul extends CardImpl {
return new NoxiousGhoul(this);
}
}
-
-enum NoxiousGhoulPredicate implements ObjectSourcePlayerPredicate> {
- instance;
-
- @Override
- public boolean apply(ObjectSourcePlayer input, Game game) {
- return input.getObject().hasSubtype(SubType.ZOMBIE, game)
- || input.getObject().getId().equals(input.getSourceId());
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/n/NoxiousToad.java b/Mage.Sets/src/mage/cards/n/NoxiousToad.java
index c05adfe612e..cb9c93f5797 100644
--- a/Mage.Sets/src/mage/cards/n/NoxiousToad.java
+++ b/Mage.Sets/src/mage/cards/n/NoxiousToad.java
@@ -3,7 +3,7 @@ package mage.cards.n;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.discard.DiscardEachPlayerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class NoxiousToad extends CardImpl {
this.toughness = new MageInt(1);
// When Noxious Toad dies, each opponent discards a card.
- this.addAbility(new DiesTriggeredAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT), false));
}
public NoxiousToad(final NoxiousToad card) {
diff --git a/Mage.Sets/src/mage/cards/n/NoxiousVapors.java b/Mage.Sets/src/mage/cards/n/NoxiousVapors.java
index 1e67b13521e..1f5fdc483e0 100644
--- a/Mage.Sets/src/mage/cards/n/NoxiousVapors.java
+++ b/Mage.Sets/src/mage/cards/n/NoxiousVapors.java
@@ -1,26 +1,28 @@
-
package mage.cards.n;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.filter.common.FilterNonlandCard;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import mage.MageItem;
/**
- *
* @author L_J
*/
public final class NoxiousVapors extends CardImpl {
@@ -30,10 +32,9 @@ public final class NoxiousVapors extends CardImpl {
// Each player reveals their hand, chooses one card of each color from it, then discards all other nonland cards.
this.getSpellAbility().addEffect(new NoxiousVaporsEffect());
-
}
- public NoxiousVapors(final NoxiousVapors card) {
+ private NoxiousVapors(final NoxiousVapors card) {
super(card);
}
@@ -47,12 +48,12 @@ class NoxiousVaporsEffect extends OneShotEffect {
private static final FilterNonlandCard filter = new FilterNonlandCard();
- public NoxiousVaporsEffect() {
+ NoxiousVaporsEffect() {
super(Outcome.Benefit);
this.staticText = "Each player reveals their hand, chooses one card of each color from it, then discards all other nonland cards";
}
- public NoxiousVaporsEffect(final NoxiousVaporsEffect effect) {
+ private NoxiousVaporsEffect(final NoxiousVaporsEffect effect) {
super(effect);
}
@@ -64,37 +65,35 @@ class NoxiousVaporsEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- player.revealCards(player.getName() + "'s hand", player.getHand(), game);
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Set chosenCards = new HashSet<>();
- chooseCardForColor(ObjectColor.WHITE, chosenCards, player, game, source);
- chooseCardForColor(ObjectColor.BLUE, chosenCards, player, game, source);
- chooseCardForColor(ObjectColor.BLACK, chosenCards, player, game, source);
- chooseCardForColor(ObjectColor.RED, chosenCards, player, game, source);
- chooseCardForColor(ObjectColor.GREEN, chosenCards, player, game, source);
-
- Set cards = player.getHand().getCards(game);
- for (Card card : cards) {
- if (card != null && !chosenCards.contains(card) && filter.match(card, game)) {
- player.discard(card, source, game);
- }
- }
- }
- }
- return true;
+ if (controller == null) {
+ return false;
}
- return false;
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player != null) {
+ player.revealCards(player.getName() + "'s hand", player.getHand(), game);
+ }
+ }
+
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ continue;
+ }
+ Set chosenCards = new HashSet<>();
+ chooseCardForColor(ObjectColor.WHITE, chosenCards, player, game, source);
+ chooseCardForColor(ObjectColor.BLUE, chosenCards, player, game, source);
+ chooseCardForColor(ObjectColor.BLACK, chosenCards, player, game, source);
+ chooseCardForColor(ObjectColor.RED, chosenCards, player, game, source);
+ chooseCardForColor(ObjectColor.GREEN, chosenCards, player, game, source);
+ chosenCards.addAll(player.getHand().getCards(StaticFilters.FILTER_CARD_LAND, game));
+ Cards cards = player.getHand().copy();
+ cards.removeIf(chosenCards.stream().map(MageItem::getId).collect(Collectors.toSet())::contains);
+ player.discard(cards, source, game);
+ }
+ return true;
}
-
+
private void chooseCardForColor(ObjectColor color, Set chosenCards, Player player, Game game, Ability source) {
FilterCard filter = new FilterCard();
filter.add(new ColorPredicate(color));
diff --git a/Mage.Sets/src/mage/cards/n/NullChamber.java b/Mage.Sets/src/mage/cards/n/NullChamber.java
index c3562465a34..99b0bf51ec3 100644
--- a/Mage.Sets/src/mage/cards/n/NullChamber.java
+++ b/Mage.Sets/src/mage/cards/n/NullChamber.java
@@ -1,22 +1,17 @@
package mage.cards.n;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
-import mage.constants.SuperType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
@@ -25,8 +20,9 @@ import mage.players.Player;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
*/
public final class NullChamber extends CardImpl {
@@ -141,7 +137,7 @@ class NullChamberReplacementEffect extends ContinuousRuleModifyingEffectImpl {
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
- return "You can't cast a spell with that name (" + mageObject.getLogName() + " in play).";
+ return "You can't cast a spell with that name (" + mageObject.getName() + " in play).";
}
return null;
}
diff --git a/Mage.Sets/src/mage/cards/o/OakhameAdversary.java b/Mage.Sets/src/mage/cards/o/OakhameAdversary.java
index bfc25c3e5c0..6cd85144ab7 100644
--- a/Mage.Sets/src/mage/cards/o/OakhameAdversary.java
+++ b/Mage.Sets/src/mage/cards/o/OakhameAdversary.java
@@ -5,19 +5,21 @@ import mage.ObjectColor;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.OpponentControlsPermanentCondition;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.abilities.keyword.DeathtouchAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.ComparisonType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
+
import java.util.UUID;
-import mage.abilities.condition.common.OpponentControlsPermanentCondition;
-import mage.constants.ComparisonType;
/**
* @author TheElk801
@@ -43,8 +45,8 @@ public final class OakhameAdversary extends CardImpl {
// This spell costs {2} less to cast if your opponent controls a green permanent.
this.addAbility(new SimpleStaticAbility(
- Zone.STACK, new SpellCostReductionSourceEffect(2, condition)
- ).setRuleAtTheTop(true));
+ Zone.ALL, new SpellCostReductionSourceEffect(2, condition)
+ ).setRuleAtTheTop(true).addHint(new ConditionHint(condition, "Your opponent controls a green permanent")));
// Deathtouch
this.addAbility(DeathtouchAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/o/OathOfLimDul.java b/Mage.Sets/src/mage/cards/o/OathOfLimDul.java
index f650fe48156..d8e6aee4661 100644
--- a/Mage.Sets/src/mage/cards/o/OathOfLimDul.java
+++ b/Mage.Sets/src/mage/cards/o/OathOfLimDul.java
@@ -14,6 +14,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
+import mage.filter.FilterCard;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
@@ -88,7 +89,7 @@ class OathOfLimDulTriggeredAbility extends TriggeredAbilityImpl {
class OathOfLimDulEffect extends OneShotEffect {
- private static final FilterControlledPermanent filter = new FilterControlledPermanent("controlled permanent other than Oath of Lim-Dul");
+ private static final FilterControlledPermanent filter = new FilterControlledPermanent("controlled permanent other than Oath of Lim-Dul to sacrifice");
static {
filter.add(AnotherPredicate.instance);
@@ -104,31 +105,34 @@ class OathOfLimDulEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
+ Boolean sacrificeDone = false;
+ int numberSacrificed = 0;
+ int numberToDiscard = 0;
+ int numberOfControlledPermanents = 0;
Player controller = game.getPlayer(source.getControllerId());
- int amount = (int) game.getState().getValue(source.getSourceId().toString() + "oathOfLimDul");
- if (amount > 0
+ int amountDamage = (int) game.getState().getValue(source.getSourceId().toString() + "oathOfLimDul");
+ if (amountDamage > 0
&& controller != null) {
- for (int i = 0; i < amount; i++) {
- TargetControlledPermanent target = new TargetControlledPermanent(filter);
- target.setNotTarget(true);
- if (target.canChoose(controller.getId(), game)
- && controller.choose(Outcome.Sacrifice, target, source.getSourceId(), game)) {
- Cost cost = new DiscardTargetCost(new TargetCardInHand());
- if (cost.canPay(source, source.getSourceId(), controller.getId(), game)
- && controller.chooseUse(Outcome.Benefit,
- "Do you wish to discard a card rather than sacrifice the target permanent?", source, game)) {
- cost.pay(source, game, source.getSourceId(), controller.getId(), true);
- } else {
- Permanent targetPermanent = game.getPermanent(target.getFirstTarget());
- if (targetPermanent != null) {
- targetPermanent.sacrifice(source.getSourceId(), game);
- }
+ TargetControlledPermanent target = new TargetControlledPermanent(0, numberOfControlledPermanents, filter, true);
+ target.setNotTarget(true);
+ if (controller.choose(Outcome.Detriment, target, source.getSourceId(), game)) {
+ for (UUID targetPermanentId : target.getTargets()) {
+ Permanent permanent = game.getPermanent(targetPermanentId);
+ if (permanent != null
+ && permanent.sacrifice(source.getSourceId(), game)) {
+ numberSacrificed += 1;
+ sacrificeDone = true;
}
}
}
- return true;
+ numberToDiscard = amountDamage - numberSacrificed;
+ Cost cost = new DiscardTargetCost(new TargetCardInHand(numberToDiscard, new FilterCard("card(s) in your hand to discard")));
+ if (numberToDiscard > 0
+ && cost.canPay(source, source.getSourceId(), controller.getId(), game)) {
+ return cost.pay(source, game, source.getSourceId(), controller.getId(), true); // discard cost paid simultaneously
+ }
}
- return false;
+ return sacrificeDone;
}
@Override
diff --git a/Mage.Sets/src/mage/cards/o/OathOfTheAncientWood.java b/Mage.Sets/src/mage/cards/o/OathOfTheAncientWood.java
index a2f1acfa262..87235786993 100644
--- a/Mage.Sets/src/mage/cards/o/OathOfTheAncientWood.java
+++ b/Mage.Sets/src/mage/cards/o/OathOfTheAncientWood.java
@@ -1,44 +1,35 @@
-
package mage.cards.o;
-import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
-import mage.abilities.effects.Effect;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SetTargetPointer;
-import mage.constants.TargetController;
-import mage.constants.Zone;
import mage.counters.CounterType;
-import mage.filter.common.FilterEnchantmentPermanent;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class OathOfTheAncientWood extends CardImpl {
- private static final FilterEnchantmentPermanent filter = new FilterEnchantmentPermanent("Oath of the Ancient Wood or another enchantment");
-
- static {
- filter.add(TargetController.YOU.getControllerPredicate());
- }
-
public OathOfTheAncientWood(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
// Whenever Oath of the Ancient Wood or another enchantment enters the battlefield under your control, you may put a +1/+1 counter on target creature.
- Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance());
- Ability ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, effect, filter, true, SetTargetPointer.NONE, null, true);
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new AddCountersTargetEffect(CounterType.P1P1.createInstance()),
+ StaticFilters.FILTER_ENCHANTMENT_PERMANENT, true, true
+ );
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
- public OathOfTheAncientWood(final OathOfTheAncientWood card) {
+ private OathOfTheAncientWood(final OathOfTheAncientWood card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/o/Oblation.java b/Mage.Sets/src/mage/cards/o/Oblation.java
index 5e84b814d1b..85af435e691 100644
--- a/Mage.Sets/src/mage/cards/o/Oblation.java
+++ b/Mage.Sets/src/mage/cards/o/Oblation.java
@@ -63,7 +63,7 @@ class OblationEffect extends OneShotEffect {
player.moveCardToLibraryWithInfo(permanent, source.getSourceId(), game, Zone.BATTLEFIELD, true, true);
player.shuffleLibrary(source, game);
- game.applyEffects(); // so effects from creatures that were on the battlefield won't trigger from draw
+ game.getState().processAction(game); // so effects from creatures that were on the battlefield won't trigger from draw
player.drawCards(2, source.getSourceId(), game);
return true;
diff --git a/Mage.Sets/src/mage/cards/o/Obliterate.java b/Mage.Sets/src/mage/cards/o/Obliterate.java
index 8cfd66e0b3a..03b8ddba0da 100644
--- a/Mage.Sets/src/mage/cards/o/Obliterate.java
+++ b/Mage.Sets/src/mage/cards/o/Obliterate.java
@@ -2,7 +2,7 @@
package mage.cards.o;
import java.util.UUID;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -30,7 +30,7 @@ public final class Obliterate extends CardImpl {
// Obliterate can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Destroy all artifacts, creatures, and lands. They can't be regenerated.
this.getSpellAbility().addEffect(new DestroyAllEffect(filter));
}
diff --git a/Mage.Sets/src/mage/cards/o/ObsessiveStitcher.java b/Mage.Sets/src/mage/cards/o/ObsessiveStitcher.java
new file mode 100644
index 00000000000..560a10f0463
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/o/ObsessiveStitcher.java
@@ -0,0 +1,54 @@
+package mage.cards.o;
+
+import mage.MageInt;
+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.ManaCostsImpl;
+import mage.abilities.effects.common.DrawDiscardControllerEffect;
+import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.filter.StaticFilters;
+import mage.target.common.TargetCardInYourGraveyard;
+
+import java.util.UUID;
+
+/**
+ * @author mikalinn777
+ */
+public final class ObsessiveStitcher extends CardImpl {
+
+ public ObsessiveStitcher(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}");
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WIZARD);
+
+ this.power = new MageInt(0);
+ this.toughness = new MageInt(3);
+
+ // {T}: Draw a card, then discard a card.
+ this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawDiscardControllerEffect(), new TapSourceCost()));
+
+ // {2}{U}{B}, {T}, Sacrifice Obsessive Stitcher: Return target creature card from your graveyard to the battlefield.
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(false, false), new ManaCostsImpl("{2}{U}{B}"));
+ ability.addCost(new TapSourceCost());
+ ability.addCost(new SacrificeSourceCost());
+ ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD));
+ this.addAbility(ability);
+
+ }
+
+ public ObsessiveStitcher(final ObsessiveStitcher card) {
+ super(card);
+ }
+
+ @Override
+ public ObsessiveStitcher copy() {
+ return new ObsessiveStitcher(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/o/ObzedatGhostCouncil.java b/Mage.Sets/src/mage/cards/o/ObzedatGhostCouncil.java
index 86004150099..f1700a55cf1 100644
--- a/Mage.Sets/src/mage/cards/o/ObzedatGhostCouncil.java
+++ b/Mage.Sets/src/mage/cards/o/ObzedatGhostCouncil.java
@@ -42,6 +42,7 @@ public final class ObzedatGhostCouncil extends CardImpl {
ability.addEffect(new GainLifeEffect(2).concatBy("and"));
ability.addTarget(new TargetOpponent());
this.addAbility(ability);
+
//At the beginning of your end step you may exile Obzedat. If you do, return it to the battlefield under its owner's
//control at the beginning of your next upkeep. It gains haste.
Ability ability2 = new BeginningOfYourEndStepTriggeredAbility(new ObzedatGhostCouncilExileSourceEffect(), true);
diff --git a/Mage.Sets/src/mage/cards/o/Oculus.java b/Mage.Sets/src/mage/cards/o/Oculus.java
index 77e73712e1e..ee4129d7b93 100644
--- a/Mage.Sets/src/mage/cards/o/Oculus.java
+++ b/Mage.Sets/src/mage/cards/o/Oculus.java
@@ -4,7 +4,7 @@ package mage.cards.o;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class Oculus extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
}
public Oculus (final Oculus card) {
diff --git a/Mage.Sets/src/mage/cards/o/OfOneMind.java b/Mage.Sets/src/mage/cards/o/OfOneMind.java
index 58df54b9a31..a38184af0dd 100644
--- a/Mage.Sets/src/mage/cards/o/OfOneMind.java
+++ b/Mage.Sets/src/mage/cards/o/OfOneMind.java
@@ -6,6 +6,7 @@ import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -39,9 +40,10 @@ public final class OfOneMind extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}");
// This spell costs {2} less to cast if you control a Human creature and a non-Human creature.
- this.addAbility(new SimpleStaticAbility(
- Zone.STACK, new SpellCostReductionSourceEffect(2, condition)
- ).setRuleAtTheTop(true));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(2, condition))
+ .setRuleAtTheTop(true)
+ .addHint(new ConditionHint(condition, "You control a Human creature and a non-Human creature"))
+ );
// Draw two cards.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2));
diff --git a/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java b/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java
index 0c9b7699604..bd8eafb3da7 100644
--- a/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java
+++ b/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java
@@ -1,7 +1,6 @@
package mage.cards.o;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -24,6 +23,8 @@ import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
*
* @author nantuko
@@ -55,7 +56,11 @@ public final class OliviaVoldaren extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// {1}{R}: Olivia Voldaren deals 1 damage to another target creature. That creature becomes a Vampire in addition to its other types. Put a +1/+1 counter on Olivia Voldaren.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{1}{R}"));
+ Ability ability = new SimpleActivatedAbility(
+ Zone.BATTLEFIELD,
+ new DamageTargetEffect(1).setText("{this} deals 1 damage to another target creature"),
+ new ManaCostsImpl("{1}{R}")
+ );
ability.addTarget(new TargetCreaturePermanent(filter));
Effect effect = new AddCardSubTypeTargetEffect(SubType.VAMPIRE, Duration.WhileOnBattlefield);
effect.setText("That creature becomes a Vampire in addition to its other types");
diff --git a/Mage.Sets/src/mage/cards/o/OmenOfTheSea.java b/Mage.Sets/src/mage/cards/o/OmenOfTheSea.java
index 2cc325328b9..6b9ddb1d343 100644
--- a/Mage.Sets/src/mage/cards/o/OmenOfTheSea.java
+++ b/Mage.Sets/src/mage/cards/o/OmenOfTheSea.java
@@ -26,8 +26,8 @@ public final class OmenOfTheSea extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// When Omen of the Sea enters the battlefield, scry 2, then draw a card.
- Ability ability = new EntersBattlefieldTriggeredAbility(new ScryEffect(2).setText("scry 2,"));
- ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy("then"));
+ Ability ability = new EntersBattlefieldTriggeredAbility(new ScryEffect(2, false));
+ ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy(", then"));
this.addAbility(ability);
// {2}{U}, Sacrifice Omen of the Sea: Scry 2.
diff --git a/Mage.Sets/src/mage/cards/o/Onulet.java b/Mage.Sets/src/mage/cards/o/Onulet.java
index 3a58d56823b..ebf562bda7e 100644
--- a/Mage.Sets/src/mage/cards/o/Onulet.java
+++ b/Mage.Sets/src/mage/cards/o/Onulet.java
@@ -3,7 +3,7 @@ package mage.cards.o;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class Onulet extends CardImpl {
this.toughness = new MageInt(2);
// When Onulet dies, you gain 2 life.
- this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(2)));
}
public Onulet(final Onulet card) {
diff --git a/Mage.Sets/src/mage/cards/o/OppressiveRays.java b/Mage.Sets/src/mage/cards/o/OppressiveRays.java
index ceb1fd488ab..77df99c37bb 100644
--- a/Mage.Sets/src/mage/cards/o/OppressiveRays.java
+++ b/Mage.Sets/src/mage/cards/o/OppressiveRays.java
@@ -39,7 +39,7 @@ public final class OppressiveRays extends CardImpl {
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
- this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
+ this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/o/OraclesVault.java b/Mage.Sets/src/mage/cards/o/OraclesVault.java
index 57ed7bfd9d4..e69ae9ac6e1 100644
--- a/Mage.Sets/src/mage/cards/o/OraclesVault.java
+++ b/Mage.Sets/src/mage/cards/o/OraclesVault.java
@@ -1,4 +1,3 @@
-
package mage.cards.o;
import java.util.UUID;
@@ -11,8 +10,10 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.effects.AsThoughEffectImpl;
+import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
@@ -21,11 +22,13 @@ import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.players.Library;
import mage.players.Player;
+import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
@@ -84,13 +87,8 @@ class OraclesVaultEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
- Card card = controller.getLibrary().getFromTop(game);
- if (card != null) {
- controller.moveCardsToExile(card, source, game, true, source.getSourceId(),
- CardUtil.createObjectRealtedWindowTitle(source, game, ""));
- game.addEffect(new OraclesVaultPlayEffect(new MageObjectReference(card, game)), source);
- }
- return true;
+ return PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(game, source, controller.getLibrary().getFromTop(game),
+ TargetController.YOU, Duration.EndOfTurn, false);
}
return false;
}
@@ -114,95 +112,9 @@ class OraclesVaultFreeEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- MageObject sourceObject = source.getSourceObject(game);
- if (controller != null && sourceObject != null && controller.getLibrary().hasCards()) {
- Library library = controller.getLibrary();
- Card card = library.getFromTop(game);
- if (card != null) {
- controller.moveCardsToExile(card, source, game, true, source.getSourceId(),
- CardUtil.createObjectRealtedWindowTitle(source, game, " "));
- game.addEffect(new OraclesVaultPlayForFreeEffect(new MageObjectReference(card, game)), source);
- }
- return true;
- }
- return false;
- }
-}
-
-class OraclesVaultPlayEffect extends AsThoughEffectImpl {
-
- private final MageObjectReference objectReference;
-
- public OraclesVaultPlayEffect(MageObjectReference objectReference) {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
- this.objectReference = objectReference;
- staticText = "Until end of turn, you may play that card";
- }
-
- public OraclesVaultPlayEffect(final OraclesVaultPlayEffect effect) {
- super(effect);
- this.objectReference = effect.objectReference;
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public OraclesVaultPlayEffect copy() {
- return new OraclesVaultPlayEffect(this);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- if (objectReference.refersTo(objectId, game) && affectedControllerId.equals(source.getControllerId())) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- return true;
- } else {
- discard();
- }
- }
- return false;
- }
-}
-
-class OraclesVaultPlayForFreeEffect extends AsThoughEffectImpl {
-
- private final MageObjectReference objectReference;
-
- public OraclesVaultPlayForFreeEffect(MageObjectReference objectReference) {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
- this.objectReference = objectReference;
- staticText = "Until end of turn, you may play that card without paying its mana cost";
- }
-
- public OraclesVaultPlayForFreeEffect(final OraclesVaultPlayForFreeEffect effect) {
- super(effect);
- this.objectReference = effect.objectReference;
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public OraclesVaultPlayForFreeEffect copy() {
- return new OraclesVaultPlayForFreeEffect(this);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- if (objectReference.refersTo(objectId, game) && affectedControllerId.equals(source.getControllerId())) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- controller.setCastSourceIdWithAlternateMana(objectId, null, null);
- return true;
- } else {
- discard();
- }
+ if (controller != null) {
+ return PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(game, source, controller.getLibrary().getFromTop(game),
+ TargetController.YOU, Duration.EndOfTurn, true);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/o/OrcishHellraiser.java b/Mage.Sets/src/mage/cards/o/OrcishHellraiser.java
index 701bb8d750b..a227b3ab608 100644
--- a/Mage.Sets/src/mage/cards/o/OrcishHellraiser.java
+++ b/Mage.Sets/src/mage/cards/o/OrcishHellraiser.java
@@ -2,7 +2,7 @@ package mage.cards.o;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.EchoAbility;
import mage.cards.CardImpl;
@@ -30,7 +30,7 @@ public final class OrcishHellraiser extends CardImpl {
this.addAbility(new EchoAbility("{R}"));
// When Orcish Hellraiser dies, it deals 2 damage to target player or planeswalker.
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(2, "it"));
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(2, "it"));
ability.addTarget(new TargetPlayerOrPlaneswalker());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/o/OrcishSquatters.java b/Mage.Sets/src/mage/cards/o/OrcishSquatters.java
index fd20a8044bc..cfcbddab651 100644
--- a/Mage.Sets/src/mage/cards/o/OrcishSquatters.java
+++ b/Mage.Sets/src/mage/cards/o/OrcishSquatters.java
@@ -1,4 +1,3 @@
-
package mage.cards.o;
import java.util.UUID;
@@ -9,14 +8,15 @@ import mage.abilities.condition.common.SourceOnBattlefieldControlUnchangedCondit
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
-import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
+import mage.constants.SubType;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.permanent.DefendingPlayerControlsPredicate;
import mage.target.TargetPermanent;
+import mage.watchers.common.LostControlWatcher;
/**
*
@@ -45,6 +45,7 @@ public final class OrcishSquatters extends CardImpl {
), true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
ability.addTarget(new TargetPermanent(filter));
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/o/OreScaleGuardian.java b/Mage.Sets/src/mage/cards/o/OreScaleGuardian.java
index cb8c54a0f6a..95d09d2f8e8 100644
--- a/Mage.Sets/src/mage/cards/o/OreScaleGuardian.java
+++ b/Mage.Sets/src/mage/cards/o/OreScaleGuardian.java
@@ -3,7 +3,10 @@ package mage.cards.o;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
@@ -28,10 +31,10 @@ public final class OreScaleGuardian extends CardImpl {
this.toughness = new MageInt(4);
// This spell costs {1} less to cast for each land card in your graveyard.
- Ability ability = new SimpleStaticAbility(
- Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(StaticFilters.FILTER_CARD_LAND)
- );
+ DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_LAND);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
ability.setRuleAtTheTop(true);
+ ability.addHint(new ValueHint("Land card in your graveyard", xValue));
this.addAbility(ability);
// Flying
diff --git a/Mage.Sets/src/mage/cards/o/OriginSpellbomb.java b/Mage.Sets/src/mage/cards/o/OriginSpellbomb.java
index 6b4dc0f0f8b..eec623e9874 100644
--- a/Mage.Sets/src/mage/cards/o/OriginSpellbomb.java
+++ b/Mage.Sets/src/mage/cards/o/OriginSpellbomb.java
@@ -4,7 +4,7 @@ package mage.cards.o;
import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
@@ -31,7 +31,7 @@ public final class OriginSpellbomb extends CardImpl {
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
- this.addAbility(new DiesTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{W}")), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{W}")), false));
}
public OriginSpellbomb (final OriginSpellbomb card) {
diff --git a/Mage.Sets/src/mage/cards/o/OrimsPrayer.java b/Mage.Sets/src/mage/cards/o/OrimsPrayer.java
index 53eb06d5f04..68fd83e3200 100644
--- a/Mage.Sets/src/mage/cards/o/OrimsPrayer.java
+++ b/Mage.Sets/src/mage/cards/o/OrimsPrayer.java
@@ -38,8 +38,6 @@ public final class OrimsPrayer extends CardImpl {
class OrimsPrayerTriggeredAbility extends TriggeredAbilityImpl {
- int numberAttackingController = 0;
-
public OrimsPrayerTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
}
@@ -65,6 +63,7 @@ class OrimsPrayerTriggeredAbility extends TriggeredAbilityImpl {
if (controller == null) {
return false;
}
+ int numberAttackingController = 0;
for (UUID attackersId : game.getCombat().getAttackers()) {
Permanent attackingCreature = game.getPermanent(attackersId);
if (attackingCreature != null
diff --git a/Mage.Sets/src/mage/cards/o/OrmosArchiveKeeper.java b/Mage.Sets/src/mage/cards/o/OrmosArchiveKeeper.java
new file mode 100644
index 00000000000..e1a74d19eab
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/o/OrmosArchiveKeeper.java
@@ -0,0 +1,144 @@
+package mage.cards.o;
+
+import mage.MageInt;
+import mage.MageObject;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.common.DiscardTargetCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.counters.CounterType;
+import mage.filter.FilterCard;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.common.TargetCardInHand;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class OrmosArchiveKeeper extends CardImpl {
+
+ public OrmosArchiveKeeper(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.SPHINX);
+ this.power = new MageInt(5);
+ this.toughness = new MageInt(5);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // If you would draw a card while your library has no cards in it, instead put five +1/+1 counters on Ormos, Archive Keeper.
+ this.addAbility(new SimpleStaticAbility(new OrmosArchiveKeeperEffect()));
+
+ // {1}{U}{U}, Discard three cards with different names: Draw five cards.
+ Ability ability = new SimpleActivatedAbility(
+ new DrawCardSourceControllerEffect(5), new ManaCostsImpl("{1}{U}{U}")
+ );
+ ability.addCost(new DiscardTargetCost(new OrmosArchiveKeeperTarget()));
+ this.addAbility(ability);
+ }
+
+ private OrmosArchiveKeeper(final OrmosArchiveKeeper card) {
+ super(card);
+ }
+
+ @Override
+ public OrmosArchiveKeeper copy() {
+ return new OrmosArchiveKeeper(this);
+ }
+}
+
+class OrmosArchiveKeeperEffect extends ReplacementEffectImpl {
+
+ OrmosArchiveKeeperEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.Benefit);
+ staticText = "If you would draw a card while your library has no cards in it, "
+ + "instead put five +1/+1 counters on {this}";
+ }
+
+ private OrmosArchiveKeeperEffect(final OrmosArchiveKeeperEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public OrmosArchiveKeeperEffect copy() {
+ return new OrmosArchiveKeeperEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ Permanent permanent = game.getPermanent(source.getSourceId());
+ if (permanent != null) {
+ permanent.addCounters(CounterType.P1P1.createInstance(5), source, game);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.DRAW_CARD;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (event.getPlayerId().equals(source.getControllerId())) {
+ Player player = game.getPlayer(event.getPlayerId());
+ if (player != null && !player.hasLost() && !player.getLibrary().hasCards()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+class OrmosArchiveKeeperTarget extends TargetCardInHand {
+
+ private static final FilterCard filter = new FilterCard("three cards with different names");
+
+ OrmosArchiveKeeperTarget() {
+ super(3, filter);
+ }
+
+ private OrmosArchiveKeeperTarget(final OrmosArchiveKeeperTarget target) {
+ super(target);
+ }
+
+ @Override
+ public OrmosArchiveKeeperTarget copy() {
+ return new OrmosArchiveKeeperTarget(this);
+ }
+
+ @Override
+ public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
+ if (!super.canTarget(controllerId, id, source, game)) {
+ return false;
+ }
+ Card card = game.getCard(id);
+ if (card == null) {
+ return false;
+ }
+ return this.getTargets()
+ .stream()
+ .map(game::getCard)
+ .map(MageObject::getName)
+ .noneMatch(card.getName()::equals);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/o/OrneryDilophosaur.java b/Mage.Sets/src/mage/cards/o/OrneryDilophosaur.java
new file mode 100644
index 00000000000..fce5c2b72cf
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/o/OrneryDilophosaur.java
@@ -0,0 +1,50 @@
+package mage.cards.o;
+
+import mage.MageInt;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.condition.common.FerociousCondition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.hint.common.FerociousHint;
+import mage.abilities.keyword.DeathtouchAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class OrneryDilophosaur extends CardImpl {
+
+ public OrneryDilophosaur(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
+
+ this.subtype.add(SubType.DINOSAUR);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Deathtouch
+ this.addAbility(DeathtouchAbility.getInstance());
+
+ // Whenever Ornery Dilophosaur attacks, if you control a creature with power 4 or greater, Ornery Dilophosaur gets +2/+2 until end of turn.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new AttacksTriggeredAbility(
+ new BoostSourceEffect(2, 2, Duration.EndOfTurn), false
+ ), FerociousCondition.instance, "Whenever {this} attacks, " +
+ "if you control a creature with power 4 or greater, {this} gets +2/+2 until end of turn."
+ ).addHint(FerociousHint.instance));
+ }
+
+ private OrneryDilophosaur(final OrneryDilophosaur card) {
+ super(card);
+ }
+
+ @Override
+ public OrneryDilophosaur copy() {
+ return new OrneryDilophosaur(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/o/OrneryGoblin.java b/Mage.Sets/src/mage/cards/o/OrneryGoblin.java
index 7e56c1249a8..3f523c0f66a 100644
--- a/Mage.Sets/src/mage/cards/o/OrneryGoblin.java
+++ b/Mage.Sets/src/mage/cards/o/OrneryGoblin.java
@@ -2,7 +2,7 @@ package mage.cards.o;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
@@ -24,7 +24,7 @@ public final class OrneryGoblin extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Ornery Goblin blocks or becomes blocked by a creature, Ornery Goblin deals 1 damage to that creature.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(
new DamageTargetEffect(1, true, "that creature"), false
));
}
diff --git a/Mage.Sets/src/mage/cards/o/OrzhovKeyrune.java b/Mage.Sets/src/mage/cards/o/OrzhovKeyrune.java
index debb0f28d14..66d63b82943 100644
--- a/Mage.Sets/src/mage/cards/o/OrzhovKeyrune.java
+++ b/Mage.Sets/src/mage/cards/o/OrzhovKeyrune.java
@@ -1,7 +1,5 @@
-
package mage.cards.o;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -12,22 +10,22 @@ import mage.abilities.mana.WhiteManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.permanent.token.TokenImpl;
-import mage.game.permanent.token.Token;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class OrzhovKeyrune extends CardImpl {
public OrzhovKeyrune(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
- // {{T}: Add {W} or {B}.
+ // {T}: Add {W} or {B}.
this.addAbility(new WhiteManaAbility());
this.addAbility(new BlackManaAbility());
@@ -56,6 +54,7 @@ public final class OrzhovKeyrune extends CardImpl {
toughness = new MageInt(4);
this.addAbility(LifelinkAbility.getInstance());
}
+
public OrzhovKeyruneToken(final OrzhovKeyruneToken token) {
super(token);
}
diff --git a/Mage.Sets/src/mage/cards/o/Outmuscle.java b/Mage.Sets/src/mage/cards/o/Outmuscle.java
index d64ecb8b254..c35df58cd9f 100644
--- a/Mage.Sets/src/mage/cards/o/Outmuscle.java
+++ b/Mage.Sets/src/mage/cards/o/Outmuscle.java
@@ -83,7 +83,7 @@ class OutmuscleEffect extends OneShotEffect {
if (creature == null) {
return true;
}
- game.applyEffects();
+ game.getState().processAction(game);
return creature.fight(permanent, source, game);
}
}
diff --git a/Mage.Sets/src/mage/cards/o/OverrideCard.java b/Mage.Sets/src/mage/cards/o/OverrideCard.java
index d69ba56a7d6..59ad499c0cb 100644
--- a/Mage.Sets/src/mage/cards/o/OverrideCard.java
+++ b/Mage.Sets/src/mage/cards/o/OverrideCard.java
@@ -4,12 +4,12 @@ import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.costs.Cost;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.filter.common.FilterArtifactPermanent;
import mage.game.Game;
import mage.game.stack.StackObject;
import mage.players.Player;
@@ -64,7 +64,7 @@ class OverrideEffect extends OneShotEffect {
Player player = game.getPlayer(spell.getControllerId());
Player controller = game.getPlayer(source.getControllerId());
if (player != null && controller != null) {
- int amount = game.getBattlefield().countAll(new FilterArtifactPermanent(), source.getControllerId(), game);
+ int amount = ArtifactYouControlCount.instance.calculate(game, source, this);
if (amount > 0) {
Cost cost = ManaUtil.createManaCost(amount, false);
if (!cost.pay(source, game, spell.getControllerId(), spell.getControllerId(), false)) {
diff --git a/Mage.Sets/src/mage/cards/o/OverwhelmedApprentice.java b/Mage.Sets/src/mage/cards/o/OverwhelmedApprentice.java
index c62134e5663..32f9fe239f3 100644
--- a/Mage.Sets/src/mage/cards/o/OverwhelmedApprentice.java
+++ b/Mage.Sets/src/mage/cards/o/OverwhelmedApprentice.java
@@ -30,7 +30,7 @@ public final class OverwhelmedApprentice extends CardImpl {
Ability ability = new EntersBattlefieldTriggeredAbility(
new PutTopCardOfLibraryIntoGraveEachPlayerEffect(2, TargetController.OPPONENT)
);
- ability.addEffect(new ScryEffect(2).setText("Then you scry 2."));
+ ability.addEffect(new ScryEffect(2, false).setText("Then you scry 2."));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/p/PackLeader.java b/Mage.Sets/src/mage/cards/p/PackLeader.java
new file mode 100644
index 00000000000..86fac27413f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/PackLeader.java
@@ -0,0 +1,55 @@
+package mage.cards.p;
+
+import mage.MageInt;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.PreventAllDamageToAllEffect;
+import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.filter.common.FilterCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class PackLeader extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.DOG, "Dogs");
+
+ static {
+ filter.add(TargetController.YOU.getControllerPredicate());
+ }
+
+ public PackLeader(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
+
+ this.subtype.add(SubType.DOG);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Other Dogs you control get +1/+1.
+ this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(
+ 1, 1, Duration.WhileOnBattlefield, filter, true
+ )));
+
+ // Whenever Pack Leader attacks, prevent all combat damage that would be dealt this turn to Dogs you control.
+ this.addAbility(new AttacksTriggeredAbility(new PreventAllDamageToAllEffect(
+ Duration.EndOfTurn, filter, true
+ ).setText("prevent all combat damage that would be dealt this turn to Dogs you control"), false));
+ }
+
+ private PackLeader(final PackLeader card) {
+ super(card);
+ }
+
+ @Override
+ public PackLeader copy() {
+ return new PackLeader(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/PackMastiff.java b/Mage.Sets/src/mage/cards/p/PackMastiff.java
index 92a049678b4..92413d6e2c3 100644
--- a/Mage.Sets/src/mage/cards/p/PackMastiff.java
+++ b/Mage.Sets/src/mage/cards/p/PackMastiff.java
@@ -28,7 +28,7 @@ public final class PackMastiff extends CardImpl {
public PackMastiff(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java b/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java
index c0b8a7ce639..f7abe82234c 100644
--- a/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java
+++ b/Mage.Sets/src/mage/cards/p/PakoArcaneRetriever.java
@@ -29,7 +29,7 @@ public final class PakoArcaneRetriever extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.ELEMENTAL);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/p/PalaceFamiliar.java b/Mage.Sets/src/mage/cards/p/PalaceFamiliar.java
index 50afbd795d3..7bf7245f86b 100644
--- a/Mage.Sets/src/mage/cards/p/PalaceFamiliar.java
+++ b/Mage.Sets/src/mage/cards/p/PalaceFamiliar.java
@@ -3,7 +3,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class PalaceFamiliar extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Palace Familiar dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public PalaceFamiliar(final PalaceFamiliar card) {
diff --git a/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java b/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java
index 3b21dd98e74..e0c8ca2b253 100644
--- a/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java
+++ b/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java
@@ -4,7 +4,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.condition.common.LiveLostLastTurnCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.dynamicvalue.common.SourcePermanentToughnessValue;
@@ -38,7 +38,7 @@ public final class PaladinOfAtonement extends CardImpl {
"At the beginning of each upkeep, if you lost life last turn, put a +1/+1 counter on {this}"));
// When Paladin of Atonement dies, you gain life equal to it's toughness.
- this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(SourcePermanentToughnessValue.getInstance(),
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(SourcePermanentToughnessValue.getInstance(),
"you gain life equal to it's toughness")));
}
diff --git a/Mage.Sets/src/mage/cards/p/PalisadeGiant.java b/Mage.Sets/src/mage/cards/p/PalisadeGiant.java
index 0ceed13bfb4..f1c808fbe9b 100644
--- a/Mage.Sets/src/mage/cards/p/PalisadeGiant.java
+++ b/Mage.Sets/src/mage/cards/p/PalisadeGiant.java
@@ -65,7 +65,7 @@ class PalisadeGiantReplacementEffect extends ReplacementEffectImpl {
PalisadeGiantReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.RedirectDamage);
- staticText = "All damage that would be dealt to you or another permanent you control is dealt to Palisade Giant instead";
+ staticText = "All damage that would be dealt to you or another permanent you control is dealt to {this} instead";
}
PalisadeGiantReplacementEffect(final PalisadeGiantReplacementEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/p/PatientRebuilding.java b/Mage.Sets/src/mage/cards/p/PatientRebuilding.java
index 130c1182c36..9f4b2ee7bc4 100644
--- a/Mage.Sets/src/mage/cards/p/PatientRebuilding.java
+++ b/Mage.Sets/src/mage/cards/p/PatientRebuilding.java
@@ -1,7 +1,5 @@
package mage.cards.p;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
@@ -11,13 +9,14 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class PatientRebuilding extends CardImpl {
@@ -49,7 +48,7 @@ class PatientRebuildingEffect extends OneShotEffect {
public PatientRebuildingEffect() {
super(Outcome.DrawCard);
- this.staticText = "target opponent puts the top three cards of their library into their graveyard, "
+ this.staticText = "target opponent mills three cards, "
+ "then you draw a card for each land card put into that graveyard this way";
}
@@ -70,7 +69,7 @@ class PatientRebuildingEffect extends OneShotEffect {
return false;
}
int numberOfLandCards = 0;
- Set movedCards = player.moveCardsToGraveyardWithInfo(player.getLibrary().getTopCards(game, 3), source, game, Zone.LIBRARY);
+ Set movedCards = player.millCards(3, source, game).getCards(game);
for (Card card : movedCards) {
if (card.isLand()) {
numberOfLandCards++;
diff --git a/Mage.Sets/src/mage/cards/p/PatrolHound.java b/Mage.Sets/src/mage/cards/p/PatrolHound.java
index aa3c45f9eec..266ba9535a8 100644
--- a/Mage.Sets/src/mage/cards/p/PatrolHound.java
+++ b/Mage.Sets/src/mage/cards/p/PatrolHound.java
@@ -22,7 +22,7 @@ public final class PatrolHound extends CardImpl {
public PatrolHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/p/PawnOfUlamog.java b/Mage.Sets/src/mage/cards/p/PawnOfUlamog.java
index d9aa4601a38..222b1b8f453 100644
--- a/Mage.Sets/src/mage/cards/p/PawnOfUlamog.java
+++ b/Mage.Sets/src/mage/cards/p/PawnOfUlamog.java
@@ -1,22 +1,17 @@
-
package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.MageObject;
-import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.DiesThisOrAnotherCreatureTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-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.PermanentToken;
+import mage.constants.TargetController;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.permanent.token.EldraziSpawnToken;
/**
@@ -24,16 +19,25 @@ import mage.game.permanent.token.EldraziSpawnToken;
* @author North
*/
public final class PawnOfUlamog extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature you control");
+ static {
+ filter.add(TargetController.YOU.getControllerPredicate());
+ filter.add(Predicates.not(TokenPredicate.instance));
+ }
+
public PawnOfUlamog(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}");
this.subtype.add(SubType.VAMPIRE);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
- this.addAbility(new PawnOfUlamogTriggeredAbility());
+ // Whenever Pawn of Ulamog or another nontoken creature you control dies, you may create a 0/1 colorless
+ // Eldrazi Spawn creature token. It has "Sacrifice this creature: Add {C}."
+ this.addAbility(new DiesThisOrAnotherCreatureTriggeredAbility(new CreateTokenEffect(new EldraziSpawnToken()), true, filter));
}
public PawnOfUlamog(final PawnOfUlamog card) {
@@ -44,49 +48,4 @@ public final class PawnOfUlamog extends CardImpl {
public PawnOfUlamog copy() {
return new PawnOfUlamog(this);
}
-}
-
-class PawnOfUlamogTriggeredAbility extends TriggeredAbilityImpl {
-
- public PawnOfUlamogTriggeredAbility() {
- super(Zone.BATTLEFIELD, new CreateTokenEffect(new EldraziSpawnToken()), true);
- }
-
- public PawnOfUlamogTriggeredAbility(PawnOfUlamogTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public PawnOfUlamogTriggeredAbility copy() {
- return new PawnOfUlamogTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == EventType.ZONE_CHANGE;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- UUID targetId = event.getTargetId();
- MageObject card = game.getLastKnownInformation(targetId, Zone.BATTLEFIELD);
- if (card instanceof Permanent && !(card instanceof PermanentToken)) {
- Permanent permanent = (Permanent) card;
- ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
- if (zEvent.isDiesEvent()
- && permanent.isControlledBy(this.controllerId)
- && (targetId.equals(this.getSourceId())
- || (permanent.isCreature()
- && !targetId.equals(this.getSourceId())
- && !(permanent instanceof PermanentToken)))) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public String getRule() {
- return "Whenever Pawn of Ulamog or another nontoken creature you control dies, you may create a 0/1 colorless Eldrazi Spawn creature token. It has \"Sacrifice this creature: Add {C}.\"";
- }
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/p/PearlLakeAncient.java b/Mage.Sets/src/mage/cards/p/PearlLakeAncient.java
index 194cb439234..09d36f2957d 100644
--- a/Mage.Sets/src/mage/cards/p/PearlLakeAncient.java
+++ b/Mage.Sets/src/mage/cards/p/PearlLakeAncient.java
@@ -3,7 +3,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.ReturnToHandChosenControlledPermanentCost;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
@@ -34,7 +34,7 @@ public final class PearlLakeAncient extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// Pearl Lake Ancient can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Prowess
this.addAbility(new ProwessAbility());
diff --git a/Mage.Sets/src/mage/cards/p/PedanticLearning.java b/Mage.Sets/src/mage/cards/p/PedanticLearning.java
index b72a54652c1..369e68327b6 100644
--- a/Mage.Sets/src/mage/cards/p/PedanticLearning.java
+++ b/Mage.Sets/src/mage/cards/p/PedanticLearning.java
@@ -1,7 +1,5 @@
-
package mage.cards.p;
-import java.util.Set;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -61,10 +59,8 @@ class PedanticLearningTriggeredAbility extends TriggeredAbilityImpl {
Card card = game.getCard(event.getTargetId());
if (card != null) {
UUID cardOwnerId = card.getOwnerId();
- Set cardType = card.getCardType();
if (cardOwnerId != null
&& card.isOwnedBy(getControllerId())
- && cardType != null
&& card.isLand()) {
return true;
}
diff --git a/Mage.Sets/src/mage/cards/p/PeerIntoTheAbyss.java b/Mage.Sets/src/mage/cards/p/PeerIntoTheAbyss.java
new file mode 100644
index 00000000000..8db533e2ef2
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/PeerIntoTheAbyss.java
@@ -0,0 +1,65 @@
+package mage.cards.p;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.TargetPlayer;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class PeerIntoTheAbyss extends CardImpl {
+
+ public PeerIntoTheAbyss(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{B}{B}");
+
+ // Target player draws cards equal to half the number of cards in their library and loses half their life. Round up each time.
+ this.getSpellAbility().addEffect(new PeerIntoTheAbyssEffect());
+ this.getSpellAbility().addTarget(new TargetPlayer());
+ }
+
+ private PeerIntoTheAbyss(final PeerIntoTheAbyss card) {
+ super(card);
+ }
+
+ @Override
+ public PeerIntoTheAbyss copy() {
+ return new PeerIntoTheAbyss(this);
+ }
+}
+
+class PeerIntoTheAbyssEffect extends OneShotEffect {
+
+ PeerIntoTheAbyssEffect() {
+ super(Outcome.Benefit);
+ staticText = "Target player draws cards equal to half the number of cards in their library " +
+ "and loses half their life. Round up each time.";
+ }
+
+ private PeerIntoTheAbyssEffect(final PeerIntoTheAbyssEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public PeerIntoTheAbyssEffect copy() {
+ return new PeerIntoTheAbyssEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
+ if (targetPlayer == null) {
+ return false;
+ }
+ targetPlayer.drawCards((int) Math.ceil(targetPlayer.getLibrary().size() / 2.0), source.getSourceId(), game);
+ targetPlayer.loseLife((int) Math.ceil(targetPlayer.getLife() / 2.0), game, false);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/p/PelakkaWurm.java b/Mage.Sets/src/mage/cards/p/PelakkaWurm.java
index 0a690d34e8c..3acc2b2a802 100644
--- a/Mage.Sets/src/mage/cards/p/PelakkaWurm.java
+++ b/Mage.Sets/src/mage/cards/p/PelakkaWurm.java
@@ -3,7 +3,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.GainLifeEffect;
@@ -28,7 +28,7 @@ public final class PelakkaWurm extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(7), false));
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public PelakkaWurm(final PelakkaWurm card) {
diff --git a/Mage.Sets/src/mage/cards/p/PenumbraBobcat.java b/Mage.Sets/src/mage/cards/p/PenumbraBobcat.java
index cb352641137..0bf08139230 100644
--- a/Mage.Sets/src/mage/cards/p/PenumbraBobcat.java
+++ b/Mage.Sets/src/mage/cards/p/PenumbraBobcat.java
@@ -3,7 +3,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class PenumbraBobcat extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(1);
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new PenumbraBobcatToken(), 1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new PenumbraBobcatToken(), 1), false));
}
public PenumbraBobcat(final PenumbraBobcat card) {
diff --git a/Mage.Sets/src/mage/cards/p/PenumbraKavu.java b/Mage.Sets/src/mage/cards/p/PenumbraKavu.java
index 62f28bb944f..39c884d8e7b 100644
--- a/Mage.Sets/src/mage/cards/p/PenumbraKavu.java
+++ b/Mage.Sets/src/mage/cards/p/PenumbraKavu.java
@@ -3,7 +3,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class PenumbraKavu extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(3);
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new PenumbraKavuToken(), 1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new PenumbraKavuToken(), 1), false));
}
public PenumbraKavu(final PenumbraKavu card) {
diff --git a/Mage.Sets/src/mage/cards/p/PenumbraSpider.java b/Mage.Sets/src/mage/cards/p/PenumbraSpider.java
index 9761b8f2b4e..34d1aa47ad5 100644
--- a/Mage.Sets/src/mage/cards/p/PenumbraSpider.java
+++ b/Mage.Sets/src/mage/cards/p/PenumbraSpider.java
@@ -3,7 +3,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class PenumbraSpider extends CardImpl {
// Reach
this.addAbility(ReachAbility.getInstance());
// When Penumbra Spider dies, create a 2/4 black Spider creature token with reach.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new PenumbraSpiderToken()), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new PenumbraSpiderToken()), false));
}
public PenumbraSpider(final PenumbraSpider card) {
diff --git a/Mage.Sets/src/mage/cards/p/PenumbraWurm.java b/Mage.Sets/src/mage/cards/p/PenumbraWurm.java
index ca9654f73d0..ac7b100b62a 100644
--- a/Mage.Sets/src/mage/cards/p/PenumbraWurm.java
+++ b/Mage.Sets/src/mage/cards/p/PenumbraWurm.java
@@ -3,7 +3,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
@@ -29,7 +29,7 @@ public final class PenumbraWurm extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// When Penumbra Wurm dies, create a 6/6 black Wurm creature token with trample.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new PenumbraWurmToken(), 1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new PenumbraWurmToken(), 1), false));
}
public PenumbraWurm(final PenumbraWurm card) {
diff --git a/Mage.Sets/src/mage/cards/p/PerilousMyr.java b/Mage.Sets/src/mage/cards/p/PerilousMyr.java
index 1ccbe47fad9..1843606d1fa 100644
--- a/Mage.Sets/src/mage/cards/p/PerilousMyr.java
+++ b/Mage.Sets/src/mage/cards/p/PerilousMyr.java
@@ -4,7 +4,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class PerilousMyr extends CardImpl {
this.toughness = new MageInt(1);
// When Perilous Myr dies, it deals 2 damage to any target.
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(2, "it"), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(2, "it"), false);
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/p/Persecute.java b/Mage.Sets/src/mage/cards/p/Persecute.java
index 606121cf23e..b5cad0fddb7 100644
--- a/Mage.Sets/src/mage/cards/p/Persecute.java
+++ b/Mage.Sets/src/mage/cards/p/Persecute.java
@@ -1,24 +1,23 @@
-
package mage.cards.p;
-import java.util.Set;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
+import mage.cards.CardsImpl;
import mage.choices.ChoiceColor;
import mage.constants.CardType;
import mage.constants.Outcome;
+import mage.filter.FilterCard;
+import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class Persecute extends CardImpl {
@@ -29,7 +28,6 @@ public final class Persecute extends CardImpl {
// Choose a color. Target player reveals their hand and discards all cards of that color.
this.getSpellAbility().addEffect(new PersecuteEffect());
this.getSpellAbility().addTarget(new TargetPlayer());
-
}
public Persecute(final Persecute card) {
@@ -44,12 +42,12 @@ public final class Persecute extends CardImpl {
class PersecuteEffect extends OneShotEffect {
- public PersecuteEffect() {
+ PersecuteEffect() {
super(Outcome.Discard);
this.staticText = "Choose a color. Target player reveals their hand and discards all cards of that color";
}
- public PersecuteEffect(final PersecuteEffect effect) {
+ private PersecuteEffect(final PersecuteEffect effect) {
super(effect);
}
@@ -64,17 +62,16 @@ class PersecuteEffect extends OneShotEffect {
MageObject sourceObject = game.getObject(source.getSourceId());
Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
ChoiceColor choice = new ChoiceColor();
- if (controller != null && sourceObject != null && targetPlayer != null && controller.choose(outcome, choice, game)) {
- Cards hand = targetPlayer.getHand();
- targetPlayer.revealCards(sourceObject.getIdName(), hand, game);
- Set cards = hand.getCards(game);
- for (Card card : cards) {
- if (card != null && card.getColor(game).shares(choice.getColor())) {
- targetPlayer.discard(card, source, game);
- }
- }
- return true;
+ if (controller == null
+ || sourceObject == null
+ || targetPlayer == null
+ || !controller.choose(outcome, choice, game)) {
+ return false;
}
- return false;
+ FilterCard filterCard = new FilterCard();
+ filterCard.add(new ColorPredicate(choice.getColor()));
+ targetPlayer.revealCards(source, targetPlayer.getHand(), game);
+ targetPlayer.discard(new CardsImpl(targetPlayer.getHand().getCards(filterCard, game)), source, game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/p/PersonalIncarnation.java b/Mage.Sets/src/mage/cards/p/PersonalIncarnation.java
index d0c82220e61..c39a4cc0fc8 100644
--- a/Mage.Sets/src/mage/cards/p/PersonalIncarnation.java
+++ b/Mage.Sets/src/mage/cards/p/PersonalIncarnation.java
@@ -4,7 +4,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
@@ -41,7 +41,7 @@ public final class PersonalIncarnation extends CardImpl {
ability.setMayActivate(TargetController.OWNER);
this.addAbility(ability);
// When Personal Incarnation dies, its owner loses half their life, rounded up.
- this.addAbility(new DiesTriggeredAbility(new PersonalIncarnationLoseHalfLifeEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new PersonalIncarnationLoseHalfLifeEffect()));
}
public PersonalIncarnation(final PersonalIncarnation card) {
diff --git a/Mage.Sets/src/mage/cards/p/PestilentHaze.java b/Mage.Sets/src/mage/cards/p/PestilentHaze.java
new file mode 100644
index 00000000000..424901bd535
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/PestilentHaze.java
@@ -0,0 +1,70 @@
+package mage.cards.p;
+
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.BoostAllEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.counters.CounterType;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class PestilentHaze extends CardImpl {
+
+ public PestilentHaze(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{B}");
+
+ // Choose one —
+ // • All creatures get -2/-2 until end of turn.
+ this.getSpellAbility().addEffect(new BoostAllEffect(-2, -2, Duration.EndOfTurn));
+
+ // • Remove two loyalty counters from each planeswalker.
+ this.getSpellAbility().addMode(new Mode(new PestilentHazeEffect()));
+ }
+
+ private PestilentHaze(final PestilentHaze card) {
+ super(card);
+ }
+
+ @Override
+ public PestilentHaze copy() {
+ return new PestilentHaze(this);
+ }
+}
+
+class PestilentHazeEffect extends OneShotEffect {
+
+ PestilentHazeEffect() {
+ super(Outcome.Benefit);
+ staticText = "remove two loyalty counters from each planeswalker";
+ }
+
+ private PestilentHazeEffect(final PestilentHazeEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public PestilentHazeEffect copy() {
+ return new PestilentHazeEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ game.getBattlefield()
+ .getActivePermanents(
+ StaticFilters.FILTER_PERMANENT_PLANESWALKER,
+ source.getControllerId(), source.getSourceId(), game
+ ).stream()
+ .forEach(permanent -> permanent.removeCounters(CounterType.LOYALTY.createInstance(2), game));
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/PetraSphinx.java b/Mage.Sets/src/mage/cards/p/PetraSphinx.java
index 253d4e77f01..c97a792299e 100644
--- a/Mage.Sets/src/mage/cards/p/PetraSphinx.java
+++ b/Mage.Sets/src/mage/cards/p/PetraSphinx.java
@@ -78,7 +78,7 @@ class PetraSphinxEffect extends OneShotEffect {
if (card != null) {
Cards cards = new CardsImpl(card);
player.revealCards(source, cards, game);
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
player.moveCards(cards, Zone.HAND, source, game);
} else {
player.moveCards(cards, Zone.GRAVEYARD, source, game);
diff --git a/Mage.Sets/src/mage/cards/p/PetrifiedWoodKin.java b/Mage.Sets/src/mage/cards/p/PetrifiedWoodKin.java
index a42b819797a..140cb43463f 100644
--- a/Mage.Sets/src/mage/cards/p/PetrifiedWoodKin.java
+++ b/Mage.Sets/src/mage/cards/p/PetrifiedWoodKin.java
@@ -7,7 +7,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.OneShotEffect;
import mage.constants.SubType;
@@ -44,7 +44,7 @@ public final class PetrifiedWoodKin extends CardImpl {
this.toughness = new MageInt(3);
// Petrified Wood-Kin can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Bloodthirst X
this.addAbility(new EntersBattlefieldAbility(
diff --git a/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java b/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java
index e1bc4cafc83..db9dec6f2b3 100644
--- a/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java
+++ b/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java
@@ -7,7 +7,7 @@ import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.InvertCondition;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.LoseGameSourceControllerEffect;
@@ -37,7 +37,7 @@ public final class PhageTheUntouchable extends CardImpl {
// When Phage the Untouchable enters the battlefield, if you didn't cast it from your hand, you lose the game.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new LoseGameSourceControllerEffect(), false),
- new InvertCondition(CastFromHandSourceCondition.instance),
+ new InvertCondition(CastFromHandSourcePermanentCondition.instance),
"When {this} enters the battlefield, if you didn't cast it from your hand, you lose the game"
), new CastFromHandWatcher());
diff --git a/Mage.Sets/src/mage/cards/p/PhantomWhelp.java b/Mage.Sets/src/mage/cards/p/PhantomWhelp.java
index 33d2e7e760d..f397cf302ab 100644
--- a/Mage.Sets/src/mage/cards/p/PhantomWhelp.java
+++ b/Mage.Sets/src/mage/cards/p/PhantomWhelp.java
@@ -22,7 +22,7 @@ public final class PhantomWhelp extends CardImpl {
public PhantomWhelp(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
this.subtype.add(SubType.ILLUSION);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/p/PhenaxGodOfDeception.java b/Mage.Sets/src/mage/cards/p/PhenaxGodOfDeception.java
index ec36c25ab34..decaf844f26 100644
--- a/Mage.Sets/src/mage/cards/p/PhenaxGodOfDeception.java
+++ b/Mage.Sets/src/mage/cards/p/PhenaxGodOfDeception.java
@@ -45,14 +45,12 @@ public final class PhenaxGodOfDeception extends CardImpl {
// Creatures you control have "{T}: Target player puts the top X cards of their library into their graveyard, where X is this creature's toughness."
Ability ability = new SimpleActivatedAbility(
new PutTopCardOfLibraryIntoGraveTargetEffect(SourcePermanentToughnessValue.getInstance())
- .setText("Target player puts the top X cards of their library into their graveyard, " +
- "where X is this creature's toughness"), new TapSourceCost());
+ .setText("Target player mills X cards, where X is this creature's toughness"), new TapSourceCost());
ability.addTarget(new TargetPlayer());
this.addAbility(new SimpleStaticAbility(
new GainAbilityControlledEffect(
ability, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES, false
- ).setText("Creatures you control have \"{T}: Target player puts the top X cards of their library " +
- "into their graveyard, where X is this creature's toughness.\"")
+ ).setText("Creatures you control have \"{T}: Target player mills X cards, where X is this creature's toughness.\"")
));
}
diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianRevoker.java b/Mage.Sets/src/mage/cards/p/PhyrexianRevoker.java
index a0880af364a..2ca284b7372 100644
--- a/Mage.Sets/src/mage/cards/p/PhyrexianRevoker.java
+++ b/Mage.Sets/src/mage/cards/p/PhyrexianRevoker.java
@@ -1,7 +1,6 @@
-
package mage.cards.p;
-import java.util.UUID;
+import java.util.Optional;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@@ -11,23 +10,20 @@ import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
+import mage.util.CardUtil;
+import java.util.UUID;
/**
- *
* @author BetaSteward_at_googlemail.com
*/
public final class PhyrexianRevoker extends CardImpl {
public PhyrexianRevoker(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}");
this.subtype.add(SubType.HORROR);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
@@ -47,7 +43,6 @@ public final class PhyrexianRevoker extends CardImpl {
public PhyrexianRevoker copy() {
return new PhyrexianRevoker(this);
}
-
}
class PhyrexianRevokerEffect2 extends ContinuousRuleModifyingEffectImpl {
@@ -75,7 +70,7 @@ class PhyrexianRevokerEffect2 extends ContinuousRuleModifyingEffectImpl {
public String getInfoMessage(Ability source, GameEvent event, Game game) {
MageObject mageObject = game.getObject(source.getSourceId());
if (mageObject != null) {
- return "You can't activate abilities of sources with that name (" + mageObject.getLogName() + " in play).";
+ return "You can't activate abilities of sources with that name (" + mageObject.getName() + " in play).";
}
return null;
}
@@ -83,12 +78,16 @@ class PhyrexianRevokerEffect2 extends ContinuousRuleModifyingEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.ACTIVATE_ABILITY) {
- MageObject object = game.getObject(event.getSourceId());
- if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) {
- return true;
+ MageObject object = game.getObject(event.getSourceId()); // Can happen for special ability????
+ if (object != null) {
+ Optional optAbility = object.getAbilities().get(event.getTargetId());
+ if (optAbility.isPresent() && AbilityType.SPECIAL_ACTION == optAbility.get().getAbilityType()) {
+ return false;
+ }
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
+ return CardUtil.haveSameNames(object, cardName, game);
}
}
return false;
}
-
}
diff --git a/Mage.Sets/src/mage/cards/p/Phytotitan.java b/Mage.Sets/src/mage/cards/p/Phytotitan.java
index 30ca720f792..e8c65913700 100644
--- a/Mage.Sets/src/mage/cards/p/Phytotitan.java
+++ b/Mage.Sets/src/mage/cards/p/Phytotitan.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@@ -32,7 +32,7 @@ public final class Phytotitan extends CardImpl {
this.toughness = new MageInt(2);
// When Phytotitan dies, return it to the battlefield tapped under its owner's control at the beginning of their next upkeep.
- this.addAbility(new DiesTriggeredAbility(new PhytotitanEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new PhytotitanEffect()));
}
public Phytotitan(final Phytotitan card) {
diff --git a/Mage.Sets/src/mage/cards/p/PitchburnDevils.java b/Mage.Sets/src/mage/cards/p/PitchburnDevils.java
index d715c2eb37e..3f18bbe2110 100644
--- a/Mage.Sets/src/mage/cards/p/PitchburnDevils.java
+++ b/Mage.Sets/src/mage/cards/p/PitchburnDevils.java
@@ -3,7 +3,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class PitchburnDevils extends CardImpl {
this.toughness = new MageInt(3);
// When Pitchburn Devils dies, it deals 3 damage to any target.
- DiesTriggeredAbility ability = new DiesTriggeredAbility(new DamageTargetEffect(3, "it"));
+ DiesSourceTriggeredAbility ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(3, "it"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/p/PithingNeedle.java b/Mage.Sets/src/mage/cards/p/PithingNeedle.java
index d8049e8ab00..2ec117dff4a 100644
--- a/Mage.Sets/src/mage/cards/p/PithingNeedle.java
+++ b/Mage.Sets/src/mage/cards/p/PithingNeedle.java
@@ -1,7 +1,5 @@
package mage.cards.p;
-import java.util.Optional;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
@@ -11,12 +9,18 @@ import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
+import mage.util.CardUtil;
+
+import java.util.Optional;
+import java.util.UUID;
/**
- *
* @author jeffwadsworth, nox
*/
public final class PithingNeedle extends CardImpl {
@@ -70,14 +74,13 @@ class PithingNeedleEffect extends ContinuousRuleModifyingEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
Optional ability = game.getAbility(event.getTargetId(), event.getSourceId());
- if (ability.isPresent()
+ if (ability.isPresent()
&& object != null) {
- if (game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId()) // controller in range
+ return game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId()) // controller in range
&& !(ability.get() instanceof ActivatedManaAbilityImpl) // not an activated mana ability
- && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) {
- return true;
- }
+ && CardUtil.haveSameNames(object, cardName, game);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/p/PlagueDogs.java b/Mage.Sets/src/mage/cards/p/PlagueDogs.java
index 9eda0693bc6..f12376dd91a 100644
--- a/Mage.Sets/src/mage/cards/p/PlagueDogs.java
+++ b/Mage.Sets/src/mage/cards/p/PlagueDogs.java
@@ -4,7 +4,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -26,12 +26,12 @@ public final class PlagueDogs extends CardImpl {
public PlagueDogs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}");
this.subtype.add(SubType.ZOMBIE);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// When Plague Dogs dies, all creatures get -1/-1 until end of turn.
- this.addAbility(new DiesTriggeredAbility(new BoostAllEffect(-1, -1, Duration.EndOfTurn), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new BoostAllEffect(-1, -1, Duration.EndOfTurn), false));
// {2}, Sacrifice Plague Dogs: Draw a card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{2}"));
ability.addCost(new SacrificeSourceCost());
diff --git a/Mage.Sets/src/mage/cards/p/PlagueSpitter.java b/Mage.Sets/src/mage/cards/p/PlagueSpitter.java
index e312b05ab3d..c80ac79d91d 100644
--- a/Mage.Sets/src/mage/cards/p/PlagueSpitter.java
+++ b/Mage.Sets/src/mage/cards/p/PlagueSpitter.java
@@ -4,7 +4,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageEverythingEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -28,7 +28,7 @@ public final class PlagueSpitter extends CardImpl {
// At the beginning of your upkeep, Plague Spitter deals 1 damage to each creature and each player.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DamageEverythingEffect(1), TargetController.YOU, false));
// When Plague Spitter dies, Plague Spitter deals 1 damage to each creature and each player.
- this.addAbility(new DiesTriggeredAbility(new DamageEverythingEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DamageEverythingEffect(1), false));
}
public PlagueSpitter(final PlagueSpitter card) {
diff --git a/Mage.Sets/src/mage/cards/p/PlagueWight.java b/Mage.Sets/src/mage/cards/p/PlagueWight.java
index 433b85b01d5..aa6551c1741 100644
--- a/Mage.Sets/src/mage/cards/p/PlagueWight.java
+++ b/Mage.Sets/src/mage/cards/p/PlagueWight.java
@@ -2,7 +2,7 @@ package mage.cards.p;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl;
@@ -32,7 +32,7 @@ public final class PlagueWight extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Plague Wight becomes blocked, each creature blocking it gets -1/-1 until end of turn.
- this.addAbility(new BecomesBlockedTriggeredAbility(new PlagueWightEffect(), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new PlagueWightEffect(), false));
}
private PlagueWight(final PlagueWight card) {
diff --git a/Mage.Sets/src/mage/cards/p/PlaneswalkersMischief.java b/Mage.Sets/src/mage/cards/p/PlaneswalkersMischief.java
index 1662e161975..c546bfda19e 100644
--- a/Mage.Sets/src/mage/cards/p/PlaneswalkersMischief.java
+++ b/Mage.Sets/src/mage/cards/p/PlaneswalkersMischief.java
@@ -22,6 +22,7 @@ import mage.watchers.common.SpellsCastWatcher;
import java.util.List;
import java.util.UUID;
+import mage.MageObject;
/**
* @author jeffwadsworth
@@ -67,16 +68,15 @@ class PlaneswalkersMischiefEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player opponent = game.getPlayer(source.getFirstTarget());
- if (opponent != null
- && opponent.getHand().size() > 0) {
+ if (opponent != null && opponent.getHand().size() > 0) {
Card revealedCard = opponent.getHand().getRandom(game);
if (revealedCard == null) {
return false;
}
Cards cards = new CardsImpl(revealedCard);
- opponent.revealCards("Planeswalker's Mischief Reveal", cards, game);
+ opponent.revealCards(source, cards, game);
if (revealedCard.isInstant()
- || revealedCard.isSorcery()) {
+ || revealedCard.isSorcery()) {
opponent.moveCardToExileWithInfo(revealedCard, source.getSourceId(), "Planeswalker's Mischief", source.getSourceId(), game, Zone.HAND, true);
AsThoughEffect effect = new PlaneswalkersMischiefCastFromExileEffect();
effect.setTargetPointer(new FixedTarget(revealedCard.getId()));
@@ -123,8 +123,7 @@ class PlaneswalkersMischiefCastFromExileEffect extends AsThoughEffectImpl {
Card card = game.getCard(objectId);
if (player != null
&& card != null) {
- player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
- return true;
+ return allowCardToPlayWithoutMana(objectId, source, affectedControllerId, game);
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/p/PollutedDead.java b/Mage.Sets/src/mage/cards/p/PollutedDead.java
index fc70b9d4e14..9bc48539cfe 100644
--- a/Mage.Sets/src/mage/cards/p/PollutedDead.java
+++ b/Mage.Sets/src/mage/cards/p/PollutedDead.java
@@ -4,7 +4,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class PollutedDead extends CardImpl {
this.toughness = new MageInt(3);
// When Polluted Dead dies, destroy target land.
- Ability ability = new DiesTriggeredAbility(new DestroyTargetEffect());
+ Ability ability = new DiesSourceTriggeredAbility(new DestroyTargetEffect());
Target target = new TargetLandPermanent();
ability.addTarget(target);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/p/PossibilityStorm.java b/Mage.Sets/src/mage/cards/p/PossibilityStorm.java
index 998707e955d..134108fb512 100644
--- a/Mage.Sets/src/mage/cards/p/PossibilityStorm.java
+++ b/Mage.Sets/src/mage/cards/p/PossibilityStorm.java
@@ -1,8 +1,6 @@
-
package mage.cards.p;
-import java.util.EnumSet;
-import java.util.Set;
+import java.util.ArrayList;
import java.util.UUID;
import mage.MageObject;
import mage.MageObjectReference;
@@ -147,7 +145,7 @@ class PossibilityStormEffect extends OneShotEffect {
return false;
}
- private boolean sharesType(Card card, Set cardTypes) {
+ private boolean sharesType(Card card, ArrayList cardTypes) {
for (CardType type : card.getCardType()) {
if (cardTypes.contains(type)) {
return true;
diff --git a/Mage.Sets/src/mage/cards/p/PowerstoneShard.java b/Mage.Sets/src/mage/cards/p/PowerstoneShard.java
index 7862217f161..722f1d88bd3 100644
--- a/Mage.Sets/src/mage/cards/p/PowerstoneShard.java
+++ b/Mage.Sets/src/mage/cards/p/PowerstoneShard.java
@@ -1,9 +1,9 @@
-
package mage.cards.p;
-import java.util.UUID;
import mage.Mana;
+import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.hint.ValueHint;
import mage.abilities.mana.DynamicManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -11,8 +11,9 @@ import mage.constants.CardType;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.NamePredicate;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class PowerstoneShard extends CardImpl {
@@ -28,7 +29,9 @@ public final class PowerstoneShard extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// {T}: Add {C} for each artifact you control named Powerstone Shard.
- this.addAbility(new DynamicManaAbility(Mana.ColorlessMana(1), new PermanentsOnBattlefieldCount(filter)));
+ DynamicValue xValue = new PermanentsOnBattlefieldCount(filter);
+ this.addAbility(new DynamicManaAbility(Mana.ColorlessMana(1), xValue)
+ .addHint(new ValueHint("Artifact you control named Powerstone Shard", xValue)));
}
public PowerstoneShard(final PowerstoneShard card) {
diff --git a/Mage.Sets/src/mage/cards/p/Preacher.java b/Mage.Sets/src/mage/cards/p/Preacher.java
index cda4db79a29..5b9769746e4 100644
--- a/Mage.Sets/src/mage/cards/p/Preacher.java
+++ b/Mage.Sets/src/mage/cards/p/Preacher.java
@@ -74,22 +74,17 @@ class PreacherEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
+ Permanent targetPermanent = game.getPermanent(source.getFirstTarget());
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null
- && sourcePermanent != null) {
- Permanent targetPermanent = game.getPermanent(source.getFirstTarget());
- if (targetPermanent != null) {
- SourceTappedCondition sourceTappedCondition = SourceTappedCondition.instance;
- SourceHasRemainedInSameZoneCondition conditionSourceSameZone = new SourceHasRemainedInSameZoneCondition(sourcePermanent.getId());
- SourceHasRemainedInSameZoneCondition conditionTargetSameZone = new SourceHasRemainedInSameZoneCondition(targetPermanent.getId());
- ConditionalContinuousEffect effect = new ConditionalContinuousEffect(
- new GainControlTargetEffect(Duration.Custom),
- new CompoundCondition(sourceTappedCondition, new CompoundCondition(conditionSourceSameZone, conditionTargetSameZone)),
- "Gain control of target creature of an opponent's choice that they control for as long as {this} remains tapped");
- effect.setTargetPointer(new FixedTarget(targetPermanent.getId()));
- game.addEffect(effect, source);
- return true;
- }
+ if (controller != null && sourcePermanent != null && targetPermanent != null) {
+ SourceTappedCondition sourceTappedCondition = SourceTappedCondition.instance;
+ ConditionalContinuousEffect effect = new ConditionalContinuousEffect(
+ new GainControlTargetEffect(Duration.Custom),
+ sourceTappedCondition,
+ "Gain control of target creature of an opponent's choice that they control for as long as {this} remains tapped");
+ effect.setTargetPointer(new FixedTarget(targetPermanent.getId()));
+ game.addEffect(effect, source);
+ return true;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/p/PredatoryWurm.java b/Mage.Sets/src/mage/cards/p/PredatoryWurm.java
new file mode 100644
index 00000000000..9808b09b7f1
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/PredatoryWurm.java
@@ -0,0 +1,53 @@
+package mage.cards.p;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
+import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.keyword.VigilanceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterPlaneswalkerPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class PredatoryWurm extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterPlaneswalkerPermanent(SubType.GARRUK);
+ private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
+
+ public PredatoryWurm(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
+
+ this.subtype.add(SubType.WURM);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(4);
+
+ // Vigilance
+ this.addAbility(VigilanceAbility.getInstance());
+
+ // Predatory Wurm gets +2/+2 as long as you control a Garruk planeswalker.
+ this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
+ new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
+ condition, "{this} gets +2/+2 as long as you control a Garruk planeswalker"
+ )));
+ }
+
+ private PredatoryWurm(final PredatoryWurm card) {
+ super(card);
+ }
+
+ @Override
+ public PredatoryWurm copy() {
+ return new PredatoryWurm(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/Predict.java b/Mage.Sets/src/mage/cards/p/Predict.java
index 1f9ec4f9302..d53aa652fd6 100644
--- a/Mage.Sets/src/mage/cards/p/Predict.java
+++ b/Mage.Sets/src/mage/cards/p/Predict.java
@@ -8,7 +8,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
@@ -30,7 +29,7 @@ public final class Predict extends CardImpl {
this.getSpellAbility().addTarget(new TargetPlayer());
}
- public Predict(final Predict card) {
+ private Predict(final Predict card) {
super(card);
}
@@ -42,13 +41,13 @@ public final class Predict extends CardImpl {
class PredictEffect extends OneShotEffect {
- public PredictEffect() {
+ PredictEffect() {
super(Outcome.DrawCard);
- this.staticText = ", then target player puts the top card of their library into their graveyard. "
- + "If that card has the chosen name, you draw two cards. Otherwise, you draw a card.";
+ this.staticText = ", then target player mills a card. If a card with the chosen name was milled this way, " +
+ "you draw two cards. Otherwise, you draw a card.";
}
- public PredictEffect(final PredictEffect effect) {
+ private PredictEffect(final PredictEffect effect) {
super(effect);
}
@@ -62,19 +61,17 @@ class PredictEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
- if (controller != null && targetPlayer != null && cardName != null && !cardName.isEmpty()) {
- int amount = 1;
- Card card = targetPlayer.getLibrary().getFromTop(game);
- if (card != null) {
- controller.moveCards(card, Zone.GRAVEYARD, source, game);
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
- amount = 2;
- }
- }
- controller.drawCards(amount, source.getSourceId(), game);
- return true;
+ if (controller == null || targetPlayer == null || cardName == null || cardName.isEmpty()) {
+ return false;
}
- return false;
+ int toDraw = 1;
+ for (Card card : targetPlayer.millCards(1, source, game).getCards(game)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
+ toDraw = 2;
+ break;
+ }
+ }
+ controller.drawCards(toDraw, source.getSourceId(), game);
+ return true;
}
-
}
diff --git a/Mage.Sets/src/mage/cards/p/Preordain.java b/Mage.Sets/src/mage/cards/p/Preordain.java
index 4eae38cd40d..39ce81a2c4e 100644
--- a/Mage.Sets/src/mage/cards/p/Preordain.java
+++ b/Mage.Sets/src/mage/cards/p/Preordain.java
@@ -1,14 +1,14 @@
package mage.cards.p;
-import java.util.UUID;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import java.util.UUID;
+
/**
- *
* @author BetaSteward_at_googlemail.com
*/
public final class Preordain extends CardImpl {
@@ -18,11 +18,11 @@ public final class Preordain extends CardImpl {
// Scry 2, then draw a card. (To scry 2, look at the top two cards of your library, then put any number of them on the bottom of your library and the rest on top in any order.)
this.getSpellAbility().addEffect(
- new ScryEffect(2).setText("Scry 2, ")
+ new ScryEffect(2, false)
);
this.getSpellAbility().addEffect(
new DrawCardSourceControllerEffect(1)
- .setText("then draw a card. (To scry 2, "
+ .setText(", then draw a card. (To scry 2, "
+ "look at the top two cards of your library, "
+ "then put any number of them on the "
+ "bottom of your library and the rest on "
diff --git a/Mage.Sets/src/mage/cards/p/PriceOfFame.java b/Mage.Sets/src/mage/cards/p/PriceOfFame.java
index 4a8dd77d97e..be37a6e7732 100644
--- a/Mage.Sets/src/mage/cards/p/PriceOfFame.java
+++ b/Mage.Sets/src/mage/cards/p/PriceOfFame.java
@@ -36,7 +36,7 @@ public final class PriceOfFame extends CardImpl {
// This spell costs {2} less to cast if it targets a legendary creature.
this.addAbility(new SimpleStaticAbility(
- Zone.STACK, new SpellCostReductionSourceEffect(2, condition)
+ Zone.ALL, new SpellCostReductionSourceEffect(2, condition).setCanWorksOnStackOnly(true)
).setRuleAtTheTop(true));
// Destroy target creature.
diff --git a/Mage.Sets/src/mage/cards/p/Pridemalkin.java b/Mage.Sets/src/mage/cards/p/Pridemalkin.java
new file mode 100644
index 00000000000..fab9b798b13
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/Pridemalkin.java
@@ -0,0 +1,61 @@
+package mage.cards.p;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
+import mage.abilities.effects.common.counter.AddCountersTargetEffect;
+import mage.abilities.keyword.TrampleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.permanent.CounterPredicate;
+import mage.target.common.TargetControlledCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class Pridemalkin extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterControlledCreaturePermanent("creature you control with a +1/+1 counter on it");
+
+ static {
+ filter.add(new CounterPredicate(CounterType.P1P1));
+ }
+
+ public Pridemalkin(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
+
+ this.subtype.add(SubType.CAT);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // When Pridemalkin enters the battlefield, put a +1/+1 counter on target creature you control.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
+ ability.addTarget(new TargetControlledCreaturePermanent());
+ this.addAbility(ability);
+
+ // Each creature you control with a +1/+1 counter on it has trample.
+ this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(
+ TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter
+ )));
+ }
+
+ private Pridemalkin(final Pridemalkin card) {
+ super(card);
+ }
+
+ @Override
+ public Pridemalkin copy() {
+ return new Pridemalkin(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/PrimalDruid.java b/Mage.Sets/src/mage/cards/p/PrimalDruid.java
index 2a8de813ed2..fcafcea74cc 100644
--- a/Mage.Sets/src/mage/cards/p/PrimalDruid.java
+++ b/Mage.Sets/src/mage/cards/p/PrimalDruid.java
@@ -2,7 +2,7 @@
package mage.cards.p;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.cards.CardImpl;
@@ -30,7 +30,7 @@ public final class PrimalDruid extends CardImpl {
// When Primal Druid dies, you may search your library for a basic land card, put it onto the battlefield tapped, then shuffle your library.
Effect effect = new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true);
effect.setText("you may search your library for a basic land card, put it onto the battlefield tapped, then shuffle your library");
- this.addAbility(new DiesTriggeredAbility(effect, true));
+ this.addAbility(new DiesSourceTriggeredAbility(effect, true));
}
diff --git a/Mage.Sets/src/mage/cards/p/PrimalMight.java b/Mage.Sets/src/mage/cards/p/PrimalMight.java
new file mode 100644
index 00000000000..b0d0e69504f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/PrimalMight.java
@@ -0,0 +1,46 @@
+package mage.cards.p;
+
+import mage.abilities.dynamicvalue.common.ManacostVariableValue;
+import mage.abilities.effects.common.FightTargetsEffect;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.filter.StaticFilters;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetControlledCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author mikalinn777
+ */
+
+
+public final class PrimalMight extends CardImpl {
+
+ public PrimalMight(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{G}");
+
+ // Target creature you control gets +X/+X until end of turn. Then it fights up to one target creature you don’t control.
+ this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
+ this.getSpellAbility().addEffect(new BoostTargetEffect(ManacostVariableValue.instance, ManacostVariableValue.instance, Duration.EndOfTurn));
+ //
+ this.getSpellAbility().addEffect(new FightTargetsEffect()
+ .concatBy("Then")
+ .setText("it fights up to one target creature you don't control"));
+ this.getSpellAbility().addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, false));
+
+ }
+
+ public PrimalMight(final PrimalMight card) {
+ super(card);
+ }
+
+ @Override
+ public PrimalMight copy() {
+ return new PrimalMight(this);
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/p/Probe.java b/Mage.Sets/src/mage/cards/p/Probe.java
index 6c98d48e93e..4a80a78d859 100644
--- a/Mage.Sets/src/mage/cards/p/Probe.java
+++ b/Mage.Sets/src/mage/cards/p/Probe.java
@@ -32,7 +32,7 @@ public final class Probe extends CardImpl {
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new DiscardTargetEffect(2),
KickedCondition.instance,
- "
if this spell was kicked, target player discards two cards"));
+ "
If this spell was kicked, target player discards two cards"));
this.getSpellAbility().setTargetAdjuster(ProbeAdjuster.instance);
}
diff --git a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java
index 67d0fa84342..8008c8eabbb 100644
--- a/Mage.Sets/src/mage/cards/p/ProfaneProcession.java
+++ b/Mage.Sets/src/mage/cards/p/ProfaneProcession.java
@@ -76,7 +76,7 @@ class ProfaneProcessionEffect extends OneShotEffect {
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && exileId != null && sourceObject != null) {
new ExileTargetEffect(exileId, sourceObject.getIdName()).setTargetPointer(targetPointer).apply(game, source);
- game.applyEffects();
+ game.getState().processAction(game);
ExileZone exileZone = game.getExile().getExileZone(exileId);
if (exileZone != null && exileZone.size() > 2) {
new TransformSourceEffect(true).apply(game, source);
diff --git a/Mage.Sets/src/mage/cards/p/ProsperousPirates.java b/Mage.Sets/src/mage/cards/p/ProsperousPirates.java
index 8d3de1a966e..06183091c96 100644
--- a/Mage.Sets/src/mage/cards/p/ProsperousPirates.java
+++ b/Mage.Sets/src/mage/cards/p/ProsperousPirates.java
@@ -1,7 +1,5 @@
-
package mage.cards.p;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -11,8 +9,9 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.game.permanent.token.TreasureToken;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class ProsperousPirates extends CardImpl {
@@ -26,7 +25,7 @@ public final class ProsperousPirates extends CardImpl {
this.toughness = new MageInt(4);
// When Prosperous Pirates enters the battlefield, create two colorless Treasure artifact tokens with "{T}, Sacrifice this artifact: Add one mana of any color."
- this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TreasureToken("XLN"), 2)));
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TreasureToken(), 2)));
}
public ProsperousPirates(final ProsperousPirates card) {
diff --git a/Mage.Sets/src/mage/cards/p/ProteanHulk.java b/Mage.Sets/src/mage/cards/p/ProteanHulk.java
index 50a43b2da69..30a2df42057 100644
--- a/Mage.Sets/src/mage/cards/p/ProteanHulk.java
+++ b/Mage.Sets/src/mage/cards/p/ProteanHulk.java
@@ -4,7 +4,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
import mage.constants.CardType;
@@ -34,7 +34,7 @@ public final class ProteanHulk extends CardImpl {
this.toughness = new MageInt(6);
// When Protean Hulk dies, search your library for any number of creature cards with total converted mana cost 6 or less and put them onto the battlefield. Then shuffle your library.
- this.addAbility(new DiesTriggeredAbility(new ProteanHulkEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new ProteanHulkEffect()));
}
public ProteanHulk(final ProteanHulk card) {
diff --git a/Mage.Sets/src/mage/cards/p/ProteanThaumaturge.java b/Mage.Sets/src/mage/cards/p/ProteanThaumaturge.java
index d8ecd23dac0..337bbe5b63f 100644
--- a/Mage.Sets/src/mage/cards/p/ProteanThaumaturge.java
+++ b/Mage.Sets/src/mage/cards/p/ProteanThaumaturge.java
@@ -72,7 +72,7 @@ class ProteanThaumaturgeApplyToPermanent extends ApplyToPermanent {
@Override
public boolean apply(Game game, Permanent permanent, Ability source, UUID copyToObjectId) {
- permanent.addAbility(ProteanThaumaturge.createAbility(), game);
+ permanent.addAbility(ProteanThaumaturge.createAbility(), source.getSourceId(), game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/p/ProwlingSerpopard.java b/Mage.Sets/src/mage/cards/p/ProwlingSerpopard.java
index e676d6beb9a..c3b547c582c 100644
--- a/Mage.Sets/src/mage/cards/p/ProwlingSerpopard.java
+++ b/Mage.Sets/src/mage/cards/p/ProwlingSerpopard.java
@@ -3,7 +3,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.CantBeCounteredControlledEffect;
import mage.cards.CardImpl;
@@ -35,7 +35,7 @@ public final class ProwlingSerpopard extends CardImpl {
this.toughness = new MageInt(3);
// Prowling Serpopard can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Creature spells you control can't be countered.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeCounteredControlledEffect(filterTarget, null, Duration.WhileOnBattlefield)));
diff --git a/Mage.Sets/src/mage/cards/p/PryingQuestions.java b/Mage.Sets/src/mage/cards/p/PryingQuestions.java
index fe21705c4cd..b1f314c267c 100644
--- a/Mage.Sets/src/mage/cards/p/PryingQuestions.java
+++ b/Mage.Sets/src/mage/cards/p/PryingQuestions.java
@@ -1,7 +1,5 @@
-
package mage.cards.p;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
@@ -16,20 +14,20 @@ import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class PryingQuestions extends CardImpl {
public PryingQuestions(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
// Target opponent loses 3 life and puts a card from their hand on top of their library.
- this.getSpellAbility().addTarget(new TargetOpponent());
this.getSpellAbility().addEffect(new LoseLifeTargetEffect(3));
- this.getSpellAbility().addEffect(new PryingQuestionsEffect());
-
+ this.getSpellAbility().addEffect(new PryingQuestionsEffect().concatBy("and"));
+ this.getSpellAbility().addTarget(new TargetOpponent());
}
public PryingQuestions(final PryingQuestions card) {
@@ -46,7 +44,7 @@ class PryingQuestionsEffect extends OneShotEffect {
public PryingQuestionsEffect() {
super(Outcome.Detriment);
- this.staticText = "and puts a card from their hand on top of their library";
+ this.staticText = "puts a card from their hand on top of their library";
}
public PryingQuestionsEffect(final PryingQuestionsEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/p/PsychicImpetus.java b/Mage.Sets/src/mage/cards/p/PsychicImpetus.java
index 8a0d6a96e8a..bbbedc9098c 100644
--- a/Mage.Sets/src/mage/cards/p/PsychicImpetus.java
+++ b/Mage.Sets/src/mage/cards/p/PsychicImpetus.java
@@ -40,7 +40,7 @@ public final class PsychicImpetus extends CardImpl {
// Whenever enchanted creature attacks, you scry 2.
this.addAbility(new AttacksAttachedTriggeredAbility(
- new ScryEffect(2).setText("you scry 2"), AttachmentType.AURA, false
+ new ScryEffect(2, false).setText("you scry 2"), AttachmentType.AURA, false
));
}
diff --git a/Mage.Sets/src/mage/cards/p/PsychicSpiral.java b/Mage.Sets/src/mage/cards/p/PsychicSpiral.java
index f142d790429..6595fa697ee 100644
--- a/Mage.Sets/src/mage/cards/p/PsychicSpiral.java
+++ b/Mage.Sets/src/mage/cards/p/PsychicSpiral.java
@@ -63,7 +63,7 @@ class PsychicSpiralEffect extends OneShotEffect {
if (cardsInGraveyard > 0) {
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (targetPlayer != null) {
- targetPlayer.moveCards(targetPlayer.getLibrary().getTopCards(game, cardsInGraveyard), Zone.GRAVEYARD, source, game);
+ targetPlayer.millCards(cardsInGraveyard, source, game);
}
}
return true;
diff --git a/Mage.Sets/src/mage/cards/p/PsychicStrike.java b/Mage.Sets/src/mage/cards/p/PsychicStrike.java
index f5c63b1c1f4..344c345efed 100644
--- a/Mage.Sets/src/mage/cards/p/PsychicStrike.java
+++ b/Mage.Sets/src/mage/cards/p/PsychicStrike.java
@@ -66,7 +66,7 @@ class PsychicStrikeEffect extends OneShotEffect {
if (stackObject != null) {
Player controller = game.getPlayer(stackObject.getControllerId());
if (controller != null) {
- controller.moveCards(controller.getLibrary().getTopCards(game, 2), Zone.GRAVEYARD, source, game);
+ controller.millCards(2, source, game);
}
}
return countered;
diff --git a/Mage.Sets/src/mage/cards/p/PsychicVortex.java b/Mage.Sets/src/mage/cards/p/PsychicVortex.java
index 91789ec2cc3..87b86d7e5bd 100644
--- a/Mage.Sets/src/mage/cards/p/PsychicVortex.java
+++ b/Mage.Sets/src/mage/cards/p/PsychicVortex.java
@@ -55,7 +55,7 @@ public final class PsychicVortex extends CardImpl {
class PsychicVortexCost extends CostImpl {
PsychicVortexCost() {
- this.text = "Draw a card.";
+ this.text = "Draw a card";
}
@Override
diff --git a/Mage.Sets/src/mage/cards/p/PureReflection.java b/Mage.Sets/src/mage/cards/p/PureReflection.java
index cad8231b337..645bc1d8958 100644
--- a/Mage.Sets/src/mage/cards/p/PureReflection.java
+++ b/Mage.Sets/src/mage/cards/p/PureReflection.java
@@ -71,7 +71,7 @@ public final class PureReflection extends CardImpl {
game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game).forEach((permanent) -> {
permanent.destroy(source.getSourceId(), game,false);
});
- game.applyEffects();
+ game.getState().processAction(game);
// Then that player creates an X/X white Reflection creature token, where X is the converted mana cost of that spell.
ReflectionPureToken token = new ReflectionPureToken(spell.getConvertedManaCost());
diff --git a/Mage.Sets/src/mage/cards/p/PurpleCrystalCrab.java b/Mage.Sets/src/mage/cards/p/PurpleCrystalCrab.java
index 43dbbc267b0..6a896a5d4c8 100644
--- a/Mage.Sets/src/mage/cards/p/PurpleCrystalCrab.java
+++ b/Mage.Sets/src/mage/cards/p/PurpleCrystalCrab.java
@@ -2,7 +2,7 @@ package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
@@ -23,7 +23,7 @@ public final class PurpleCrystalCrab extends CardImpl {
this.toughness = new MageInt(1);
// When Purple-Crystal Crab dies, draw card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public PurpleCrystalCrab(final PurpleCrystalCrab card) {
diff --git a/Mage.Sets/src/mage/cards/p/PursuedWhale.java b/Mage.Sets/src/mage/cards/p/PursuedWhale.java
new file mode 100644
index 00000000000..d26a8f02d8c
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/p/PursuedWhale.java
@@ -0,0 +1,76 @@
+package mage.cards.p;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.FilterCard;
+import mage.game.Game;
+import mage.game.permanent.token.PursuedWhaleToken;
+import mage.game.permanent.token.Token;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class PursuedWhale extends CardImpl {
+
+ public PursuedWhale(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}");
+
+ this.subtype.add(SubType.WHALE);
+ this.power = new MageInt(8);
+ this.toughness = new MageInt(8);
+
+ // When Pursued Whale enters the battlefield, each opponent creates a 1/1 red Pirate creature token with "This creature can't block" and "Creatures you control attack each combat if able."
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new PursuedWhaleTokenEffect()));
+
+ // Spells your opponents cast that target Pursued Whale cost {3} more to cast.
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(3, new FilterCard("Spells"), TargetController.OPPONENT))
+ );
+ }
+
+ private PursuedWhale(final PursuedWhale card) {
+ super(card);
+ }
+
+ @Override
+ public PursuedWhale copy() {
+ return new PursuedWhale(this);
+ }
+}
+
+class PursuedWhaleTokenEffect extends OneShotEffect {
+
+ private static final Token token = new PursuedWhaleToken();
+
+ PursuedWhaleTokenEffect() {
+ super(Outcome.Benefit);
+ staticText = "each opponent creates a 1/1 red Pirate creature token with " +
+ "\"This creature can't block\" and \"Creatures you control attack each combat if able.\"";
+ }
+
+ private PursuedWhaleTokenEffect(final PursuedWhaleTokenEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public PursuedWhaleTokenEffect copy() {
+ return new PursuedWhaleTokenEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ for (UUID playerId : game.getOpponents(source.getControllerId())) {
+ token.putOntoBattlefield(1, game, source.getSourceId(), playerId);
+ }
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/p/Putrefy.java b/Mage.Sets/src/mage/cards/p/Putrefy.java
index b0b3c0f39bc..f467c3a8753 100644
--- a/Mage.Sets/src/mage/cards/p/Putrefy.java
+++ b/Mage.Sets/src/mage/cards/p/Putrefy.java
@@ -27,7 +27,7 @@ public final class Putrefy extends CardImpl {
public Putrefy (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}{G}");
-
+ // Destroy target artifact or creature. It can't be regenerated.
this.getSpellAbility().addTarget(new TargetPermanent(filter));
this.getSpellAbility().addEffect(new DestroyTargetEffect(true));
}
diff --git a/Mage.Sets/src/mage/cards/p/PyreHound.java b/Mage.Sets/src/mage/cards/p/PyreHound.java
index 6e42ee1b4c4..4a17383d6db 100644
--- a/Mage.Sets/src/mage/cards/p/PyreHound.java
+++ b/Mage.Sets/src/mage/cards/p/PyreHound.java
@@ -22,7 +22,7 @@ public final class PyreHound extends CardImpl {
public PyreHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}");
this.subtype.add(SubType.ELEMENTAL);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/q/QarsiSadist.java b/Mage.Sets/src/mage/cards/q/QarsiSadist.java
index bc18b2e299c..7e05641809c 100644
--- a/Mage.Sets/src/mage/cards/q/QarsiSadist.java
+++ b/Mage.Sets/src/mage/cards/q/QarsiSadist.java
@@ -1,11 +1,8 @@
-
package mage.cards.q;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ExploitCreatureTriggeredAbility;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.keyword.ExploitAbility;
@@ -15,14 +12,15 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class QarsiSadist extends CardImpl {
public QarsiSadist(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.CLERIC);
this.power = new MageInt(1);
@@ -30,12 +28,11 @@ public final class QarsiSadist extends CardImpl {
// Exploit
this.addAbility(new ExploitAbility());
+
// When Qarsi Sadist exploits a creature, target opponent loses 2 life and you gain 2 life.
Ability ability = new ExploitCreatureTriggeredAbility(new LoseLifeTargetEffect(2), false);
+ ability.addEffect(new GainLifeEffect(2).concatBy("and"));
ability.addTarget(new TargetOpponent());
- Effect effect = new GainLifeEffect(2);
- effect.setText("and you gain 2 life");
- ability.addEffect(effect);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/q/QasaliAmbusher.java b/Mage.Sets/src/mage/cards/q/QasaliAmbusher.java
index 9fa8d530231..32f19ddb9e2 100644
--- a/Mage.Sets/src/mage/cards/q/QasaliAmbusher.java
+++ b/Mage.Sets/src/mage/cards/q/QasaliAmbusher.java
@@ -2,16 +2,22 @@ package mage.cards.q;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.ActivatedAbilityImpl;
-import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.Ability;
+import mage.abilities.condition.CompoundCondition;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.AttackedThisStepCondition;
+import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
+import mage.abilities.costs.AlternativeCostSourceAbility;
+import mage.abilities.decorator.ConditionalAsThoughEffect;
import mage.abilities.effects.common.continuous.CastAsThoughItHadFlashSourceEffect;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterControlledLandPermanent;
-import mage.game.Game;
-import mage.game.combat.CombatGroup;
+import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.Predicates;
+import mage.watchers.common.PlayerAttackedStepWatcher;
/**
*
@@ -19,6 +25,18 @@ import mage.game.combat.CombatGroup;
*/
public final class QasaliAmbusher extends CardImpl {
+ private static final FilterControlledPermanent filterForest = new FilterControlledPermanent();
+ private static final FilterControlledPermanent filterPlains = new FilterControlledPermanent();
+
+ static {
+ filterForest.add(SubType.FOREST.getPredicate());
+ filterPlains.add(SubType.PLAINS.getPredicate());
+ }
+
+ private static final Condition condition =
+ new CompoundCondition("If a creature is attacking you and you control a Forest and a Plains",
+ AttackedThisStepCondition.instance, new PermanentsOnTheBattlefieldCondition(filterForest), new PermanentsOnTheBattlefieldCondition(filterPlains));
+
public QasaliAmbusher(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{W}");
this.subtype.add(SubType.CAT);
@@ -30,10 +48,13 @@ public final class QasaliAmbusher extends CardImpl {
// Reach
this.addAbility(ReachAbility.getInstance());
- // If a creature is attacking you and you control a Forest and a Plains,
+ // If a creature is attacking you and you control a Forest and a Plains,
// you may cast Qasali Ambusher without paying its mana cost and as though it had flash.
- this.addAbility(new QasaliAmbusherAbility());
-
+ Ability ability = new AlternativeCostSourceAbility(null, condition);
+ ability.addEffect(new ConditionalAsThoughEffect(new CastAsThoughItHadFlashSourceEffect(Duration.EndOfGame), condition)
+ .setText("you may cast {this} without paying its mana cost and as though it had flash"));
+ ability.addWatcher(new PlayerAttackedStepWatcher());
+ this.addAbility(ability);
}
public QasaliAmbusher(final QasaliAmbusher card) {
@@ -44,57 +65,4 @@ public final class QasaliAmbusher extends CardImpl {
public QasaliAmbusher copy() {
return new QasaliAmbusher(this);
}
-}
-
-class QasaliAmbusherAbility extends ActivatedAbilityImpl {
-
- private static final FilterControlledLandPermanent filterPlains = new FilterControlledLandPermanent();
- private static final FilterControlledLandPermanent filterForest = new FilterControlledLandPermanent();
-
- static {
- filterPlains.add(SubType.PLAINS.getPredicate());
- filterForest.add(SubType.FOREST.getPredicate());
- }
-
- public QasaliAmbusherAbility() {
- super(Zone.HAND, new CastAsThoughItHadFlashSourceEffect(Duration.EndOfGame), new ManaCostsImpl());
- this.timing = TimingRule.INSTANT;
- this.usesStack = false;
- }
-
- public QasaliAmbusherAbility(final QasaliAmbusherAbility ability) {
- super(ability);
- }
-
- @Override
- public QasaliAmbusherAbility copy() {
- return new QasaliAmbusherAbility(this);
- }
-
- @Override
- public ActivationStatus canActivate(UUID playerId, Game game) {
- if (!game.getBattlefield().getActivePermanents(filterPlains,
- this.getControllerId(), this.getSourceId(), game).isEmpty()
- && !game.getBattlefield().getActivePermanents(filterForest,
- this.getControllerId(), this.getSourceId(), game).isEmpty()) {
- for (CombatGroup group : game.getCombat().getGroups()) {
- if (isControlledBy(group.getDefenderId())) {
- return super.canActivate(playerId, game);
- }
- }
- }
- return ActivationStatus.getFalse();
- }
-
- @Override
- public String getRule(boolean all) {
- return this.getRule();
- }
-
- @Override
- public String getRule() {
- return "If a creature is attacking you and you control a Forest and "
- + "a Plains, you may cast {this} without paying its mana "
- + "cost and as though it had flash.";
- }
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/q/QasaliSlingers.java b/Mage.Sets/src/mage/cards/q/QasaliSlingers.java
index a68dd907373..457e83c16f6 100644
--- a/Mage.Sets/src/mage/cards/q/QasaliSlingers.java
+++ b/Mage.Sets/src/mage/cards/q/QasaliSlingers.java
@@ -1,28 +1,27 @@
-
package mage.cards.q;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.keyword.ReachAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Zone;
+import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
-import mage.game.Game;
-import mage.game.events.GameEvent;
-import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
+import java.util.UUID;
+
/**
- *
* @author spjspj
*/
public final class QasaliSlingers extends CardImpl {
+ private static final FilterPermanent filter = new FilterPermanent(SubType.CAT, "Cat");
+
public QasaliSlingers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}");
@@ -35,10 +34,14 @@ public final class QasaliSlingers extends CardImpl {
this.addAbility(ReachAbility.getInstance());
// Whenever Qasali Slingers or another Cat enters the battlefield under your control, you may destroy target artifact or enchantment.
- this.addAbility(new QasaliSlingersTriggeredAbility());
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new DestroyTargetEffect(), filter, true, true
+ );
+ ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
+ this.addAbility(ability);
}
- public QasaliSlingers(final QasaliSlingers card) {
+ private QasaliSlingers(final QasaliSlingers card) {
super(card);
}
@@ -47,44 +50,3 @@ public final class QasaliSlingers extends CardImpl {
return new QasaliSlingers(this);
}
}
-
-class QasaliSlingersTriggeredAbility extends TriggeredAbilityImpl {
-
- public QasaliSlingersTriggeredAbility() {
- super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true);
- this.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
- }
-
- public QasaliSlingersTriggeredAbility(final QasaliSlingersTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public QasaliSlingersTriggeredAbility copy() {
- return new QasaliSlingersTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- Permanent permanent = game.getPermanent(event.getTargetId());
- if (permanent != null) {
- if (permanent.getId().equals(this.getSourceId())) {
- return true;
- }
- if (permanent.hasSubtype(SubType.CAT, game) && permanent.isControlledBy(this.getControllerId())) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public String getRule() {
- return "Whenever {this} or another Cat enters the battlefield under your control, you may destroy target artifact or enchantment.";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/q/QuartzwoodCrasher.java b/Mage.Sets/src/mage/cards/q/QuartzwoodCrasher.java
index 3316de67033..e83513d2237 100644
--- a/Mage.Sets/src/mage/cards/q/QuartzwoodCrasher.java
+++ b/Mage.Sets/src/mage/cards/q/QuartzwoodCrasher.java
@@ -12,7 +12,7 @@ import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
-import mage.game.permanent.token.BeastXToken;
+import mage.game.permanent.token.DinosaurBeastToken;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.Watcher;
@@ -50,7 +50,7 @@ public final class QuartzwoodCrasher extends CardImpl {
class QuartzwoodCrasherTriggeredAbility extends TriggeredAbilityImpl {
- private final Set damagedPlayerIds = new HashSet();
+ private final Set damagedPlayerIds = new HashSet<>();
QuartzwoodCrasherTriggeredAbility() {
super(Zone.BATTLEFIELD, new QuartzwoodCrasherEffect(), false);
@@ -78,17 +78,16 @@ class QuartzwoodCrasherTriggeredAbility extends TriggeredAbilityImpl {
damagedPlayerIds.clear();
return false;
}
- if (event.getType() != GameEvent.EventType.DAMAGED_PLAYER
- && !((DamagedPlayerEvent) event).isCombatDamage()) {
- return false;
- }
- Permanent creature = game.getPermanent(event.getSourceId());
- if (creature != null && creature.isControlledBy(controllerId)
- && creature.getAbilities(game).containsKey(TrampleAbility.getInstance().getId())
- && !damagedPlayerIds.contains(event.getTargetId())) {
- damagedPlayerIds.add(event.getTargetId());
- this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
- return true;
+ if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER
+ && ((DamagedPlayerEvent) event).isCombatDamage()) {
+ Permanent creature = game.getPermanent(event.getSourceId());
+ if (creature != null && creature.isControlledBy(controllerId)
+ && creature.hasAbility(TrampleAbility.getInstance(), game)
+ && !damagedPlayerIds.contains(event.getTargetId())) {
+ damagedPlayerIds.add(event.getTargetId());
+ this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
+ return true;
+ }
}
return false;
}
@@ -119,7 +118,7 @@ class QuartzwoodCrasherEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
QuartzwoodCrasherWatcher watcher = game.getState().getWatcher(QuartzwoodCrasherWatcher.class);
- return watcher != null && new BeastXToken(
+ return watcher != null && new DinosaurBeastToken(
watcher.getDamage(targetPointer.getFirst(game, source), source.getControllerId())
).putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
}
@@ -127,7 +126,7 @@ class QuartzwoodCrasherEffect extends OneShotEffect {
class QuartzwoodCrasherWatcher extends Watcher {
- private final Map> damageMap = new HashMap();
+ private final Map> damageMap = new HashMap<>();
QuartzwoodCrasherWatcher() {
super(WatcherScope.GAME);
@@ -144,7 +143,7 @@ class QuartzwoodCrasherWatcher extends Watcher {
return;
}
Permanent creature = game.getPermanent(event.getSourceId());
- if (creature == null || !creature.getAbilities(game).containsKey(TrampleAbility.getInstance().getId())) {
+ if (creature == null || !creature.hasAbility(TrampleAbility.getInstance(), game)) {
return;
}
damageMap
diff --git a/Mage.Sets/src/mage/cards/q/QuicksmithRebel.java b/Mage.Sets/src/mage/cards/q/QuicksmithRebel.java
index 87b0caca71f..38c7600aa89 100644
--- a/Mage.Sets/src/mage/cards/q/QuicksmithRebel.java
+++ b/Mage.Sets/src/mage/cards/q/QuicksmithRebel.java
@@ -1,4 +1,3 @@
-
package mage.cards.q;
import java.util.UUID;
@@ -14,12 +13,13 @@ import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledArtifactPermanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetAnyTarget;
+import mage.watchers.common.LostControlWatcher;
/**
*
@@ -44,6 +44,7 @@ public final class QuicksmithRebel extends CardImpl {
"target artifact you control gains \"{T}: This artifact deals 2 damage to any target\" for as long as you control {this}");
Ability ability = new EntersBattlefieldTriggeredAbility(effect, false);
ability.addTarget(new TargetPermanent(new FilterControlledArtifactPermanent()));
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/q/QuicksmithSpy.java b/Mage.Sets/src/mage/cards/q/QuicksmithSpy.java
index 2b69c073e1b..d52dfb6b076 100644
--- a/Mage.Sets/src/mage/cards/q/QuicksmithSpy.java
+++ b/Mage.Sets/src/mage/cards/q/QuicksmithSpy.java
@@ -1,4 +1,3 @@
-
package mage.cards.q;
import java.util.UUID;
@@ -14,11 +13,12 @@ import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledArtifactPermanent;
import mage.target.TargetPermanent;
+import mage.watchers.common.LostControlWatcher;
/**
*
@@ -42,6 +42,7 @@ public final class QuicksmithSpy extends CardImpl {
"target artifact you control gains \"{T}: Draw a card\" for as long as you control {this}");
Ability ability = new EntersBattlefieldTriggeredAbility(effect, false);
ability.addTarget(new TargetPermanent(new FilterControlledArtifactPermanent()));
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/q/QuirionDryad.java b/Mage.Sets/src/mage/cards/q/QuirionDryad.java
index 4e2afae86e5..e15c7011082 100644
--- a/Mage.Sets/src/mage/cards/q/QuirionDryad.java
+++ b/Mage.Sets/src/mage/cards/q/QuirionDryad.java
@@ -21,7 +21,7 @@ import mage.filter.predicate.mageobject.ColorPredicate;
*/
public final class QuirionDryad extends CardImpl {
- private static final FilterSpell filter = new FilterSpell("white, blue, black, or red spell");
+ private static final FilterSpell filter = new FilterSpell("a spell that's white, blue, black, or red");
static {
filter.add(Predicates.or(
diff --git a/Mage.Sets/src/mage/cards/r/RabidElephant.java b/Mage.Sets/src/mage/cards/r/RabidElephant.java
index 58f07702759..95a69e47ecb 100644
--- a/Mage.Sets/src/mage/cards/r/RabidElephant.java
+++ b/Mage.Sets/src/mage/cards/r/RabidElephant.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.MultipliedValue;
import mage.abilities.dynamicvalue.common.BlockedCreatureCount;
@@ -32,7 +32,7 @@ public final class RabidElephant extends CardImpl {
DynamicValue value = new MultipliedValue(new BlockedCreatureCount(), 2);
Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn, true);
effect.setText("it gets +2/+2 until end of turn for each creature blocking it");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public RabidElephant(final RabidElephant card) {
diff --git a/Mage.Sets/src/mage/cards/r/RadhaHeartOfKeld.java b/Mage.Sets/src/mage/cards/r/RadhaHeartOfKeld.java
new file mode 100644
index 00000000000..64237b8e0e4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/RadhaHeartOfKeld.java
@@ -0,0 +1,75 @@
+package mage.cards.r;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.MyTurnCondition;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect;
+import mage.abilities.effects.common.continuous.PlayTheTopCardEffect;
+import mage.abilities.hint.common.MyTurnHint;
+import mage.abilities.keyword.FirstStrikeAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
+import mage.filter.common.FilterLandCard;
+
+import java.util.UUID;
+
+/**
+ * @author arcox
+ */
+public final class RadhaHeartOfKeld extends CardImpl {
+ private static final FilterCard filter = new FilterLandCard("play land cards");
+
+ public RadhaHeartOfKeld(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.ELF);
+ this.subtype.add(SubType.WARRIOR);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // As long as it's your turn, Radha, Heart of Keld has first strike.
+ this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
+ new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield),
+ MyTurnCondition.instance, "As long as it's your turn, {this} has first strike."
+ )).addHint(MyTurnHint.instance));
+
+ // You may look at the top card of your library any time, and you may play lands from the top of your library.
+ LookAtTopCardOfLibraryAnyTimeEffect lookEffect = new LookAtTopCardOfLibraryAnyTimeEffect();
+ lookEffect.overrideRuleText("You may look at the top card of your library any time, ");
+ PlayTheTopCardEffect playEffect = new PlayTheTopCardEffect(filter);
+ playEffect.overrideRuleText("and you may play lands from the top of your library");
+
+ SimpleStaticAbility lookAndPlayAbility = new SimpleStaticAbility(lookEffect);
+ lookAndPlayAbility.addEffect(playEffect);
+ this.addAbility(lookAndPlayAbility);
+
+ // 4RG: Radha gets +X/+X until end of turn, where X is the number of lands you control.
+ DynamicValue controlledLands = new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS);
+ BoostSourceEffect bse = new BoostSourceEffect(controlledLands, controlledLands, Duration.EndOfTurn, true);
+ bse.overrideRuleText("Radha gets +X/+X until end of turn, where X is the number of lands you control");
+ this.addAbility(new SimpleActivatedAbility(bse, new ManaCostsImpl("{4}{R}{G}")));
+ }
+
+ private RadhaHeartOfKeld(final RadhaHeartOfKeld card) {
+ super(card);
+ }
+
+ @Override
+ public RadhaHeartOfKeld copy() {
+ return new RadhaHeartOfKeld(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/RagDealer.java b/Mage.Sets/src/mage/cards/r/RagDealer.java
index a10c1d4138f..0f97076fede 100644
--- a/Mage.Sets/src/mage/cards/r/RagDealer.java
+++ b/Mage.Sets/src/mage/cards/r/RagDealer.java
@@ -1,7 +1,5 @@
-
package mage.cards.r;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@@ -13,11 +11,12 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInASingleGraveyard;
+import java.util.UUID;
+
/**
- *
* @author LevelX, North
*/
public final class RagDealer extends CardImpl {
@@ -33,7 +32,7 @@ public final class RagDealer extends CardImpl {
// {2}{B}, {T}: Exile up to three target cards from a single graveyard.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new ManaCostsImpl("{2}{B}"));
ability.addCost(new TapSourceCost());
- ability.addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("cards from a single graveyard")));
+ ability.addTarget(new TargetCardInASingleGraveyard(0, 3, StaticFilters.FILTER_CARD_CARDS));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/r/RagingGorilla.java b/Mage.Sets/src/mage/cards/r/RagingGorilla.java
index 8b11fd21f7e..5c5df5d7f62 100644
--- a/Mage.Sets/src/mage/cards/r/RagingGorilla.java
+++ b/Mage.Sets/src/mage/cards/r/RagingGorilla.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class RagingGorilla extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Raging Gorilla blocks or becomes blocked, it gets +2/-2 until end of turn.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(2, -2, Duration.EndOfTurn), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(2, -2, Duration.EndOfTurn), false));
}
public RagingGorilla(final RagingGorilla card) {
diff --git a/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java b/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java
index 37f54529210..00a84e1aeeb 100644
--- a/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java
+++ b/Mage.Sets/src/mage/cards/r/RakdosLordOfRiots.java
@@ -105,10 +105,8 @@ class RakdosLordOfRiotsCostReductionEffect extends CostModificationEffectImpl {
Ability spellAbility = abilityToModify;
if (spellAbility != null) {
int amount = OpponentsLostLifeCount.instance.calculate(game, source, this);
- if (amount > 0) {
- CardUtil.reduceCost(spellAbility, amount);
- return true;
- }
+ CardUtil.reduceCost(spellAbility, amount);
+ return true;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/r/RakdosRagemutt.java b/Mage.Sets/src/mage/cards/r/RakdosRagemutt.java
index e4c1a606b29..90171b0a0c8 100644
--- a/Mage.Sets/src/mage/cards/r/RakdosRagemutt.java
+++ b/Mage.Sets/src/mage/cards/r/RakdosRagemutt.java
@@ -19,7 +19,7 @@ public final class RakdosRagemutt extends CardImpl {
public RakdosRagemutt(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{R}");
this.subtype.add(SubType.ELEMENTAL);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/r/RakshasasSecret.java b/Mage.Sets/src/mage/cards/r/RakshasasSecret.java
index 0b62846b48c..2f2ea93bdae 100644
--- a/Mage.Sets/src/mage/cards/r/RakshasasSecret.java
+++ b/Mage.Sets/src/mage/cards/r/RakshasasSecret.java
@@ -1,8 +1,5 @@
-
package mage.cards.r;
-import java.util.UUID;
-import mage.abilities.effects.Effect;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveControllerEffect;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardImpl;
@@ -10,25 +7,23 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class RakshasasSecret extends CardImpl {
public RakshasasSecret(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
// Target opponent discards two cards. Put the top two cards of your library into your graveyard.
this.getSpellAbility().addEffect(new DiscardTargetEffect(2));
this.getSpellAbility().addTarget(new TargetOpponent());
- Effect effect = new PutTopCardOfLibraryIntoGraveControllerEffect(2);
- effect.setText("Put the top two cards of your library into your graveyard");
- this.getSpellAbility().addEffect(effect);
+ this.getSpellAbility().addEffect(new PutTopCardOfLibraryIntoGraveControllerEffect(2).setText("Mill two cards."));
}
- public RakshasasSecret(final RakshasasSecret card) {
+ private RakshasasSecret(final RakshasasSecret card) {
super(card);
}
diff --git a/Mage.Sets/src/mage/cards/r/RambunctiousMutt.java b/Mage.Sets/src/mage/cards/r/RambunctiousMutt.java
new file mode 100644
index 00000000000..f751f3d5297
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/RambunctiousMutt.java
@@ -0,0 +1,51 @@
+package mage.cards.r;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.DestroyTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterArtifactOrEnchantmentPermanent;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class RambunctiousMutt extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterArtifactOrEnchantmentPermanent("artifact or enchantment an opponent controls");
+
+ static {
+ filter.add(TargetController.OPPONENT.getControllerPredicate());
+ }
+
+ public RambunctiousMutt(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
+
+ this.subtype.add(SubType.DOG);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(4);
+
+ // When Rambunctious Mutt enters the battlefield, destroy target artifact or enchantment an opponent controls.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect());
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(ability);
+ }
+
+ private RambunctiousMutt(final RambunctiousMutt card) {
+ super(card);
+ }
+
+ @Override
+ public RambunctiousMutt copy() {
+ return new RambunctiousMutt(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/RapidDecay.java b/Mage.Sets/src/mage/cards/r/RapidDecay.java
index 459a1d05964..f83aeca414c 100644
--- a/Mage.Sets/src/mage/cards/r/RapidDecay.java
+++ b/Mage.Sets/src/mage/cards/r/RapidDecay.java
@@ -1,18 +1,17 @@
-
package mage.cards.r;
-import java.util.UUID;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInASingleGraveyard;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class RapidDecay extends CardImpl {
@@ -22,7 +21,7 @@ public final class RapidDecay extends CardImpl {
// Exile up to three target cards from a single graveyard.
this.getSpellAbility().addEffect(new ExileTargetEffect());
- this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("cards from a single graveyard")));
+ this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, StaticFilters.FILTER_CARD_CARDS));
// Cycling {2}
this.addAbility(new CyclingAbility(new ManaCostsImpl("{2}")));
diff --git a/Mage.Sets/src/mage/cards/r/RareBGone.java b/Mage.Sets/src/mage/cards/r/RareBGone.java
index bb97dfceb0c..5440a478f84 100644
--- a/Mage.Sets/src/mage/cards/r/RareBGone.java
+++ b/Mage.Sets/src/mage/cards/r/RareBGone.java
@@ -2,23 +2,18 @@ package mage.cards.r;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
-import mage.cards.CardImpl;
-import mage.cards.CardSetInfo;
-import mage.cards.Cards;
+import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicate;
-import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.Objects;
-import java.util.Set;
import java.util.UUID;
/**
@@ -31,10 +26,9 @@ public final class RareBGone extends CardImpl {
// Each player sacrifices all permanents that are rare or mythic rare, then each player reveals their hand and discards all cards that are rare or mythic rare.
this.getSpellAbility().addEffect(new RareBGoneEffect());
-
}
- public RareBGone(final RareBGone card) {
+ private RareBGone(final RareBGone card) {
super(card);
}
@@ -50,22 +44,17 @@ class RareBGoneEffect extends OneShotEffect {
private static final FilterCard filterCard = new FilterCard();
static {
- filterPermanent.add(Predicates.or(
- new RarityPredicate(Rarity.RARE),
- new RarityPredicate(Rarity.MYTHIC)
- ));
- filterCard.add(Predicates.or(
- new RarityPredicate(Rarity.RARE),
- new RarityPredicate(Rarity.MYTHIC)
- ));
+ filterPermanent.add(RareBGonePredicate.instance);
+ filterCard.add(RareBGonePredicate.instance);
}
- public RareBGoneEffect() {
+ RareBGoneEffect() {
super(Outcome.Benefit);
- this.staticText = "Each player sacrifices all permanents that are rare or mythic rare, then each player reveals their hand and discards all cards that are rare or mythic rare";
+ this.staticText = "Each player sacrifices all permanents that are rare or mythic rare, " +
+ "then each player reveals their hand and discards all cards that are rare or mythic rare";
}
- public RareBGoneEffect(final RareBGoneEffect effect) {
+ private RareBGoneEffect(final RareBGoneEffect effect) {
super(effect);
}
@@ -77,44 +66,29 @@ class RareBGoneEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterPermanent, playerId, game)) {
- permanent.sacrifice(source.getSourceId(), game);
- }
- Cards hand = player.getHand();
- player.revealCards("Rare-B-Gone", hand, game);
- Set cards = hand.getCards(game);
- for (Card card : cards) {
- if (card != null && filterCard.match(card, game)) {
- player.discard(card, source, game);
- }
- }
- }
- }
- return true;
+ if (controller == null) {
+ return false;
}
- return false;
+ for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
+ Player player = game.getPlayer(playerId);
+ if (player == null) {
+ }
+ for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filterPermanent, playerId, game)) {
+ permanent.sacrifice(source.getSourceId(), game);
+ }
+ Cards cards = player.getHand();
+ player.revealCards(source, cards, game);
+ player.discard(new CardsImpl(cards.getCards(filterCard, game)), source, game);
+ }
+ return true;
}
}
-class RarityPredicate implements Predicate {
-
- private final Rarity rarity;
-
- public RarityPredicate(Rarity rarity) {
- this.rarity = rarity;
- }
+enum RareBGonePredicate implements Predicate {
+ instance;
@Override
public boolean apply(Card input, Game game) {
- return Objects.equals(input.getRarity(), rarity);
- }
-
- @Override
- public String toString() {
- return "Rarity(" + rarity + ')';
+ return Objects.equals(input.getRarity(), Rarity.RARE) || Objects.equals(input.getRarity(), Rarity.MYTHIC);
}
}
diff --git a/Mage.Sets/src/mage/cards/r/RatsFeast.java b/Mage.Sets/src/mage/cards/r/RatsFeast.java
index 395650b520e..38bc8555ebc 100644
--- a/Mage.Sets/src/mage/cards/r/RatsFeast.java
+++ b/Mage.Sets/src/mage/cards/r/RatsFeast.java
@@ -22,7 +22,7 @@ public final class RatsFeast extends CardImpl {
// Exile X target cards from a single graveyard.
this.getSpellAbility().addEffect(new ExileTargetEffect(
- "Exile X target cards from a single graveyard.", true
+ "Exile X target cards from a single graveyard", true
));
this.getSpellAbility().setTargetAdjuster(RatsFeastAdjuster.instance);
}
@@ -44,6 +44,6 @@ enum RatsFeastAdjuster implements TargetAdjuster {
public void adjustTargets(Ability ability, Game game) {
int xValue = ability.getManaCostsToPay().getX();
ability.getTargets().clear();
- ability.addTarget(new TargetCardInASingleGraveyard(xValue, xValue, StaticFilters.FILTER_CARD));
+ ability.addTarget(new TargetCardInASingleGraveyard(xValue, xValue, StaticFilters.FILTER_CARD_CARDS));
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/r/RazorclawBear.java b/Mage.Sets/src/mage/cards/r/RazorclawBear.java
index 74057a10b8a..1fe1cd2af45 100644
--- a/Mage.Sets/src/mage/cards/r/RazorclawBear.java
+++ b/Mage.Sets/src/mage/cards/r/RazorclawBear.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class RazorclawBear extends CardImpl {
// Whenever Razorclaw Bear becomes blocked, it gets +2/+2 until end of turn.
Effect effect = new BoostSourceEffect(2, 2, Duration.EndOfTurn);
effect.setText("it gets +2/+2 until end of turn");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public RazorclawBear(final RazorclawBear card) {
diff --git a/Mage.Sets/src/mage/cards/r/ReadTheTides.java b/Mage.Sets/src/mage/cards/r/ReadTheTides.java
new file mode 100644
index 00000000000..1c02d51448f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/ReadTheTides.java
@@ -0,0 +1,39 @@
+package mage.cards.r;
+
+import mage.abilities.Mode;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.ReturnToHandTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ReadTheTides extends CardImpl {
+
+ public ReadTheTides(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{U}");
+
+ // Choose one —
+ // • Draw three cards.
+ this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(3));
+
+ // • Return up to two target creatures to their owners' hands.
+ Mode mode = new Mode(new ReturnToHandTargetEffect());
+ mode.addTarget(new TargetCreaturePermanent(0, 2));
+ this.getSpellAbility().addMode(mode);
+ }
+
+ private ReadTheTides(final ReadTheTides card) {
+ super(card);
+ }
+
+ @Override
+ public ReadTheTides copy() {
+ return new ReadTheTides(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/RebornHero.java b/Mage.Sets/src/mage/cards/r/RebornHero.java
index eafb801ffa6..c0f824c082f 100644
--- a/Mage.Sets/src/mage/cards/r/RebornHero.java
+++ b/Mage.Sets/src/mage/cards/r/RebornHero.java
@@ -4,7 +4,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CardsInControllerGraveCondition;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -41,7 +41,7 @@ public final class RebornHero extends CardImpl {
Ability ability = new SimpleStaticAbility(
Zone.BATTLEFIELD,
new ConditionalContinuousEffect(
- new GainAbilitySourceEffect(new DiesTriggeredAbility(new DoIfCostPaid(
+ new GainAbilitySourceEffect(new DiesSourceTriggeredAbility(new DoIfCostPaid(
new ReturnSourceFromGraveyardToBattlefieldEffect(), new ManaCostsImpl("{W}{W}")
))),
new CardsInControllerGraveCondition(7),
diff --git a/Mage.Sets/src/mage/cards/r/ReefPirates.java b/Mage.Sets/src/mage/cards/r/ReefPirates.java
index 970faaf4adc..b74cbde8fe4 100644
--- a/Mage.Sets/src/mage/cards/r/ReefPirates.java
+++ b/Mage.Sets/src/mage/cards/r/ReefPirates.java
@@ -26,7 +26,7 @@ public final class ReefPirates extends CardImpl {
// Whenever Reef Pirates deals damage to an opponent, that player puts the top card of their library into their graveyard.
Effect effect = new PutLibraryIntoGraveTargetEffect(1);
- effect.setText("that player puts the top card of their library into their graveyard");
+ effect.setText("that player mills a card");
this.addAbility(new DealsDamageToAPlayerTriggeredAbility(effect, false, true));
}
diff --git a/Mage.Sets/src/mage/cards/r/ReefWorm.java b/Mage.Sets/src/mage/cards/r/ReefWorm.java
index 07707cac536..b54fed6a464 100644
--- a/Mage.Sets/src/mage/cards/r/ReefWorm.java
+++ b/Mage.Sets/src/mage/cards/r/ReefWorm.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class ReefWorm extends CardImpl {
this.toughness = new MageInt(1);
// When Reef Worm dies, create a 3/3 blue Fish creature token with "When this creature dies, create a 6/6 blue Whale creature token with "When this creature dies, create a 9/9 blue Kraken creature token.""
- addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ReefWormFishToken())));
+ addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new ReefWormFishToken())));
}
public ReefWorm(final ReefWorm card) {
diff --git a/Mage.Sets/src/mage/cards/r/ReflectorMage.java b/Mage.Sets/src/mage/cards/r/ReflectorMage.java
index faabe8b4779..8de4580f253 100644
--- a/Mage.Sets/src/mage/cards/r/ReflectorMage.java
+++ b/Mage.Sets/src/mage/cards/r/ReflectorMage.java
@@ -119,7 +119,7 @@ class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl
if (spell != null && spell.isFaceDown(game)) {
return false; // Face Down cast spell (Morph creature) has no name
}
- return CardUtil.haveSameNames(card.getName(), creatureName) && Objects.equals(ownerId, card.getOwnerId());
+ return CardUtil.haveSameNames(card, creatureName, game) && Objects.equals(ownerId, card.getOwnerId());
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/r/ReiverDemon.java b/Mage.Sets/src/mage/cards/r/ReiverDemon.java
index 695f4151a08..71167330d34 100644
--- a/Mage.Sets/src/mage/cards/r/ReiverDemon.java
+++ b/Mage.Sets/src/mage/cards/r/ReiverDemon.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.keyword.FlyingAbility;
@@ -43,7 +43,7 @@ public final class ReiverDemon extends CardImpl {
// When Reiver Demon enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter, true), false),
- CastFromHandSourceCondition.instance,
+ CastFromHandSourcePermanentCondition.instance,
"When {this} enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated."),
new CastFromHandWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/r/RekindledFlame.java b/Mage.Sets/src/mage/cards/r/RekindledFlame.java
index b294ef6821a..a5592bde474 100644
--- a/Mage.Sets/src/mage/cards/r/RekindledFlame.java
+++ b/Mage.Sets/src/mage/cards/r/RekindledFlame.java
@@ -1,30 +1,26 @@
-
package mage.cards.r;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
-import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.OpponentHasNoCardsInHandCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect;
+import mage.abilities.hint.ConditionHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
-import mage.game.Game;
-import mage.players.Player;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
*/
public final class RekindledFlame extends CardImpl {
- static final String rule = "if an opponent has no cards in hand, you may return Rekindled Flame from your graveyard to your hand";
-
public RekindledFlame(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}{R}");
@@ -34,10 +30,10 @@ public final class RekindledFlame extends CardImpl {
// At the beginning of your upkeep, if an opponent has no cards in hand, you may return Rekindled Flame from your graveyard to your hand.
Ability ability = new ConditionalInterveningIfTriggeredAbility(
- new BeginningOfUpkeepTriggeredAbility(
- Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), TargetController.YOU, true
- ),
- new OpponentHasNoCardsInHandCondition(), rule);
+ new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), TargetController.YOU, true),
+ OpponentHasNoCardsInHandCondition.instance,
+ "If an opponent has no cards in hand, you may return Rekindled Flame from your graveyard to your hand.");
+ ability.addHint(new ConditionHint(OpponentHasNoCardsInHandCondition.instance, "Opponent has no cards in hand"));
ability.setRuleVisible(true);
this.addAbility(ability);
@@ -51,21 +47,4 @@ public final class RekindledFlame extends CardImpl {
public RekindledFlame copy() {
return new RekindledFlame(this);
}
-}
-
-class OpponentHasNoCardsInHandCondition implements Condition {
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- for (UUID playerId : game.getOpponents(source.getControllerId())) {
- Player opponent = game.getPlayer(playerId);
- if (opponent != null && opponent.getHand().isEmpty()) {
- return true;
- }
- }
- }
- return false;
- }
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/r/RekindlingPhoenix.java b/Mage.Sets/src/mage/cards/r/RekindlingPhoenix.java
index 3eac6457e96..6528f7ae011 100644
--- a/Mage.Sets/src/mage/cards/r/RekindlingPhoenix.java
+++ b/Mage.Sets/src/mage/cards/r/RekindlingPhoenix.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -29,7 +29,7 @@ public final class RekindlingPhoenix extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Rekindling Phoenix dies, create a 0/1 red Elemental creature token with "At the beginning of your upkeep, sacrifice this creature and return target card named Rekindling Phoenix from your graveyard to the battlefield. It gains haste until end of turn."
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new RekindlingPhoenixToken()), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new RekindlingPhoenixToken()), false));
}
public RekindlingPhoenix(final RekindlingPhoenix card) {
diff --git a/Mage.Sets/src/mage/cards/r/ReleaseTheDogs.java b/Mage.Sets/src/mage/cards/r/ReleaseTheDogs.java
new file mode 100644
index 00000000000..6e7e8dc8b94
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/ReleaseTheDogs.java
@@ -0,0 +1,31 @@
+package mage.cards.r;
+
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.game.permanent.token.WhiteDogToken;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ReleaseTheDogs extends CardImpl {
+
+ public ReleaseTheDogs(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}");
+
+ // Create four 1/1 white Dog creature tokens.
+ this.getSpellAbility().addEffect(new CreateTokenEffect(new WhiteDogToken(), 4));
+ }
+
+ private ReleaseTheDogs(final ReleaseTheDogs card) {
+ super(card);
+ }
+
+ @Override
+ public ReleaseTheDogs copy() {
+ return new ReleaseTheDogs(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/ReleaseToTheWind.java b/Mage.Sets/src/mage/cards/r/ReleaseToTheWind.java
index c8a9ebdf8d9..6ee617e186d 100644
--- a/Mage.Sets/src/mage/cards/r/ReleaseToTheWind.java
+++ b/Mage.Sets/src/mage/cards/r/ReleaseToTheWind.java
@@ -4,8 +4,8 @@ package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
-import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -13,7 +13,7 @@ import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.TargetController;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@@ -67,58 +67,7 @@ class ReleaseToTheWindEffect extends OneShotEffect {
if (controller != null) {
Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (targetPermanent != null) {
- if (controller.moveCards(targetPermanent, Zone.EXILED, source, game)) {
- Card card = game.getCard(targetPermanent.getId());
- if (card != null) {
- ContinuousEffect effect = new ReleaseToTheWindEffectCastFromExileEffect();
- effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
- game.addEffect(effect, source);
- }
- }
- }
- return true;
- }
- return false;
- }
-}
-
-class ReleaseToTheWindEffectCastFromExileEffect extends AsThoughEffectImpl {
-
- public ReleaseToTheWindEffectCastFromExileEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
- staticText = "For as long as that card remains exiled, its owner may cast it without paying its mana cost";
- }
-
- public ReleaseToTheWindEffectCastFromExileEffect(final ReleaseToTheWindEffectCastFromExileEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public ReleaseToTheWindEffectCastFromExileEffect copy() {
- return new ReleaseToTheWindEffectCastFromExileEffect(this);
- }
-
- @Override
- public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
- UUID ownerId = game.getOwnerId(objectId);
- if (objectId.equals(getTargetPointer().getFirst(game, source))) {
- if (affectedControllerId.equals(ownerId)) {
- Card card = game.getCard(objectId);
- Player player = game.getPlayer(ownerId);
- if (player != null && card != null) {
- player.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
- return true;
- }
- }
- } else {
- if (((FixedTarget) getTargetPointer()).getTarget().equals(objectId)) {
- // object has moved zone so effect can be discarted
- this.discard();
+ return PlayFromNotOwnHandZoneTargetEffect.exileAndPlayFromExile(game, source, targetPermanent, TargetController.OWNER, Duration.Custom, true);
}
}
return false;
diff --git a/Mage.Sets/src/mage/cards/r/RelentlessDead.java b/Mage.Sets/src/mage/cards/r/RelentlessDead.java
index 063fd464b51..d9567943bab 100644
--- a/Mage.Sets/src/mage/cards/r/RelentlessDead.java
+++ b/Mage.Sets/src/mage/cards/r/RelentlessDead.java
@@ -2,7 +2,7 @@ package mage.cards.r;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DoIfCostPaid;
@@ -37,10 +37,10 @@ public final class RelentlessDead extends CardImpl {
this.addAbility(new MenaceAbility());
// When Relentless Dead dies, you may pay {B}. If you do, return it to its owner's hand.
- this.addAbility(new DiesTriggeredAbility(new DoIfCostPaid(new ReturnToHandSourceEffect(), new ManaCostsImpl("{B}"))));
+ this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new ReturnToHandSourceEffect(), new ManaCostsImpl("{B}"))));
// When Relentless Dead dies, you may pay {X}. If you do, return another target Zombie creature card with converted mana cost X from your graveyard to the battlefield.
- this.addAbility(new DiesTriggeredAbility(new RelentlessDeadEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new RelentlessDeadEffect()));
}
public RelentlessDead(final RelentlessDead card) {
diff --git a/Mage.Sets/src/mage/cards/r/ReliquaryMonk.java b/Mage.Sets/src/mage/cards/r/ReliquaryMonk.java
index 2e3e3ff0449..5b254a277b7 100644
--- a/Mage.Sets/src/mage/cards/r/ReliquaryMonk.java
+++ b/Mage.Sets/src/mage/cards/r/ReliquaryMonk.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -29,7 +29,7 @@ public final class ReliquaryMonk extends CardImpl {
this.toughness = new MageInt(2);
// When Reliquary Monk dies, destroy target artifact or enchantment.
- Ability ability = new DiesTriggeredAbility(new DestroyTargetEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DestroyTargetEffect(), false);
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/r/RequiemAngel.java b/Mage.Sets/src/mage/cards/r/RequiemAngel.java
index 20cfb3f4dbc..0ccb69b287b 100644
--- a/Mage.Sets/src/mage/cards/r/RequiemAngel.java
+++ b/Mage.Sets/src/mage/cards/r/RequiemAngel.java
@@ -1,7 +1,5 @@
-
package mage.cards.r;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@@ -16,8 +14,9 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.permanent.token.SpiritWhiteToken;
+import java.util.UUID;
+
/**
- *
* @author intimidatingant
*/
public final class RequiemAngel extends CardImpl {
@@ -30,7 +29,7 @@ public final class RequiemAngel extends CardImpl {
}
public RequiemAngel(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}");
this.subtype.add(SubType.ANGEL);
this.power = new MageInt(5);
@@ -39,7 +38,7 @@ public final class RequiemAngel extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever another non-Spirit creature you control dies, create a 1/1 white Spirit creature token with flying.
- this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken("ISD"), 1), false, filter));
+ this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken(), 1), false, filter));
}
public RequiemAngel(final RequiemAngel card) {
diff --git a/Mage.Sets/src/mage/cards/r/ResearchDevelopment.java b/Mage.Sets/src/mage/cards/r/ResearchDevelopment.java
index cc9497ea6f3..6bfeeb052f3 100644
--- a/Mage.Sets/src/mage/cards/r/ResearchDevelopment.java
+++ b/Mage.Sets/src/mage/cards/r/ResearchDevelopment.java
@@ -1,28 +1,23 @@
-
package mage.cards.r;
-import java.util.Set;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
-import mage.cards.Card;
-import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
-import mage.cards.SplitCard;
+import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
-import mage.game.permanent.token.ElementalToken;
+import mage.game.permanent.token.ResearchDevelopmentToken;
import mage.players.Player;
import mage.target.TargetCard;
+import java.util.Set;
+import java.util.UUID;
+
/**
- *
* @author magenoxx
*/
public final class ResearchDevelopment extends SplitCard {
@@ -144,7 +139,7 @@ class DevelopmentEffect extends OneShotEffect {
for (UUID opponentUuid : opponents) {
Player opponent = game.getPlayer(opponentUuid);
if (opponent != null && opponent.chooseUse(Outcome.Detriment,
- "Allow " + player.getLogName() + " to draw a card instead? (" + Integer.toString(i + 1) + ')', source, game)) {
+ "Allow " + player.getLogName() + " to draw a card instead? (" + (i + 1) + ')', source, game)) {
game.informPlayers(opponent.getLogName() + " had chosen to let " + player.getLogName() + " draw a card.");
player.drawCards(1, source.getSourceId(), game);
putToken = false;
@@ -152,7 +147,7 @@ class DevelopmentEffect extends OneShotEffect {
}
}
if (putToken) {
- new CreateTokenEffect(new ElementalToken("DIS", 1)).apply(game, source);
+ new CreateTokenEffect(new ResearchDevelopmentToken()).apply(game, source);
}
}
diff --git a/Mage.Sets/src/mage/cards/r/ResoluteWatchdog.java b/Mage.Sets/src/mage/cards/r/ResoluteWatchdog.java
index 80f127f7006..2376752bd1a 100644
--- a/Mage.Sets/src/mage/cards/r/ResoluteWatchdog.java
+++ b/Mage.Sets/src/mage/cards/r/ResoluteWatchdog.java
@@ -25,7 +25,7 @@ public final class ResoluteWatchdog extends CardImpl {
public ResoluteWatchdog(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/r/RestoreBalance.java b/Mage.Sets/src/mage/cards/r/RestoreBalance.java
index dec27da79f1..18a8f979639 100644
--- a/Mage.Sets/src/mage/cards/r/RestoreBalance.java
+++ b/Mage.Sets/src/mage/cards/r/RestoreBalance.java
@@ -1,25 +1,13 @@
-
package mage.cards.r;
-import mage.abilities.Ability;
import mage.abilities.costs.mana.ColoredManaCost;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.BalanceEffect;
import mage.abilities.keyword.SuspendAbility;
-import mage.cards.*;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
-import mage.constants.Outcome;
-import mage.filter.FilterCard;
-import mage.filter.common.FilterControlledCreaturePermanent;
-import mage.filter.common.FilterControlledLandPermanent;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
-import mage.target.common.TargetCardInHand;
-import mage.target.common.TargetControlledPermanent;
-import java.util.HashMap;
-import java.util.Map;
import java.util.UUID;
/**
@@ -35,10 +23,10 @@ public final class RestoreBalance extends CardImpl {
// Suspend 6-{W}
this.addAbility(new SuspendAbility(6, new ColoredManaCost(ColoredManaSymbol.W), this));
// Each player chooses a number of lands they control equal to the number of lands controlled by the player who controls the fewest, then sacrifices the rest. Players sacrifice creatures and discard cards the same way.
- this.getSpellAbility().addEffect(new RestoreBalanceEffect());
+ this.getSpellAbility().addEffect(new BalanceEffect());
}
- public RestoreBalance(final RestoreBalance card) {
+ private RestoreBalance(final RestoreBalance card) {
super(card);
}
@@ -47,137 +35,3 @@ public final class RestoreBalance extends CardImpl {
return new RestoreBalance(this);
}
}
-
-
-class RestoreBalanceEffect extends OneShotEffect {
-
- RestoreBalanceEffect() {
- super(Outcome.Sacrifice);
- staticText = "Each player chooses a number of lands they control equal to the number of lands controlled by the player who controls the fewest, then sacrifices the rest. Players sacrifice creatures and discard cards the same way";
- }
-
- RestoreBalanceEffect(final RestoreBalanceEffect effect) {
- super(effect);
- }
-
- @Override
- public RestoreBalanceEffect copy() {
- return new RestoreBalanceEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- //Lands
- int minLand = Integer.MAX_VALUE;
- Cards landsToSacrifice = new CardsImpl();
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int count = game.getBattlefield().countAll(new FilterControlledLandPermanent(), player.getId(), game);
- if (count < minLand) {
- minLand = count;
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- TargetControlledPermanent target = new TargetControlledPermanent(minLand, minLand, new FilterControlledLandPermanent(), true);
- if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) {
- for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledLandPermanent(), player.getId(), source.getSourceId(), game)) {
- if (permanent != null && !target.getTargets().contains(permanent.getId())) {
- landsToSacrifice.add(permanent);
- }
- }
- }
- }
- }
-
- for (UUID cardId : landsToSacrifice) {
- Permanent permanent = game.getPermanent(cardId);
- if (permanent != null) {
- permanent.sacrifice(source.getSourceId(), game);
- }
- }
-
- //Creatures
- int minCreature = Integer.MAX_VALUE;
- Cards creaturesToSacrifice = new CardsImpl();
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int count = game.getBattlefield().countAll(new FilterControlledCreaturePermanent(), player.getId(), game);
- if (count < minCreature) {
- minCreature = count;
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- TargetControlledPermanent target = new TargetControlledPermanent(minCreature, minCreature, new FilterControlledCreaturePermanent(), true);
- if (target.choose(Outcome.Sacrifice, player.getId(), source.getSourceId(), game)) {
- for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), player.getId(), source.getSourceId(), game)) {
- if (permanent != null && !target.getTargets().contains(permanent.getId())) {
- creaturesToSacrifice.add(permanent);
- }
- }
- }
- }
- }
-
- for (UUID cardId : creaturesToSacrifice) {
- Permanent permanent = game.getPermanent(cardId);
- if (permanent != null) {
- permanent.sacrifice(source.getSourceId(), game);
- }
- }
-
- //Cards in hand
- int minCard = Integer.MAX_VALUE;
- Map cardsToDiscard = new HashMap<>(2);
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- int count = player.getHand().size();
- if (count < minCard) {
- minCard = count;
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null) {
- Cards cards = new CardsImpl();
- TargetCardInHand target = new TargetCardInHand(minCard, new FilterCard());
- if (target.choose(Outcome.Discard, player.getId(), source.getSourceId(), game)) {
- for (Card card : player.getHand().getCards(game)) {
- if (card != null && !target.getTargets().contains(card.getId())) {
- cards.add(card);
- }
- }
- cardsToDiscard.put(playerId, cards);
- }
- }
- }
-
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- Player player = game.getPlayer(playerId);
- if (player != null && cardsToDiscard.get(playerId) != null) {
- for (UUID cardId : cardsToDiscard.get(playerId)) {
- Card card = game.getCard(cardId);
- player.discard(card, source, game);
-
- }
- }
- }
- return true;
- }
- return false;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/r/Retaliation.java b/Mage.Sets/src/mage/cards/r/Retaliation.java
index 21e41b00574..87b2954d07d 100644
--- a/Mage.Sets/src/mage/cards/r/Retaliation.java
+++ b/Mage.Sets/src/mage/cards/r/Retaliation.java
@@ -1,9 +1,9 @@
-
package mage.cards.r;
import java.util.UUID;
import mage.abilities.common.BecomesBlockedByCreatureTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.cards.CardImpl;
@@ -20,12 +20,20 @@ import mage.filter.StaticFilters;
public final class Retaliation extends CardImpl {
public Retaliation(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
- // Creatures you control have "Whenever this creature becomes blocked by a creature, this creature gets +1/+1 until end of turn."
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
- new GainAbilityControlledEffect(new BecomesBlockedByCreatureTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), false),
- Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES)));
+ // Creatures you control have "Whenever this creature becomes blocked by a creature,
+ // this creature gets +1/+1 until end of turn."
+ Effect effect = new GainAbilityControlledEffect(
+ new BecomesBlockedByCreatureTriggeredAbility(
+ new BoostSourceEffect(
+ 1, 1,
+ Duration.EndOfTurn), false),
+ Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES);
+ effect.setText("Creatures you control have \"Whenever this creature becomes blocked by a creature, "
+ + "this creature gets +1/+1 until end of turn.");
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ effect));
}
public Retaliation(final Retaliation card) {
diff --git a/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java b/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java
index f6decd52d66..6a3f7ce162a 100644
--- a/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java
+++ b/Mage.Sets/src/mage/cards/r/ReturnFromExtinction.java
@@ -88,7 +88,7 @@ class ReturnFromExtinctionTarget extends TargetCardInYourGraveyard {
return false;
}
for (Card card : player.getGraveyard().getCards(filter, sourceId, sourceControllerId, game)) {
- if (card.isAllCreatureTypes() || card.getAbilities(game).contains(ChangelingAbility.getInstance())) {
+ if (card.isAllCreatureTypes() || card.hasAbility(ChangelingAbility.getInstance(), game)) {
if (!subTypes.isEmpty()) {
return true;
} else {
diff --git a/Mage.Sets/src/mage/cards/r/ReturnedReveler.java b/Mage.Sets/src/mage/cards/r/ReturnedReveler.java
index e0a10efc985..34a34083ae9 100644
--- a/Mage.Sets/src/mage/cards/r/ReturnedReveler.java
+++ b/Mage.Sets/src/mage/cards/r/ReturnedReveler.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class ReturnedReveler extends CardImpl {
this.toughness = new MageInt(3);
// When Returned Reveler dies, each player puts the top three cards of their library into their graveyard.
- this.addAbility(new DiesTriggeredAbility(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(3, TargetController.ANY)));
+ this.addAbility(new DiesSourceTriggeredAbility(new PutTopCardOfLibraryIntoGraveEachPlayerEffect(3, TargetController.ANY)));
}
public ReturnedReveler(final ReturnedReveler card) {
diff --git a/Mage.Sets/src/mage/cards/r/RevelInRiches.java b/Mage.Sets/src/mage/cards/r/RevelInRiches.java
index b1011b4465d..ca8bf841b2d 100644
--- a/Mage.Sets/src/mage/cards/r/RevelInRiches.java
+++ b/Mage.Sets/src/mage/cards/r/RevelInRiches.java
@@ -1,7 +1,5 @@
-
package mage.cards.r;
-import java.util.UUID;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.DiesCreatureTriggeredAbility;
@@ -19,8 +17,9 @@ import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.permanent.token.TreasureToken;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class RevelInRiches extends CardImpl {
@@ -37,7 +36,7 @@ public final class RevelInRiches extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{B}");
// Whenever a creature an opponent controls dies, create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color."
- this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new TreasureToken("XLN")), false, filter));
+ this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new TreasureToken()), false, filter));
// At the beginning of your upkeep, if you control ten or more Treasures, you win the game.
TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect(), TargetController.YOU, false);
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
diff --git a/Mage.Sets/src/mage/cards/r/Riddlekeeper.java b/Mage.Sets/src/mage/cards/r/Riddlekeeper.java
index 2310fa20ee5..d6d08f9799d 100644
--- a/Mage.Sets/src/mage/cards/r/Riddlekeeper.java
+++ b/Mage.Sets/src/mage/cards/r/Riddlekeeper.java
@@ -28,7 +28,7 @@ public final class Riddlekeeper extends CardImpl {
// Whenever a creature attacks you or a planeswalker you control, that creature's controller puts the top two cards of their library into their graveyard.
Effect effect = new PutTopCardOfLibraryIntoGraveTargetEffect(2);
- effect.setText("that creature's controller puts the top two cards of their library into their graveyard");
+ effect.setText("that creature's controller mills two cards");
this.addAbility(new AttacksAllTriggeredAbility(effect, false, StaticFilters.FILTER_PERMANENT_CREATURE, SetTargetPointer.PLAYER, true, true));
}
diff --git a/Mage.Sets/src/mage/cards/r/RielleTheEverwise.java b/Mage.Sets/src/mage/cards/r/RielleTheEverwise.java
index 17b4eb219e4..58c90e1f7c4 100644
--- a/Mage.Sets/src/mage/cards/r/RielleTheEverwise.java
+++ b/Mage.Sets/src/mage/cards/r/RielleTheEverwise.java
@@ -99,7 +99,7 @@ class RielleTheEverwiseTriggeredAbility extends TriggeredAbilityImpl {
class RielleTheEverwiseWatcher extends Watcher {
- private final Map discardedThisTurn = new HashMap();
+ private final Map discardedThisTurn = new HashMap<>();
RielleTheEverwiseWatcher() {
super(WatcherScope.GAME);
@@ -107,8 +107,9 @@ class RielleTheEverwiseWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
- if (event.getAmount() > 0) {
- discardedThisTurn.compute(event.getPlayerId(), (u, i) -> i == null ? 1 : i + 1);
+ if (event.getType() == GameEvent.EventType.DISCARDED_CARDS
+ && event.getAmount() > 0) {
+ discardedThisTurn.merge(event.getPlayerId(), 1, Integer::sum);
}
}
diff --git a/Mage.Sets/src/mage/cards/r/RinAndSeriInseparable.java b/Mage.Sets/src/mage/cards/r/RinAndSeriInseparable.java
new file mode 100644
index 00000000000..10266f3289d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/RinAndSeriInseparable.java
@@ -0,0 +1,92 @@
+package mage.cards.r;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SpellCastControllerTriggeredAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.hint.ValueHint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.filter.FilterPermanent;
+import mage.filter.FilterSpell;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.game.permanent.token.GreenCatToken;
+import mage.game.permanent.token.WhiteDogToken;
+import mage.target.common.TargetAnyTarget;
+
+import java.util.UUID;
+
+/**
+ * @author htrajan
+ */
+public final class RinAndSeriInseparable extends CardImpl {
+
+ private static final FilterSpell dogSpellFilter = new FilterSpell("a Dog spell");
+ private static final FilterSpell catSpellFilter = new FilterSpell("a Cat spell");
+
+ private static final FilterPermanent dogPermanentFilter = new FilterControlledCreaturePermanent("Dogs you control");
+ private static final FilterPermanent catPermanentFilter = new FilterControlledCreaturePermanent("Cats you control");
+
+ static {
+ dogSpellFilter.add(SubType.DOG.getPredicate());
+ catSpellFilter.add(SubType.CAT.getPredicate());
+
+ dogPermanentFilter.add(SubType.DOG.getPredicate());
+ catPermanentFilter.add(SubType.CAT.getPredicate());
+ }
+
+ public RinAndSeriInseparable(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}{W}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.DOG);
+ this.subtype.add(SubType.CAT);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(4);
+
+ // Whenever you cast a Dog spell, create a 1/1 green Cat creature token.
+ this.addAbility(new SpellCastControllerTriggeredAbility(
+ new CreateTokenEffect(new GreenCatToken()), dogSpellFilter, false
+ ));
+
+ // Whenever you cast a Cat spell, create a 1/1 white Dog creature token.
+ this.addAbility(new SpellCastControllerTriggeredAbility(
+ new CreateTokenEffect(new WhiteDogToken()), catSpellFilter, false
+ ));
+
+ // {R}{G}{W}, {T}: Rin and Seri, Inseparable deals damage to any target equal to the number of Dogs you control. You gain life equal to the number of Cats you control.
+ DynamicValue dogCount = new PermanentsOnBattlefieldCount(dogPermanentFilter);
+ Effect damageEffect = new DamageTargetEffect(dogCount);
+ damageEffect.setText("{source} deals damage to any target equal to the number of Dogs you control");
+ DynamicValue catCount = new PermanentsOnBattlefieldCount(catPermanentFilter);
+ Effect lifeGainEffect = new GainLifeEffect(catCount);
+ lifeGainEffect.setText("You gain life equal to the number of Cats you control");
+ Ability ability = new SimpleActivatedAbility(damageEffect, new ManaCostsImpl("{R}{G}{W}"));
+ ability.addEffect(lifeGainEffect);
+ ability.addCost(new TapSourceCost());
+ ability.addTarget(new TargetAnyTarget());
+ ability.addHint(new ValueHint("Dogs you control", dogCount));
+ ability.addHint(new ValueHint("Cats you control", catCount));
+ this.addAbility(ability);
+ }
+
+ private RinAndSeriInseparable(final RinAndSeriInseparable card) {
+ super(card);
+ }
+
+ @Override
+ public RinAndSeriInseparable copy() {
+ return new RinAndSeriInseparable(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/RiptideCrab.java b/Mage.Sets/src/mage/cards/r/RiptideCrab.java
index c0ce13fec5a..2bfcc369a58 100644
--- a/Mage.Sets/src/mage/cards/r/RiptideCrab.java
+++ b/Mage.Sets/src/mage/cards/r/RiptideCrab.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class RiptideCrab extends CardImpl {
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// When Riptide Crab dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public RiptideCrab(final RiptideCrab card) {
diff --git a/Mage.Sets/src/mage/cards/r/RiseAgain.java b/Mage.Sets/src/mage/cards/r/RiseAgain.java
new file mode 100644
index 00000000000..a87bc573962
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/RiseAgain.java
@@ -0,0 +1,33 @@
+package mage.cards.r;
+
+import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.filter.StaticFilters;
+import mage.target.common.TargetCardInYourGraveyard;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class RiseAgain extends CardImpl {
+
+ public RiseAgain(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}");
+
+ // Return target creature card from your graveyard to the battlefield.
+ this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect());
+ this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD));
+ }
+
+ private RiseAgain(final RiseAgain card) {
+ super(card);
+ }
+
+ @Override
+ public RiseAgain copy() {
+ return new RiseAgain(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/RiseFall.java b/Mage.Sets/src/mage/cards/r/RiseFall.java
index b3042b99025..f345dce851e 100644
--- a/Mage.Sets/src/mage/cards/r/RiseFall.java
+++ b/Mage.Sets/src/mage/cards/r/RiseFall.java
@@ -1,19 +1,15 @@
-
package mage.cards.r;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
-import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
-import mage.cards.SplitCard;
+import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
+import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.game.permanent.Permanent;
@@ -22,19 +18,22 @@ import mage.target.TargetPlayer;
import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class RiseFall extends SplitCard {
+ private static final FilterCard filter = new FilterCreatureCard("creature card from a graveyard");
+
public RiseFall(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{B}", "{B}{R}", SpellAbilityType.SPLIT);
// Rise
// Return target creature card from a graveyard and target creature on the battlefield to their owners' hands.
getLeftHalfCard().getSpellAbility().addEffect(new RiseEffect());
- getLeftHalfCard().getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard")));
+ getLeftHalfCard().getSpellAbility().addTarget(new TargetCardInGraveyard(filter));
getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent());
// Fall
@@ -43,7 +42,7 @@ public final class RiseFall extends SplitCard {
getRightHalfCard().getSpellAbility().addTarget(new TargetPlayer());
}
- public RiseFall(final RiseFall card) {
+ private RiseFall(final RiseFall card) {
super(card);
}
@@ -55,12 +54,12 @@ public final class RiseFall extends SplitCard {
class RiseEffect extends OneShotEffect {
- public RiseEffect() {
+ RiseEffect() {
super(Outcome.ReturnToHand);
this.staticText = "Return target creature card from a graveyard and target creature on the battlefield to their owners' hands";
}
- public RiseEffect(final RiseEffect effect) {
+ private RiseEffect(final RiseEffect effect) {
super(effect);
}
@@ -72,31 +71,31 @@ class RiseEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Cards cardsToHand = new CardsImpl();
- Card cardInGraveyard = game.getCard(getTargetPointer().getFirst(game, source));
- if (cardInGraveyard != null) {
- cardsToHand.add(cardInGraveyard);
- }
- Permanent permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
- if (permanent != null) {
- cardsToHand.add(permanent);
- }
- controller.moveCards(cardsToHand, Zone.HAND, source, game);
- return true;
+ if (controller == null) {
+ return false;
}
- return false;
+ Cards cardsToHand = new CardsImpl();
+ Card cardInGraveyard = game.getCard(getTargetPointer().getFirst(game, source));
+ if (cardInGraveyard != null) {
+ cardsToHand.add(cardInGraveyard);
+ }
+ Permanent permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
+ if (permanent != null) {
+ cardsToHand.add(permanent);
+ }
+ controller.moveCards(cardsToHand, Zone.HAND, source, game);
+ return true;
}
}
class FallEffect extends OneShotEffect {
- public FallEffect() {
+ FallEffect() {
super(Outcome.Discard);
this.staticText = "Target player reveals two cards at random from their hand, then discards each nonland card revealed this way";
}
- public FallEffect(final FallEffect effect) {
+ private FallEffect(final FallEffect effect) {
super(effect);
}
@@ -109,34 +108,32 @@ class FallEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
- if (controller != null) {
- Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
- if (targetPlayer != null) {
- if (!targetPlayer.getHand().isEmpty()) {
- Card card = targetPlayer.getHand().getRandom(game);
- if (card == null) {
- return false;
- }
- Cards cards = new CardsImpl(card);
- if (targetPlayer.getHand().size() > 1) {
- do {
- card = targetPlayer.getHand().getRandom(game);
- if (card == null) {
- return false;
- }
- } while (cards.contains(card.getId()));
- cards.add(card);
- }
- targetPlayer.revealCards(sourceObject.getIdName(), cards, game);
- for (Card cardToDiscard : cards.getCards(game)) {
- if (!cardToDiscard.isLand()) {
- targetPlayer.discard(cardToDiscard, source, game);
- }
- }
- }
- }
+ if (controller == null) {
+ return false;
+ }
+ Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
+ if (targetPlayer == null) {
return true;
}
- return false;
+ if (targetPlayer.getHand().isEmpty()) {
+ return true;
+ }
+ Card card = targetPlayer.getHand().getRandom(game);
+ if (card == null) {
+ return false;
+ }
+ Cards cards = new CardsImpl(card);
+ if (targetPlayer.getHand().size() > 1) {
+ do {
+ card = targetPlayer.getHand().getRandom(game);
+ if (card == null) {
+ return false;
+ }
+ } while (cards.contains(card.getId()));
+ cards.add(card);
+ }
+ targetPlayer.revealCards(sourceObject.getIdName(), cards, game);
+ targetPlayer.discard(new CardsImpl(cards.getCards(StaticFilters.FILTER_CARD_NON_LAND, game)), source, game);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/r/RisenReef.java b/Mage.Sets/src/mage/cards/r/RisenReef.java
index 71c38de59ae..8b58944b897 100644
--- a/Mage.Sets/src/mage/cards/r/RisenReef.java
+++ b/Mage.Sets/src/mage/cards/r/RisenReef.java
@@ -2,7 +2,7 @@ package mage.cards.r;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
@@ -22,8 +22,7 @@ import java.util.UUID;
*/
public final class RisenReef extends CardImpl {
- private static final FilterPermanent filter
- = new FilterPermanent(SubType.ELEMENTAL, "{this} or another Elemental");
+ private static final FilterPermanent filter = new FilterPermanent(SubType.ELEMENTAL, "Elemental");
public RisenReef(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}");
@@ -33,7 +32,9 @@ public final class RisenReef extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Risen Reef or another Elemental enters the battlefield under your control, look at the top card of your library. If it's a land card, you may put it onto the battlefield tapped. If you don't put the card onto the battlefield, put it into your hand.
- this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new RisenReefEffect(), filter));
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new RisenReefEffect(), filter, false, true
+ ));
}
private RisenReef(final RisenReef card) {
@@ -85,4 +86,4 @@ class RisenReefEffect extends OneShotEffect {
}
return true;
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/r/RitesOfSpring.java b/Mage.Sets/src/mage/cards/r/RitesOfSpring.java
index 76dfca48a10..3991d3acd3c 100644
--- a/Mage.Sets/src/mage/cards/r/RitesOfSpring.java
+++ b/Mage.Sets/src/mage/cards/r/RitesOfSpring.java
@@ -1,25 +1,23 @@
-
package mage.cards.r;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
-import mage.target.Target;
-import mage.target.common.TargetCardInHand;
+import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
+import mage.target.common.TargetDiscard;
+
+import java.util.UUID;
/**
- *
* @author LevelX2
*/
public final class RitesOfSpring extends CardImpl {
@@ -31,7 +29,7 @@ public final class RitesOfSpring extends CardImpl {
getSpellAbility().addEffect(new RitesOfSpringEffect());
}
- public RitesOfSpring(final RitesOfSpring card) {
+ private RitesOfSpring(final RitesOfSpring card) {
super(card);
}
@@ -43,12 +41,13 @@ public final class RitesOfSpring extends CardImpl {
class RitesOfSpringEffect extends OneShotEffect {
- public RitesOfSpringEffect() {
+ RitesOfSpringEffect() {
super(Outcome.DrawCard);
- this.staticText = "Discard any number of cards. Search your library for up to that many basic land cards, reveal those cards, and put them into your hand. Then shuffle your library.";
+ this.staticText = "Discard any number of cards. Search your library for up to that many basic land cards, " +
+ "reveal those cards, and put them into your hand. Then shuffle your library.";
}
- public RitesOfSpringEffect(final RitesOfSpringEffect effect) {
+ private RitesOfSpringEffect(final RitesOfSpringEffect effect) {
super(effect);
}
@@ -60,23 +59,15 @@ class RitesOfSpringEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Target target = new TargetCardInHand(0, Integer.MAX_VALUE, new FilterCard("cards to discard"));
- while (controller.canRespond() && !target.isChosen()) {
- target.choose(Outcome.BoostCreature, controller.getId(), source.getSourceId(), game);
- }
- int numDiscarded = 0;
- for (UUID targetId : target.getTargets()) {
- Card card = controller.getHand().get(targetId, game);
- if (controller.discard(card, source, game)) {
- numDiscarded++;
- }
- }
- game.applyEffects();
- return new SearchLibraryPutInHandEffect(
- new TargetCardInLibrary(0, numDiscarded, StaticFilters.FILTER_CARD_BASIC_LAND), true, true)
- .apply(game, source);
+ if (controller == null) {
+ return false;
}
- return false;
+ TargetCard target = new TargetDiscard(0, Integer.MAX_VALUE, StaticFilters.FILTER_CARD, controller.getId());
+ controller.choose(Outcome.AIDontUseIt, controller.getHand(), target, game);
+ int numDiscarded = controller.discard(new CardsImpl(target.getTargets()), source, game).size();
+ new SearchLibraryPutInHandEffect(new TargetCardInLibrary(
+ 0, numDiscarded, StaticFilters.FILTER_CARD_BASIC_LAND
+ ), true, true).apply(game, source);
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/r/RoaleskApexHybrid.java b/Mage.Sets/src/mage/cards/r/RoaleskApexHybrid.java
index 6c77689b4a1..29cd3f704ae 100644
--- a/Mage.Sets/src/mage/cards/r/RoaleskApexHybrid.java
+++ b/Mage.Sets/src/mage/cards/r/RoaleskApexHybrid.java
@@ -2,7 +2,7 @@ package mage.cards.r;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.effects.common.counter.ProliferateEffect;
@@ -56,7 +56,7 @@ public final class RoaleskApexHybrid extends CardImpl {
this.addAbility(ability);
// When Roalsk dies, proliferate, then proliferate again. (Choose any number of permanents and/or players, then give each another counter of each kind already there. Then do it again.)
- ability = new DiesTriggeredAbility(new ProliferateEffect(false));
+ ability = new DiesSourceTriggeredAbility(new ProliferateEffect(false));
ability.addEffect(new ProliferateEffect(" again", true).concatBy(", then"));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/r/RoamingGhostlight.java b/Mage.Sets/src/mage/cards/r/RoamingGhostlight.java
new file mode 100644
index 00000000000..75f7bf1158f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/RoamingGhostlight.java
@@ -0,0 +1,54 @@
+package mage.cards.r;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.ReturnToHandTargetEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.Predicates;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class RoamingGhostlight extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterCreaturePermanent("non-Spirit creature");
+
+ static {
+ filter.add(Predicates.not(SubType.SPIRIT.getPredicate()));
+ }
+
+ public RoamingGhostlight(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
+
+ this.subtype.add(SubType.SPIRIT);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(2);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // When Roaming Ghostlight enters the battlefield, return up to one target non-Spirit creature to its owner's hand.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect());
+ ability.addTarget(new TargetPermanent(0, 1, filter, false));
+ this.addAbility(ability);
+ }
+
+ private RoamingGhostlight(final RoamingGhostlight card) {
+ super(card);
+ }
+
+ @Override
+ public RoamingGhostlight copy() {
+ return new RoamingGhostlight(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/RocEgg.java b/Mage.Sets/src/mage/cards/r/RocEgg.java
index 126df90a82a..e5e5797ee9b 100644
--- a/Mage.Sets/src/mage/cards/r/RocEgg.java
+++ b/Mage.Sets/src/mage/cards/r/RocEgg.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class RocEgg extends CardImpl {
this.toughness = new MageInt(3);
this.addAbility(DefenderAbility.getInstance());
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(rocEggToken, 1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(rocEggToken, 1), false));
}
public RocEgg(final RocEgg card) {
diff --git a/Mage.Sets/src/mage/cards/r/RockBasilisk.java b/Mage.Sets/src/mage/cards/r/RockBasilisk.java
index 6fef87b86ba..43581603bca 100644
--- a/Mage.Sets/src/mage/cards/r/RockBasilisk.java
+++ b/Mage.Sets/src/mage/cards/r/RockBasilisk.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -38,7 +38,7 @@ public final class RockBasilisk extends CardImpl {
Effect effect = new CreateDelayedTriggeredAbilityEffect(
new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true);
effect.setText("destroy that creature at end of combat");
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, filter, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, filter, false));
}
public RockBasilisk(final RockBasilisk card) {
diff --git a/Mage.Sets/src/mage/cards/r/RoilElemental.java b/Mage.Sets/src/mage/cards/r/RoilElemental.java
index 4a2b3c44c5c..a4e01d142ee 100644
--- a/Mage.Sets/src/mage/cards/r/RoilElemental.java
+++ b/Mage.Sets/src/mage/cards/r/RoilElemental.java
@@ -1,4 +1,3 @@
-
package mage.cards.r;
import java.util.UUID;
@@ -13,6 +12,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.target.common.TargetCreaturePermanent;
+import mage.watchers.common.LostControlWatcher;
/**
*
@@ -36,6 +36,7 @@ public final class RoilElemental extends CardImpl {
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new GainControlTargetEffect(Duration.Custom), new SourceOnBattlefieldControlUnchangedCondition(), rule);
Ability ability = new LandfallAbility(Zone.BATTLEFIELD, effect, true);
ability.addTarget(new TargetCreaturePermanent());
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/r/RookieMistake.java b/Mage.Sets/src/mage/cards/r/RookieMistake.java
new file mode 100644
index 00000000000..9946d80a52f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/RookieMistake.java
@@ -0,0 +1,80 @@
+package mage.cards.r;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.BoostTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetCreaturePermanent;
+import mage.target.targetpointer.FixedTarget;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class RookieMistake extends CardImpl {
+
+ public RookieMistake(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}");
+
+ // Until end of turn, target creature gets +0/+2 and another target creature gets -2/-0.
+ this.getSpellAbility().addEffect(new RookieMistakeEffect());
+ TargetPermanent target = new TargetCreaturePermanent();
+ target.setTargetTag(1);
+ this.getSpellAbility().addTarget(target.withChooseHint("+0/+2"));
+ target = new TargetCreaturePermanent();
+ target.setTargetTag(2);
+ this.getSpellAbility().addTarget(target.withChooseHint("-2/-0"));
+ }
+
+ private RookieMistake(final RookieMistake card) {
+ super(card);
+ }
+
+ @Override
+ public RookieMistake copy() {
+ return new RookieMistake(this);
+ }
+}
+
+class RookieMistakeEffect extends OneShotEffect {
+
+ RookieMistakeEffect() {
+ super(Outcome.BoostCreature);
+ this.staticText = "until end of turn, target creature gets +0/+2 and another target creature gets -2/-0";
+ }
+
+ private RookieMistakeEffect(final RookieMistakeEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public RookieMistakeEffect copy() {
+ return new RookieMistakeEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanent(source.getFirstTarget());
+ if (permanent != null) {
+ ContinuousEffect effect = new BoostTargetEffect(0, 2, Duration.EndOfTurn);
+ effect.setTargetPointer(new FixedTarget(permanent, game));
+ game.addEffect(effect, source);
+ }
+ permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
+ if (permanent != null) {
+ ContinuousEffect effect = new BoostTargetEffect(-2, 0, Duration.EndOfTurn);
+ effect.setTargetPointer(new FixedTarget(permanent, game));
+ game.addEffect(effect, source);
+ }
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/RootingKavu.java b/Mage.Sets/src/mage/cards/r/RootingKavu.java
index 7e0fc263db1..8e34a334943 100644
--- a/Mage.Sets/src/mage/cards/r/RootingKavu.java
+++ b/Mage.Sets/src/mage/cards/r/RootingKavu.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DoIfCostPaid;
@@ -31,7 +31,7 @@ public final class RootingKavu extends CardImpl {
this.toughness = new MageInt(3);
// When Rooting Kavu dies, you may exile it. If you do, shuffle all creature cards from your graveyard into your library.
- this.addAbility(new DiesTriggeredAbility(new DoIfCostPaid(new RootingKavuEffect(), new ExileSourceFromGraveCost())));
+ this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new RootingKavuEffect(), new ExileSourceFromGraveCost())));
}
public RootingKavu(final RootingKavu card) {
diff --git a/Mage.Sets/src/mage/cards/r/RotcrownGhoul.java b/Mage.Sets/src/mage/cards/r/RotcrownGhoul.java
index bb979190f92..5591fd73a1c 100644
--- a/Mage.Sets/src/mage/cards/r/RotcrownGhoul.java
+++ b/Mage.Sets/src/mage/cards/r/RotcrownGhoul.java
@@ -4,7 +4,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class RotcrownGhoul extends CardImpl {
this.toughness = new MageInt(3);
// When Rotcrown Ghoul dies, target player puts the top five cards of their library into their graveyard.
- Ability ability = new DiesTriggeredAbility(new PutLibraryIntoGraveTargetEffect(5));
+ Ability ability = new DiesSourceTriggeredAbility(new PutLibraryIntoGraveTargetEffect(5));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/r/RottenheartGhoul.java b/Mage.Sets/src/mage/cards/r/RottenheartGhoul.java
index a3ae6504fac..8a71bd7a30a 100644
--- a/Mage.Sets/src/mage/cards/r/RottenheartGhoul.java
+++ b/Mage.Sets/src/mage/cards/r/RottenheartGhoul.java
@@ -4,7 +4,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.discard.DiscardTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class RottenheartGhoul extends CardImpl {
this.toughness = new MageInt(4);
// When Rottenheart Ghoul dies, target player discards a card.
- Ability ability = new DiesTriggeredAbility(new DiscardTargetEffect(1));
+ Ability ability = new DiesSourceTriggeredAbility(new DiscardTargetEffect(1));
ability.addTarget(new TargetPlayer());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/r/RousingRead.java b/Mage.Sets/src/mage/cards/r/RousingRead.java
new file mode 100644
index 00000000000..80646faf206
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/RousingRead.java
@@ -0,0 +1,58 @@
+package mage.cards.r;
+
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.common.AttachEffect;
+import mage.abilities.effects.common.DrawDiscardControllerEffect;
+import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
+import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
+import mage.abilities.keyword.EnchantAbility;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class RousingRead extends CardImpl {
+
+ public RousingRead(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
+
+ this.subtype.add(SubType.AURA);
+
+ // Enchant creature
+ TargetPermanent auraTarget = new TargetCreaturePermanent();
+ this.getSpellAbility().addTarget(auraTarget);
+ this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
+ Ability ability = new EnchantAbility(auraTarget.getTargetName());
+ this.addAbility(ability);
+
+ // When Rousing Read enters the battlefield, draw two cards, then discard a card.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(
+ new DrawDiscardControllerEffect(2, 1)
+ ));
+
+ // Enchanted creature gets +1/+1 and has flying.
+ ability = new SimpleStaticAbility(new BoostEnchantedEffect(1, 1, Duration.WhileOnBattlefield));
+ ability.addEffect(new GainAbilityAttachedEffect(
+ FlyingAbility.getInstance(), AttachmentType.AURA
+ ).setText("and has flying"));
+ this.addAbility(ability);
+ }
+
+ private RousingRead(final RousingRead card) {
+ super(card);
+ }
+
+ @Override
+ public RousingRead copy() {
+ return new RousingRead(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/RubyLeech.java b/Mage.Sets/src/mage/cards/r/RubyLeech.java
index 13638d55dad..ba11fe901b3 100644
--- a/Mage.Sets/src/mage/cards/r/RubyLeech.java
+++ b/Mage.Sets/src/mage/cards/r/RubyLeech.java
@@ -1,23 +1,23 @@
-
package mage.cards.r;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementControllerEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author LoneFox
*/
public final class RubyLeech extends CardImpl {
@@ -29,7 +29,7 @@ public final class RubyLeech extends CardImpl {
}
public RubyLeech(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.LEECH);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
@@ -38,7 +38,7 @@ public final class RubyLeech extends CardImpl {
this.addAbility(FirstStrikeAbility.getInstance());
// Red spells you cast cost {R} more to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
- new SpellsCostIncreasementControllerEffect(filter, new ManaCostsImpl("{R}"))));
+ new SpellsCostIncreasingAllEffect(new ManaCostsImpl("{R}"), filter, TargetController.YOU)));
}
public RubyLeech(final RubyLeech card) {
diff --git a/Mage.Sets/src/mage/cards/r/RuinRat.java b/Mage.Sets/src/mage/cards/r/RuinRat.java
index 513b1372190..86ce487b074 100644
--- a/Mage.Sets/src/mage/cards/r/RuinRat.java
+++ b/Mage.Sets/src/mage/cards/r/RuinRat.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.cards.CardImpl;
@@ -30,7 +30,7 @@ public final class RuinRat extends CardImpl {
this.addAbility(DeathtouchAbility.getInstance());
// When Ruin Rat dies, exile target card from an opponent's graveyard.
- DiesTriggeredAbility ability = new DiesTriggeredAbility(new ExileTargetEffect());
+ DiesSourceTriggeredAbility ability = new DiesSourceTriggeredAbility(new ExileTargetEffect());
ability.addTarget(new TargetCardInOpponentsGraveyard(new FilterCard("card from an opponent's graveyard")));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/r/RuinationRioter.java b/Mage.Sets/src/mage/cards/r/RuinationRioter.java
index dace98732cc..00af5f37cf5 100644
--- a/Mage.Sets/src/mage/cards/r/RuinationRioter.java
+++ b/Mage.Sets/src/mage/cards/r/RuinationRioter.java
@@ -2,7 +2,7 @@ package mage.cards.r;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -31,7 +31,7 @@ public final class RuinationRioter extends CardImpl {
this.toughness = new MageInt(2);
// When Ruination Rioter dies, you may have it deal damage to any target equal to the number of land cards in your graveyard.
- Ability ability = new DiesTriggeredAbility(
+ Ability ability = new DiesSourceTriggeredAbility(
new DamageTargetEffect(xValue).setText("you may have it deal damage to any target " +
"equal to the number of land cards in your graveyard."), true
);
diff --git a/Mage.Sets/src/mage/cards/r/RukhEgg.java b/Mage.Sets/src/mage/cards/r/RukhEgg.java
index 6cb6036d6ea..7889f9206f4 100644
--- a/Mage.Sets/src/mage/cards/r/RukhEgg.java
+++ b/Mage.Sets/src/mage/cards/r/RukhEgg.java
@@ -4,7 +4,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -31,7 +31,7 @@ public final class RukhEgg extends CardImpl {
// When Rukh Egg dies, create a 4/4 red Bird creature token with flying at the beginning of the next end step.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new CreateTokenEffect(new RukhEggBirdToken())));
effect.setText("create a 4/4 red Bird creature token with flying at the beginning of the next end step");
- Ability ability = new DiesTriggeredAbility(effect);
+ Ability ability = new DiesSourceTriggeredAbility(effect);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/r/RunAfoul.java b/Mage.Sets/src/mage/cards/r/RunAfoul.java
new file mode 100644
index 00000000000..db304c47c40
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/r/RunAfoul.java
@@ -0,0 +1,41 @@
+package mage.cards.r;
+
+import java.util.UUID;
+
+import mage.abilities.effects.common.SacrificeEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+import mage.target.common.TargetOpponent;
+
+/**
+ * @author arcox
+ */
+public final class RunAfoul extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with flying");
+
+ static {
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ }
+
+ public RunAfoul(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}");
+
+ // Target opponent sacrifices a creature with flying.
+ this.getSpellAbility().addEffect(new SacrificeEffect(filter, 1, "Target opponent"));
+ this.getSpellAbility().addTarget(new TargetOpponent());
+ }
+
+ public RunAfoul(final RunAfoul card) {
+ super(card);
+ }
+
+ @Override
+ public RunAfoul copy() {
+ return new RunAfoul(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/r/RunedHalo.java b/Mage.Sets/src/mage/cards/r/RunedHalo.java
index 3800320f377..50861691d1c 100644
--- a/Mage.Sets/src/mage/cards/r/RunedHalo.java
+++ b/Mage.Sets/src/mage/cards/r/RunedHalo.java
@@ -57,7 +57,7 @@ class RunedHaloSetProtectionEffect extends OneShotEffect {
public RunedHaloSetProtectionEffect() {
super(Outcome.Protect);
- staticText = "
You have protection from the chosen name (You can't be targeted, dealt damage, or enchanted by anything with that name.)";
+ staticText = "
You have protection from the chosen card name (You can't be targeted, dealt damage, or enchanted by anything with that name.)";
}
public RunedHaloSetProtectionEffect(final RunedHaloSetProtectionEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/r/RunedServitor.java b/Mage.Sets/src/mage/cards/r/RunedServitor.java
index 80651aab251..0f8e979d4ad 100644
--- a/Mage.Sets/src/mage/cards/r/RunedServitor.java
+++ b/Mage.Sets/src/mage/cards/r/RunedServitor.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -21,7 +21,7 @@ public final class RunedServitor extends CardImpl {
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
- this.addAbility(new DiesTriggeredAbility(new DrawCardAllEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardAllEffect(1), false));
}
public RunedServitor(final RunedServitor card) {
diff --git a/Mage.Sets/src/mage/cards/r/Runewing.java b/Mage.Sets/src/mage/cards/r/Runewing.java
index 4532e36b6d9..f5a329d2bcb 100644
--- a/Mage.Sets/src/mage/cards/r/Runewing.java
+++ b/Mage.Sets/src/mage/cards/r/Runewing.java
@@ -3,7 +3,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility;
@@ -37,7 +37,7 @@ public final class Runewing extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Runewing dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
}
public Runewing(final Runewing card) {
diff --git a/Mage.Sets/src/mage/cards/r/RushingTideZubera.java b/Mage.Sets/src/mage/cards/r/RushingTideZubera.java
index f80c8015a46..fb8920811be 100644
--- a/Mage.Sets/src/mage/cards/r/RushingTideZubera.java
+++ b/Mage.Sets/src/mage/cards/r/RushingTideZubera.java
@@ -4,7 +4,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
@@ -31,7 +31,7 @@ public final class RushingTideZubera extends CardImpl {
this.toughness = new MageInt(3);
// When Rushing-Tide Zubera dies, if 4 or more damage was dealt to it this turn, draw three cards.
- Ability ability = new ConditionalInterveningIfTriggeredAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(3)), new RushingTideZuberaCondition(),
+ Ability ability = new ConditionalInterveningIfTriggeredAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(3)), new RushingTideZuberaCondition(),
"When {this} dies, if 4 or more damage was dealt to it this turn, draw three cards.");
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/r/RyuseiTheFallingStar.java b/Mage.Sets/src/mage/cards/r/RyuseiTheFallingStar.java
index 08a62c7fd6f..58b9630ef62 100644
--- a/Mage.Sets/src/mage/cards/r/RyuseiTheFallingStar.java
+++ b/Mage.Sets/src/mage/cards/r/RyuseiTheFallingStar.java
@@ -4,7 +4,7 @@ package mage.cards.r;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -36,7 +36,7 @@ public final class RyuseiTheFallingStar extends CardImpl {
this.power = new MageInt(5);
this.toughness = new MageInt(5);
this.addAbility(FlyingAbility.getInstance());
- this.addAbility(new DiesTriggeredAbility(new DamageAllEffect(5, filter)));
+ this.addAbility(new DiesSourceTriggeredAbility(new DamageAllEffect(5, filter)));
}
public RyuseiTheFallingStar(final RyuseiTheFallingStar card) {
diff --git a/Mage.Sets/src/mage/cards/s/SabertoothMauler.java b/Mage.Sets/src/mage/cards/s/SabertoothMauler.java
new file mode 100644
index 00000000000..4ee840e7214
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SabertoothMauler.java
@@ -0,0 +1,51 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.condition.common.MorbidCondition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.UntapSourceEffect;
+import mage.abilities.effects.common.counter.AddCountersSourceEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.counters.CounterType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SabertoothMauler extends CardImpl {
+
+ public SabertoothMauler(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}");
+
+ this.subtype.add(SubType.CAT);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // At the beginning of your end step, if a creature died this turn, put a +1/+1 counter on Sabertooth Mauler and untap it.
+ Ability ability = new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfEndStepTriggeredAbility(
+ new AddCountersSourceEffect(CounterType.P1P1.createInstance()
+ ), TargetController.YOU, false
+ ), MorbidCondition.instance, "At the beginning of your end step, " +
+ "if a creature died this turn, put a +1/+1 counter on {this} and untap it."
+ );
+ ability.addEffect(new UntapSourceEffect());
+ this.addAbility(ability);
+ }
+
+ private SabertoothMauler(final SabertoothMauler card) {
+ super(card);
+ }
+
+ @Override
+ public SabertoothMauler copy() {
+ return new SabertoothMauler(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SacredPrey.java b/Mage.Sets/src/mage/cards/s/SacredPrey.java
index fe1ff1407ab..ce4c023b4d0 100644
--- a/Mage.Sets/src/mage/cards/s/SacredPrey.java
+++ b/Mage.Sets/src/mage/cards/s/SacredPrey.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class SacredPrey extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Sacred Prey becomes blocked, you gain 1 life.
- this.addAbility(new BecomesBlockedTriggeredAbility(new GainLifeEffect(1), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new GainLifeEffect(1), false));
}
public SacredPrey(final SacredPrey card) {
diff --git a/Mage.Sets/src/mage/cards/s/SacredRites.java b/Mage.Sets/src/mage/cards/s/SacredRites.java
index a1302c4ba34..3104c737bdc 100644
--- a/Mage.Sets/src/mage/cards/s/SacredRites.java
+++ b/Mage.Sets/src/mage/cards/s/SacredRites.java
@@ -1,24 +1,23 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
-import mage.target.common.TargetCardInHand;
+import mage.target.common.TargetDiscard;
+
+import java.util.UUID;
/**
- *
* @author cbt33
*/
public final class SacredRites extends CardImpl {
@@ -30,7 +29,7 @@ public final class SacredRites extends CardImpl {
this.getSpellAbility().addEffect(new SacredRitesEffect());
}
- public SacredRites(final SacredRites card) {
+ private SacredRites(final SacredRites card) {
super(card);
}
@@ -43,11 +42,11 @@ public final class SacredRites extends CardImpl {
class SacredRitesEffect extends OneShotEffect {
SacredRitesEffect() {
- super(Outcome.Benefit);
+ super(Outcome.AIDontUseIt);
this.staticText = "Discard any number of cards. Creatures you control get +0/+1 until end of turn for each card discarded this way.";
}
- SacredRitesEffect(final SacredRitesEffect effect) {
+ private SacredRitesEffect(final SacredRitesEffect effect) {
super(effect);
}
@@ -59,21 +58,15 @@ class SacredRitesEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Target target = new TargetCardInHand(0, Integer.MAX_VALUE, new FilterCard("cards to discard"));
- while (controller.canRespond() && !target.isChosen()) {
- target.choose(Outcome.BoostCreature, controller.getId(), source.getSourceId(), game);
- }
- int numDiscarded = 0;
- for (UUID targetId : target.getTargets()) {
- Card card = controller.getHand().get(targetId, game);
- if (controller.discard(card, source, game)) {
- numDiscarded++;
- }
- }
- game.addEffect(new BoostControlledEffect(0, numDiscarded, Duration.EndOfTurn), source);
- return true;
+ if (controller == null) {
+ return false;
}
- return false;
+ Target target = new TargetDiscard(0, Integer.MAX_VALUE, StaticFilters.FILTER_CARD, controller.getId());
+ target.choose(outcome, controller.getId(), source.getSourceId(), game);
+ int numDiscarded = controller.discard(new CardsImpl(target.getTargets()), source, game).size();
+ if (numDiscarded > 0) {
+ game.addEffect(new BoostControlledEffect(0, numDiscarded, Duration.EndOfTurn), source);
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/s/SadisticAugermage.java b/Mage.Sets/src/mage/cards/s/SadisticAugermage.java
index f6b2d9d83f3..dfbd3d36f51 100644
--- a/Mage.Sets/src/mage/cards/s/SadisticAugermage.java
+++ b/Mage.Sets/src/mage/cards/s/SadisticAugermage.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
@@ -32,7 +32,7 @@ public final class SadisticAugermage extends CardImpl {
this.toughness = new MageInt(1);
// When Sadistic Augermage dies, each player puts a card from their hand on top of their library.
- this.addAbility(new DiesTriggeredAbility(new WidespreadPanicEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new WidespreadPanicEffect()));
}
public SadisticAugermage(final SadisticAugermage card) {
diff --git a/Mage.Sets/src/mage/cards/s/SageOfTheFalls.java b/Mage.Sets/src/mage/cards/s/SageOfTheFalls.java
index 29ad92531e7..b40b05b3e3c 100644
--- a/Mage.Sets/src/mage/cards/s/SageOfTheFalls.java
+++ b/Mage.Sets/src/mage/cards/s/SageOfTheFalls.java
@@ -1,7 +1,7 @@
package mage.cards.s;
import mage.MageInt;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -18,8 +18,7 @@ import java.util.UUID;
*/
public final class SageOfTheFalls extends CardImpl {
- private static final FilterPermanent filter
- = new FilterCreaturePermanent("{this} or another non-Human creature");
+ private static final FilterPermanent filter = new FilterCreaturePermanent("non-Human creature");
static {
filter.add(Predicates.not(SubType.HUMAN.getPredicate()));
@@ -34,9 +33,9 @@ public final class SageOfTheFalls extends CardImpl {
this.toughness = new MageInt(5);
// Whenever Sage of the Falls or another non-Human creature enters the battlefield under you control, you may draw a card. If you do, discard a card.
- this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
- new DrawDiscardControllerEffect(1, 1, true), filter
- ));
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(new DrawDiscardControllerEffect(
+ 1, 1, true
+ ), filter, false, true));
}
private SageOfTheFalls(final SageOfTheFalls card) {
diff --git a/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java b/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java
index 8fed936baa9..a0e23f4e3db 100644
--- a/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java
+++ b/Mage.Sets/src/mage/cards/s/SakashimaTheImpostor.java
@@ -64,7 +64,7 @@ class SakashimaTheImpostorApplier extends ApplyToPermanent {
permanent.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnToHandSourceEffect(true)), false),
new ManaCostsImpl("{2}{U}{U}")
- ), game);
+ ), source.getSourceId(), game);
return true;
}
diff --git a/Mage.Sets/src/mage/cards/s/SaltRoadAmbushers.java b/Mage.Sets/src/mage/cards/s/SaltRoadAmbushers.java
index 3329be28191..95f4f69c7e5 100644
--- a/Mage.Sets/src/mage/cards/s/SaltRoadAmbushers.java
+++ b/Mage.Sets/src/mage/cards/s/SaltRoadAmbushers.java
@@ -23,7 +23,7 @@ public final class SaltRoadAmbushers extends CardImpl {
public SaltRoadAmbushers(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/s/SalvageDrone.java b/Mage.Sets/src/mage/cards/s/SalvageDrone.java
index 66e0942638d..e8944e482ff 100644
--- a/Mage.Sets/src/mage/cards/s/SalvageDrone.java
+++ b/Mage.Sets/src/mage/cards/s/SalvageDrone.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.abilities.keyword.DevoidAbility;
import mage.abilities.keyword.IngestAbility;
@@ -30,7 +30,7 @@ public final class SalvageDrone extends CardImpl {
// Ingest (Whenever this creature deals combat damage to a player, that player exiles the top card of their library.)
this.addAbility(new IngestAbility());
// When Salvage Drone dies, you may draw a card. If you do, discard a card.
- this.addAbility(new DiesTriggeredAbility(new DrawDiscardControllerEffect(1, 1, true), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawDiscardControllerEffect(1, 1, true), false));
}
diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfAll.java b/Mage.Sets/src/mage/cards/s/SanctumOfAll.java
new file mode 100644
index 00000000000..97386229b2e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SanctumOfAll.java
@@ -0,0 +1,109 @@
+package mage.cards.s;
+
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.effects.common.search.SearchLibraryGraveyardPutOntoBattlefieldEffect;
+import mage.abilities.hint.ValueHint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.constants.TargetController;
+import mage.filter.FilterCard;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class SanctumOfAll extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledPermanent();
+ private static final FilterCard filterCard = new FilterCard("a Shrine card");
+
+ static final PermanentsOnBattlefieldCount count = new PermanentsOnBattlefieldCount(filter);
+
+ static {
+ filter.add(SubType.SHRINE.getPredicate());
+ filterCard.add(SubType.SHRINE.getPredicate());
+ }
+
+ public SanctumOfAll(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{U}{B}{R}{G}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.SHRINE);
+
+ // At the beginning of your upkeep, you may search your library and/or graveyard for a Shrine card and put it onto the battlefield. If you search your library this way, shuffle it.
+ this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SearchLibraryGraveyardPutOntoBattlefieldEffect(filterCard), TargetController.YOU, true));
+
+ // If an ability of another Shrine you control triggers while you control six or more Shrines, that ability triggers an additional time.
+ this.addAbility(new SimpleStaticAbility(new SanctumOfAllTriggerEffect()).addHint(new ValueHint("Shrines you control", count)));
+ }
+
+ private SanctumOfAll(final SanctumOfAll card) {
+ super(card);
+ }
+
+ @Override
+ public SanctumOfAll copy() {
+ return new SanctumOfAll(this);
+ }
+}
+
+class SanctumOfAllTriggerEffect extends ReplacementEffectImpl {
+
+ SanctumOfAllTriggerEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.Benefit);
+ staticText = "if an ability of another Shrine you control triggers while you control six or more Shrines, that ability triggers an additional time";
+ }
+
+ private SanctumOfAllTriggerEffect(SanctumOfAllTriggerEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public SanctumOfAllTriggerEffect copy() {
+ return new SanctumOfAllTriggerEffect(this);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ event.setAmount(event.getAmount() + 1);
+ return false;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.NUMBER_OF_TRIGGERS;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ // Only triggers of the controller of Sanctum of All
+ if (source.isControlledBy(event.getPlayerId())) {
+ // Only trigger while you control six or more Shrines
+ int numShrines = SanctumOfAll.count.calculate(game, source, this);
+ if (numShrines >= 6) {
+ // Only for triggers of other Shrines
+ Permanent permanent = game.getPermanent(event.getSourceId());
+ return permanent != null
+ && !permanent.getId().equals(source.getSourceId())
+ && permanent.hasSubtype(SubType.SHRINE, game);
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfCalmWaters.java b/Mage.Sets/src/mage/cards/s/SanctumOfCalmWaters.java
new file mode 100644
index 00000000000..a132be5050f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SanctumOfCalmWaters.java
@@ -0,0 +1,56 @@
+package mage.cards.s;
+
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.discard.DiscardControllerEffect;
+import mage.abilities.hint.ValueHint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.constants.TargetController;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author jmharmon
+ */
+
+public final class SanctumOfCalmWaters extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledPermanent();
+ private static final PermanentsOnBattlefieldCount xValue = new PermanentsOnBattlefieldCount(filter);
+
+ static {
+ filter.add(SubType.SHRINE.getPredicate());
+ }
+
+ public SanctumOfCalmWaters(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.SHRINE);
+
+ // At the beginning of your precombat main phase, you may draw X cards, where X is the number of Shrines you control. If you do, discard a card.
+ Ability ability = new BeginningOfPreCombatMainTriggeredAbility(new DrawCardSourceControllerEffect(xValue)
+ .setText("you may draw X cards, where X is the number of Shrines you control"),
+ TargetController.YOU, true)
+ .addHint(new ValueHint("Shrines you control", xValue));
+ ability.addEffect(new DiscardControllerEffect(1).setText("If you do, discard a card"));
+ this.addAbility(ability);
+ }
+
+ public SanctumOfCalmWaters(final SanctumOfCalmWaters card) {
+ super(card);
+ }
+
+ @Override
+ public SanctumOfCalmWaters copy() {
+ return new SanctumOfCalmWaters(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfFruitfulHarvest.java b/Mage.Sets/src/mage/cards/s/SanctumOfFruitfulHarvest.java
new file mode 100644
index 00000000000..62c8b50374a
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SanctumOfFruitfulHarvest.java
@@ -0,0 +1,57 @@
+package mage.cards.s;
+
+import mage.Mana;
+import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.mana.DynamicManaEffect;
+import mage.abilities.hint.ValueHint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.constants.TargetController;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class SanctumOfFruitfulHarvest extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledPermanent();
+ private static final PermanentsOnBattlefieldCount xValue = new PermanentsOnBattlefieldCount(filter);
+
+ static {
+ filter.add(SubType.SHRINE.getPredicate());
+ }
+
+ public SanctumOfFruitfulHarvest(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.SHRINE);
+
+ // At the beginning of your precombat main phase, add X mana of any one color, where X is the number of Shrines you control.
+ this.addAbility(new BeginningOfPreCombatMainTriggeredAbility(
+ new DynamicManaEffect(
+ Mana.AnyMana(1),
+ xValue,
+ "add X mana of any one color, where X is the number of Shrines you control",
+ true),
+ TargetController.YOU, false)
+ .addHint(new ValueHint("Shrines you control", xValue)));
+ }
+
+ private SanctumOfFruitfulHarvest(final SanctumOfFruitfulHarvest card) {
+ super(card);
+ }
+
+ @Override
+ public SanctumOfFruitfulHarvest copy() {
+ return new SanctumOfFruitfulHarvest(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfShatteredHeights.java b/Mage.Sets/src/mage/cards/s/SanctumOfShatteredHeights.java
new file mode 100644
index 00000000000..d6ef9e04952
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SanctumOfShatteredHeights.java
@@ -0,0 +1,64 @@
+package mage.cards.s;
+
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.DiscardTargetCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.hint.ValueHint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.Predicates;
+import mage.target.common.TargetCardInHand;
+import mage.target.common.TargetCreatureOrPlaneswalker;
+
+import java.util.UUID;
+
+/**
+ * @author jmharmon
+ */
+
+public final class SanctumOfShatteredHeights extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard("a land card or Shrine card");
+ private static final FilterPermanent filterShrinesOnly = new FilterControlledPermanent("Shrine you control");
+ private static final PermanentsOnBattlefieldCount xValue = new PermanentsOnBattlefieldCount(filterShrinesOnly);
+
+ static {
+ filter.add(Predicates.or(CardType.LAND.getPredicate(), SubType.SHRINE.getPredicate()));
+ filterShrinesOnly.add(SubType.SHRINE.getPredicate());
+ }
+
+ public SanctumOfShatteredHeights(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.SHRINE);
+
+ // {1}, Discard a land card or Shrine card: Sanctum of Shattered Heights deals X damage to target creature or planeswalker, where X is the number of Shrines you control.
+ Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(xValue)
+ .setText("Sanctum of Shattered Heights deals X damage to target creature or planeswalker, where X is the number of Shrines you control"),
+ new ManaCostsImpl<>("{1}"))
+ .addHint(new ValueHint("Shrines you control", xValue));
+ ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter)));
+ ability.addTarget(new TargetCreatureOrPlaneswalker());
+ this.addAbility(ability);
+ }
+
+ public SanctumOfShatteredHeights(final SanctumOfShatteredHeights card) {
+ super(card);
+ }
+
+ @Override
+ public SanctumOfShatteredHeights copy() {
+ return new SanctumOfShatteredHeights(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfStoneFangs.java b/Mage.Sets/src/mage/cards/s/SanctumOfStoneFangs.java
new file mode 100644
index 00000000000..2067849ca46
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SanctumOfStoneFangs.java
@@ -0,0 +1,56 @@
+package mage.cards.s;
+
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.common.LoseLifeOpponentsEffect;
+import mage.abilities.hint.ValueHint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.constants.TargetController;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class SanctumOfStoneFangs extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledPermanent("");
+ private static final PermanentsOnBattlefieldCount xValue = new PermanentsOnBattlefieldCount(filter, null);
+
+ static {
+ filter.add(SubType.SHRINE.getPredicate());
+ }
+
+ public SanctumOfStoneFangs(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.SHRINE);
+
+ // At the beginning of your precombat main phase, each opponent loses X life and you gain X life, where X is the number of Shrines you control.
+ Ability ability = new BeginningOfPreCombatMainTriggeredAbility(
+ new LoseLifeOpponentsEffect(xValue).setText("each opponent loses X life"),
+ TargetController.YOU, false)
+ .addHint(new ValueHint("Shrines you control", xValue));
+ ability.addEffect(new GainLifeEffect(xValue).setText("and you gain X life, where X is the number of Shrines you control"));
+ this.addAbility(ability);
+ }
+
+ private SanctumOfStoneFangs(final SanctumOfStoneFangs card) {
+ super(card);
+ }
+
+ @Override
+ public SanctumOfStoneFangs copy() {
+ return new SanctumOfStoneFangs(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfTranquilLight.java b/Mage.Sets/src/mage/cards/s/SanctumOfTranquilLight.java
new file mode 100644
index 00000000000..50ea1e8b8d0
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SanctumOfTranquilLight.java
@@ -0,0 +1,76 @@
+package mage.cards.s;
+
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.abilities.effects.common.cost.CostModificationSourceEffect;
+import mage.abilities.hint.ValueHint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.constants.Zone;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ *
+ * @author htrajan
+ */
+public final class SanctumOfTranquilLight extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterControlledPermanent("Shrine you control");
+ private static final PermanentsOnBattlefieldCount count = new PermanentsOnBattlefieldCount(filter);
+
+ static {
+ filter.add(SubType.SHRINE.getPredicate());
+ }
+
+ public SanctumOfTranquilLight(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.SHRINE);
+
+ // {5}{W}: Tap target creature. This ability costs {1} less to activate for each Shrine you control.
+ Ability ability = new SimpleActivatedAbility(new SanctumOfTranquilLightActivatedAbility());
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new CostModificationSourceEffect(Duration.EndOfGame, Outcome.Benefit, SanctumOfTranquilLightActivatedAbility.class, count, true).setText(""))
+ .addHint(new ValueHint("Shrines you control", count)));
+ }
+
+ private SanctumOfTranquilLight(final SanctumOfTranquilLight card) {
+ super(card);
+ }
+
+ @Override
+ public SanctumOfTranquilLight copy() {
+ return new SanctumOfTranquilLight(this);
+ }
+}
+
+class SanctumOfTranquilLightActivatedAbility extends SimpleActivatedAbility {
+
+ SanctumOfTranquilLightActivatedAbility() {
+ super(new TapTargetEffect().setText("target creature. This ability costs {1} less to activate for each Shrine you control"), new ManaCostsImpl<>("{5}{W}"));
+ }
+
+ private SanctumOfTranquilLightActivatedAbility(SanctumOfTranquilLightActivatedAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public SanctumOfTranquilLightActivatedAbility copy() {
+ return new SanctumOfTranquilLightActivatedAbility(this);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/s/SandsteppeOutcast.java b/Mage.Sets/src/mage/cards/s/SandsteppeOutcast.java
index fcc419c66af..72b0150e3e7 100644
--- a/Mage.Sets/src/mage/cards/s/SandsteppeOutcast.java
+++ b/Mage.Sets/src/mage/cards/s/SandsteppeOutcast.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.Mode;
@@ -15,14 +13,15 @@ import mage.constants.SubType;
import mage.counters.CounterType;
import mage.game.permanent.token.SpiritWhiteToken;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class SandsteppeOutcast extends CardImpl {
public SandsteppeOutcast(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(2);
@@ -31,12 +30,12 @@ public final class SandsteppeOutcast extends CardImpl {
// When Sandsteppe Outcast enters the battlefield, choose one -
// * Put a +1/+1 counter on Sandsteppe Outcast.
Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()));
-
+
// * Create a 1/1 white Spirit creature token with flying.
Mode mode = new Mode();
- mode.addEffect(new CreateTokenEffect(new SpiritWhiteToken("FRF")));
+ mode.addEffect(new CreateTokenEffect(new SpiritWhiteToken()));
ability.addMode(mode);
- this.addAbility(ability);
+ this.addAbility(ability);
}
public SandsteppeOutcast(final SandsteppeOutcast card) {
diff --git a/Mage.Sets/src/mage/cards/s/SandsteppeScavenger.java b/Mage.Sets/src/mage/cards/s/SandsteppeScavenger.java
index 770fa837680..d23385995da 100644
--- a/Mage.Sets/src/mage/cards/s/SandsteppeScavenger.java
+++ b/Mage.Sets/src/mage/cards/s/SandsteppeScavenger.java
@@ -18,7 +18,7 @@ public final class SandsteppeScavenger extends CardImpl {
public SandsteppeScavenger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.subtype.add(SubType.SCOUT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/s/SandwurmConvergence.java b/Mage.Sets/src/mage/cards/s/SandwurmConvergence.java
index 63d0b0374a6..ba04fcf1ca8 100644
--- a/Mage.Sets/src/mage/cards/s/SandwurmConvergence.java
+++ b/Mage.Sets/src/mage/cards/s/SandwurmConvergence.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.Effect;
@@ -16,10 +14,11 @@ import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.AbilityPredicate;
-import mage.game.permanent.token.WurmToken3;
+import mage.game.permanent.token.Wurm55Token;
+
+import java.util.UUID;
/**
- *
* @author fireshoes
*/
public final class SandwurmConvergence extends CardImpl {
@@ -39,7 +38,7 @@ public final class SandwurmConvergence extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
// At the beginning of your end step, create a 5/5 green Wurm creature token.
- this.addAbility(new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new WurmToken3()), TargetController.YOU, false));
+ this.addAbility(new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new Wurm55Token()), TargetController.YOU, false));
}
public SandwurmConvergence(final SandwurmConvergence card) {
diff --git a/Mage.Sets/src/mage/cards/s/SanguineBond.java b/Mage.Sets/src/mage/cards/s/SanguineBond.java
index 9a25f2c7ae4..fa12709d1e4 100644
--- a/Mage.Sets/src/mage/cards/s/SanguineBond.java
+++ b/Mage.Sets/src/mage/cards/s/SanguineBond.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
@@ -13,15 +11,15 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class SanguineBond extends CardImpl {
public SanguineBond(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{B}{B}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}");
// Whenever you gain life, target opponent loses that much life.
SanguineBondTriggeredAbility ability = new SanguineBondTriggeredAbility();
diff --git a/Mage.Sets/src/mage/cards/s/SanguineIndulgence.java b/Mage.Sets/src/mage/cards/s/SanguineIndulgence.java
new file mode 100644
index 00000000000..d81bac3e947
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SanguineIndulgence.java
@@ -0,0 +1,51 @@
+package mage.cards.s;
+
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.YouGainedLifeCondition;
+import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
+import mage.abilities.hint.Hint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.ComparisonType;
+import mage.constants.Zone;
+import mage.filter.StaticFilters;
+import mage.target.common.TargetCardInYourGraveyard;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SanguineIndulgence extends CardImpl {
+
+ private static final Condition condition = new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2);
+ private static final Hint hint = new ConditionHint(condition, "You gained 3 or more life this turn");
+
+ public SanguineIndulgence(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}");
+
+ // This spell costs {3} less to cast if you've gained 3 or more life this turn.
+ this.addAbility(new SimpleStaticAbility(
+ Zone.ALL, new SpellCostReductionSourceEffect(3, condition)
+ ).addHint(hint));
+
+ // Return up to two target creature cards from your graveyard to your hand.
+ this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect());
+ this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(
+ 0, 2, StaticFilters.FILTER_CARD_CREATURES_YOUR_GRAVEYARD
+ ));
+ }
+
+ private SanguineIndulgence(final SanguineIndulgence card) {
+ super(card);
+ }
+
+ @Override
+ public SanguineIndulgence copy() {
+ return new SanguineIndulgence(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SanityGrinding.java b/Mage.Sets/src/mage/cards/s/SanityGrinding.java
index a63afd36f95..ae141fcb70d 100644
--- a/Mage.Sets/src/mage/cards/s/SanityGrinding.java
+++ b/Mage.Sets/src/mage/cards/s/SanityGrinding.java
@@ -1,33 +1,26 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
-import mage.cards.CardImpl;
-import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
+import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
- *
*/
public final class SanityGrinding extends CardImpl {
public SanityGrinding(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{U}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{U}{U}");
// Chroma - Reveal the top ten cards of your library. For each blue mana symbol in the mana costs of the revealed cards, target opponent puts the top card of their library into their graveyard. Then put the cards you revealed this way on the bottom of your library in any order.
this.getSpellAbility().addEffect(new SanityGrindingEffect());
@@ -49,7 +42,9 @@ class SanityGrindingEffect extends OneShotEffect {
public SanityGrindingEffect() {
super(Outcome.Neutral);
- staticText = "Chroma — Reveal the top ten cards of your library. For each blue mana symbol in the mana costs of the revealed cards, target opponent puts the top card of their library into their graveyard. Then put the cards you revealed this way on the bottom of your library in any order";
+ staticText = "Chroma — Reveal the top ten cards of your library. " +
+ "For each blue mana symbol in the mana costs of the revealed cards, target opponent mills a card. " +
+ "Then put the cards you revealed this way on the bottom of your library in any order";
}
public SanityGrindingEffect(final SanityGrindingEffect effect) {
@@ -68,8 +63,7 @@ class SanityGrindingEffect extends OneShotEffect {
controller.revealCards(sourceObject.getIdName(), revealed, game);
Player targetOpponent = game.getPlayer(source.getFirstTarget());
if (targetOpponent != null) {
- targetOpponent.moveCards(targetOpponent.getLibrary().getTopCards(game, new ChromaSanityGrindingCount(revealed).calculate(game, source, this)),
- Zone.GRAVEYARD, source, game);
+ targetOpponent.millCards(new ChromaSanityGrindingCount(revealed).calculate(game, source, this), source, game);
}
return controller.putCardsOnBottomOfLibrary(revealed, game, source, true);
}
diff --git a/Mage.Sets/src/mage/cards/s/SapphireLeech.java b/Mage.Sets/src/mage/cards/s/SapphireLeech.java
index 8b7e1386d78..31d8772e275 100644
--- a/Mage.Sets/src/mage/cards/s/SapphireLeech.java
+++ b/Mage.Sets/src/mage/cards/s/SapphireLeech.java
@@ -1,23 +1,23 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementControllerEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author LoneFox
*/
public final class SapphireLeech extends CardImpl {
@@ -29,7 +29,7 @@ public final class SapphireLeech extends CardImpl {
}
public SapphireLeech(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.LEECH);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
@@ -38,7 +38,7 @@ public final class SapphireLeech extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Blue spells you cast cost {U} more to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
- new SpellsCostIncreasementControllerEffect(filter, new ManaCostsImpl("{U}"))));
+ new SpellsCostIncreasingAllEffect(new ManaCostsImpl("{U}"), filter, TargetController.YOU)));
}
public SapphireLeech(final SapphireLeech card) {
diff --git a/Mage.Sets/src/mage/cards/s/SaprazzanBreaker.java b/Mage.Sets/src/mage/cards/s/SaprazzanBreaker.java
index df66369b2ed..336099b0710 100644
--- a/Mage.Sets/src/mage/cards/s/SaprazzanBreaker.java
+++ b/Mage.Sets/src/mage/cards/s/SaprazzanBreaker.java
@@ -1,27 +1,24 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
+import mage.MageObject;
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.combat.CantBeBlockedByAllSourceEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author L_J
*/
public final class SaprazzanBreaker extends CardImpl {
@@ -36,7 +33,7 @@ public final class SaprazzanBreaker extends CardImpl {
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new SaprazzanBreakerEffect(), new ManaCostsImpl("{U}")));
}
- public SaprazzanBreaker(final SaprazzanBreaker card) {
+ private SaprazzanBreaker(final SaprazzanBreaker card) {
super(card);
}
@@ -48,12 +45,12 @@ public final class SaprazzanBreaker extends CardImpl {
class SaprazzanBreakerEffect extends OneShotEffect {
- public SaprazzanBreakerEffect() {
+ SaprazzanBreakerEffect() {
super(Outcome.Benefit);
- this.staticText = "Put the top card of your library into your graveyard. If that card is a land card, {this} can't be blocked this turn";
+ this.staticText = "Mill a card. If a land card was milled this way, {this} can't be blocked this turn";
}
- public SaprazzanBreakerEffect(final SaprazzanBreakerEffect effect) {
+ private SaprazzanBreakerEffect(final SaprazzanBreakerEffect effect) {
super(effect);
}
@@ -65,16 +62,12 @@ class SaprazzanBreakerEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- Card card = player.getLibrary().getFromTop(game);
- if (card != null) {
- player.moveCards(card, Zone.GRAVEYARD, source, game);
- if (card.isLand()) {
- game.addEffect(new CantBeBlockedByAllSourceEffect(StaticFilters.FILTER_PERMANENT_CREATURES, Duration.EndOfTurn), source);
- }
- }
- return true;
+ if (player == null) {
+ return false;
}
- return false;
+ if (player.millCards(1, source, game).getCards(game).stream().filter(Objects::nonNull).anyMatch(MageObject::isLand)) {
+ game.addEffect(new CantBeBlockedByAllSourceEffect(StaticFilters.FILTER_PERMANENT_CREATURES, Duration.EndOfTurn), source);
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/s/SaprazzanHeir.java b/Mage.Sets/src/mage/cards/s/SaprazzanHeir.java
index 3fea5cefbb6..111f4df99c2 100644
--- a/Mage.Sets/src/mage/cards/s/SaprazzanHeir.java
+++ b/Mage.Sets/src/mage/cards/s/SaprazzanHeir.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class SaprazzanHeir extends CardImpl {
this.toughness = new MageInt(1);
// Whenever Saprazzan Heir becomes blocked, you may draw three cards.
- this.addAbility(new BecomesBlockedTriggeredAbility(new DrawCardSourceControllerEffect(3), true));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new DrawCardSourceControllerEffect(3), true));
}
public SaprazzanHeir(final SaprazzanHeir card) {
diff --git a/Mage.Sets/src/mage/cards/s/SaprazzanRaider.java b/Mage.Sets/src/mage/cards/s/SaprazzanRaider.java
index 50ab00e49df..cb0d63682f8 100644
--- a/Mage.Sets/src/mage/cards/s/SaprazzanRaider.java
+++ b/Mage.Sets/src/mage/cards/s/SaprazzanRaider.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class SaprazzanRaider extends CardImpl {
this.toughness = new MageInt(2);
// When Saprazzan Raider becomes blocked, return it to its owner's hand.
- this.addAbility(new BecomesBlockedTriggeredAbility(new ReturnToHandSourceEffect(), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new ReturnToHandSourceEffect(), false));
}
public SaprazzanRaider(final SaprazzanRaider card) {
diff --git a/Mage.Sets/src/mage/cards/s/SaprolingInfestation.java b/Mage.Sets/src/mage/cards/s/SaprolingInfestation.java
index 7fd3df301ee..3a604196c95 100644
--- a/Mage.Sets/src/mage/cards/s/SaprolingInfestation.java
+++ b/Mage.Sets/src/mage/cards/s/SaprolingInfestation.java
@@ -13,14 +13,13 @@ import mage.game.permanent.token.SaprolingToken;
import java.util.UUID;
/**
- *
* @author noahg
*/
public final class SaprolingInfestation extends CardImpl {
public SaprolingInfestation(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}");
-
+
// Whenever a player kicks a spell, you put a 1/1 green Saproling creature token onto the battlefield.
this.addAbility(new SaprolingInfestationTriggeredAbility());
@@ -38,7 +37,7 @@ public final class SaprolingInfestation extends CardImpl {
class SaprolingInfestationTriggeredAbility extends TriggeredAbilityImpl {
SaprolingInfestationTriggeredAbility() {
- super(Zone.BATTLEFIELD, new CreateTokenEffect(new SaprolingToken("INV")), false);
+ super(Zone.BATTLEFIELD, new CreateTokenEffect(new SaprolingToken()), false);
}
SaprolingInfestationTriggeredAbility(final SaprolingInfestationTriggeredAbility ability) {
diff --git a/Mage.Sets/src/mage/cards/s/SavageStomp.java b/Mage.Sets/src/mage/cards/s/SavageStomp.java
index 993f367ce20..d2a8f044d1e 100644
--- a/Mage.Sets/src/mage/cards/s/SavageStomp.java
+++ b/Mage.Sets/src/mage/cards/s/SavageStomp.java
@@ -36,7 +36,7 @@ public final class SavageStomp extends CardImpl {
// Savage Stomp costs {2} less to cast if it targets a Dinosaur you control.
this.addAbility(new SimpleStaticAbility(
- Zone.STACK, new SpellCostReductionSourceEffect(2, condition)
+ Zone.ALL, new SpellCostReductionSourceEffect(2, condition).setCanWorksOnStackOnly(true)
).setRuleAtTheTop(true));
// Put a +1/+1 counter on target creature you control. Then that creature fights target creature you don't control.
diff --git a/Mage.Sets/src/mage/cards/s/SavageSummoning.java b/Mage.Sets/src/mage/cards/s/SavageSummoning.java
index 8c4d07ebba3..15228dd8449 100644
--- a/Mage.Sets/src/mage/cards/s/SavageSummoning.java
+++ b/Mage.Sets/src/mage/cards/s/SavageSummoning.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.ReplacementEffectImpl;
@@ -34,7 +34,7 @@ public final class SavageSummoning extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}");
// Savage Summoning can't be countered.
- Ability ability = new CantBeCounteredAbility();
+ Ability ability = new CantBeCounteredSourceAbility();
ability.setRuleAtTheTop(true);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/s/SavageSwipe.java b/Mage.Sets/src/mage/cards/s/SavageSwipe.java
index 8c8140ad78d..65caea08557 100644
--- a/Mage.Sets/src/mage/cards/s/SavageSwipe.java
+++ b/Mage.Sets/src/mage/cards/s/SavageSwipe.java
@@ -70,7 +70,7 @@ class SavageSwipeEffect extends OneShotEffect {
ContinuousEffect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
- game.applyEffects();
+ game.getState().processAction(game);
}
return new FightTargetsEffect().apply(game, source);
}
diff --git a/Mage.Sets/src/mage/cards/s/SavaiThundermane.java b/Mage.Sets/src/mage/cards/s/SavaiThundermane.java
index 921dfdb90ec..544f27681c0 100644
--- a/Mage.Sets/src/mage/cards/s/SavaiThundermane.java
+++ b/Mage.Sets/src/mage/cards/s/SavaiThundermane.java
@@ -1,23 +1,16 @@
package mage.cards.s;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.CycleControllerTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
-import mage.abilities.effects.common.DoIfCostPaid;
+import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.effects.common.GainLifeEffect;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
import mage.constants.SubType;
-import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
@@ -35,12 +28,15 @@ public final class SavaiThundermane extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(2);
- // Whenever you cycle a card, you may pay {2}. When you do Savai Thundermane deals 2 damage to target creature and you gain 2 life.
+ // Whenever you cycle a card, you may pay {2}. When you do, Savai Thundermane deals 2 damage to target creature and you gain 2 life.
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new DamageTargetEffect(2), false,
+ "{this} deals 2 damage to target creature and you gain 2 life"
+ );
+ ability.addEffect(new GainLifeEffect(2));
+ ability.addTarget(new TargetCreaturePermanent());
this.addAbility(new CycleControllerTriggeredAbility(
- new DoIfCostPaid(
- new SavaiThundermaneCreateReflexiveTriggerEffect(), new GenericManaCost(2),
- "Pay {2} to deal 2 damage and gain 2 life?"
- ).setText("you may pay {2}. When you do, {this} deals 2 damage to target creature and you gain 2 life")
+ new DoWhenCostPaid(ability, new GenericManaCost(2), "Pay {2}?")
));
}
@@ -53,59 +49,3 @@ public final class SavaiThundermane extends CardImpl {
return new SavaiThundermane(this);
}
}
-
-class SavaiThundermaneCreateReflexiveTriggerEffect extends OneShotEffect {
-
- SavaiThundermaneCreateReflexiveTriggerEffect() {
- super(Outcome.Benefit);
- }
-
- private SavaiThundermaneCreateReflexiveTriggerEffect(final SavaiThundermaneCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public SavaiThundermaneCreateReflexiveTriggerEffect copy() {
- return new SavaiThundermaneCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new SavaiThundermaneReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class SavaiThundermaneReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- SavaiThundermaneReflexiveTriggeredAbility() {
- super(new DamageTargetEffect(2), Duration.OneUse, true);
- this.addEffect(new GainLifeEffect(2));
- this.addTarget(new TargetCreaturePermanent());
- }
-
- private SavaiThundermaneReflexiveTriggeredAbility(final SavaiThundermaneReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public SavaiThundermaneReflexiveTriggeredAbility copy() {
- return new SavaiThundermaneReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "{this} deals 2 damage to target creature and you gain 2 life";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/s/SawtoothOgre.java b/Mage.Sets/src/mage/cards/s/SawtoothOgre.java
new file mode 100644
index 00000000000..960fd59c7f3
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SawtoothOgre.java
@@ -0,0 +1,43 @@
+package mage.cards.s;
+
+import java.util.UUID;
+
+import mage.MageInt;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
+import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
+import mage.abilities.effects.Effect;
+import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+/**
+ * @author arcox
+ */
+public final class SawtoothOgre extends CardImpl {
+
+ public SawtoothOgre(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}");
+ this.subtype.add(SubType.OGRE);
+
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Whenever Sawtooth Ogre blocks or becomes blocked by a creature, Sawtooth Ogre deals 1 damage to that creature at end of combat.
+ Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(
+ new DamageTargetEffect(1)), true)
+ .setText("{this} deals 1 damage to that creature at end of combat");
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, false));
+ }
+
+ public SawtoothOgre(final SawtoothOgre card) {
+ super(card);
+ }
+
+ @Override
+ public SawtoothOgre copy() {
+ return new SawtoothOgre(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/ScamperingScorcher.java b/Mage.Sets/src/mage/cards/s/ScamperingScorcher.java
index fbbbc088bf2..9561b437f8a 100644
--- a/Mage.Sets/src/mage/cards/s/ScamperingScorcher.java
+++ b/Mage.Sets/src/mage/cards/s/ScamperingScorcher.java
@@ -13,7 +13,7 @@ import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
-import mage.game.permanent.token.YoungPyromancerElementalToken;
+import mage.game.permanent.token.RedElementalToken;
import java.util.UUID;
@@ -34,7 +34,7 @@ public final class ScamperingScorcher extends CardImpl {
// When Scampering Scorcher enters the battlefield, create two 1/1 red Elemental creature tokens. Elementals you control gain haste until end of turn.
Ability ability = new EntersBattlefieldTriggeredAbility(
- new CreateTokenEffect(new YoungPyromancerElementalToken(), 2)
+ new CreateTokenEffect(new RedElementalToken(), 2)
);
ability.addEffect(new GainAbilityControlledEffect(
HasteAbility.getInstance(), Duration.EndOfTurn, filter
diff --git a/Mage.Sets/src/mage/cards/s/ScarabFeast.java b/Mage.Sets/src/mage/cards/s/ScarabFeast.java
index 8e8b1dfa6b8..6a3e02693ca 100644
--- a/Mage.Sets/src/mage/cards/s/ScarabFeast.java
+++ b/Mage.Sets/src/mage/cards/s/ScarabFeast.java
@@ -1,25 +1,26 @@
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.keyword.CyclingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInASingleGraveyard;
+import java.util.UUID;
+
/**
* @author Stravant
*/
public final class ScarabFeast extends CardImpl {
public ScarabFeast(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}");
// Exile up to three target cards from a single graveyard.
getSpellAbility().addEffect(new ExileTargetEffect());
- getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("cards from a single graveyard")));
+ getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, StaticFilters.FILTER_CARD_CARDS));
// Cycling {B}
addAbility(new CyclingAbility(new ManaCostsImpl("{B}")));
diff --git a/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java
index fa59c4dcc53..31934619f83 100644
--- a/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java
+++ b/Mage.Sets/src/mage/cards/s/ScarwoodBandits.java
@@ -26,6 +26,7 @@ import mage.target.common.TargetArtifactPermanent;
import mage.util.CardUtil;
import java.util.UUID;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
/**
* @author L_J
@@ -47,7 +48,7 @@ public final class ScarwoodBandits extends CardImpl {
new DoUnlessAnyOpponentPaysEffect(
new ConditionalContinuousEffect(
new GainControlTargetEffect(Duration.Custom, true),
- SourceOnBattlefieldCondition.instance,
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD),
"gain control of target artifact for as long as {this} remains on the battlefield"),
new GenericManaCost(2)),
new ManaCostsImpl("{2}{G}"));
diff --git a/Mage.Sets/src/mage/cards/s/ScholarOfTheLostTrove.java b/Mage.Sets/src/mage/cards/s/ScholarOfTheLostTrove.java
new file mode 100644
index 00000000000..d518ad24f6e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/ScholarOfTheLostTrove.java
@@ -0,0 +1,154 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.MageObjectReference;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.ContinuousEffect;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.FilterCard;
+import mage.filter.predicate.Predicates;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.events.ZoneChangeEvent;
+import mage.players.Player;
+import mage.target.common.TargetCardInYourGraveyard;
+import mage.target.targetpointer.FixedTarget;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ScholarOfTheLostTrove extends CardImpl {
+
+ private static final FilterCard filter
+ = new FilterCard("instant, sorcery, or artifact card from your graveyard");
+
+ static {
+ filter.add(Predicates.or(
+ CardType.INSTANT.getPredicate(),
+ CardType.SORCERY.getPredicate(),
+ CardType.ARTIFACT.getPredicate()
+ ));
+ }
+
+ public ScholarOfTheLostTrove(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}");
+
+ this.subtype.add(SubType.SPHINX);
+ this.power = new MageInt(5);
+ this.toughness = new MageInt(5);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // When Scholar of the Lost Trove enters the battlefield, you may cast target instant, sorcery, or artifact card from your graveyard without paying its mana cost. If an instant or sorcery spell cast this way would be put into your graveyard this turn, exile it instead.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new ScholarOfTheLostTroveEffect(), true);
+ ability.addTarget(new TargetCardInYourGraveyard(filter));
+ this.addAbility(ability);
+ }
+
+ private ScholarOfTheLostTrove(final ScholarOfTheLostTrove card) {
+ super(card);
+ }
+
+ @Override
+ public ScholarOfTheLostTrove copy() {
+ return new ScholarOfTheLostTrove(this);
+ }
+}
+
+class ScholarOfTheLostTroveEffect extends OneShotEffect {
+
+ ScholarOfTheLostTroveEffect() {
+ super(Outcome.PlayForFree);
+ this.staticText = "you may cast target instant, sorcery, or artifact card from your graveyard without paying its mana cost. " +
+ "If an instant or sorcery spell cast this way would be put into your graveyard this turn, exile it instead";
+ }
+
+ private ScholarOfTheLostTroveEffect(final ScholarOfTheLostTroveEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ScholarOfTheLostTroveEffect copy() {
+ return new ScholarOfTheLostTroveEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller == null) {
+ return false;
+ }
+ Card card = game.getCard(this.getTargetPointer().getFirst(game, source));
+ if (card == null) {
+ return true;
+ }
+ if (!controller.chooseUse(Outcome.PlayForFree, "Cast " + card.getLogName() + '?', source, game)) {
+ return true;
+ }
+ game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
+ Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true),
+ game, true, new MageObjectReference(source.getSourceObject(game), game));
+ game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
+ if (!cardWasCast || !card.isInstantOrSorcery()) {
+ return true;
+ }
+ ContinuousEffect effect = new ScholarOfTheLostTroveReplacementEffect(card.getId());
+ effect.setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId())));
+ game.addEffect(effect, source);
+ return true;
+ }
+}
+
+class ScholarOfTheLostTroveReplacementEffect extends ReplacementEffectImpl {
+
+ private final UUID cardId;
+
+ ScholarOfTheLostTroveReplacementEffect(UUID cardId) {
+ super(Duration.EndOfTurn, Outcome.Exile);
+ this.cardId = cardId;
+ staticText = "If an instant or sorcery spell cast this way would be put into your graveyard this turn, exile it instead";
+ }
+
+ private ScholarOfTheLostTroveReplacementEffect(final ScholarOfTheLostTroveReplacementEffect effect) {
+ super(effect);
+ this.cardId = effect.cardId;
+ }
+
+ @Override
+ public ScholarOfTheLostTroveReplacementEffect copy() {
+ return new ScholarOfTheLostTroveReplacementEffect(this);
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ Player controller = game.getPlayer(source.getControllerId());
+ Card card = game.getCard(this.cardId);
+ if (controller == null || card == null) {
+ return false;
+ }
+ controller.moveCards(card, Zone.EXILED, source, game);
+ return true;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.ZONE_CHANGE;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
+ return zEvent.getToZone() == Zone.GRAVEYARD
+ && zEvent.getTargetId().equals(this.cardId);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java b/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java
index 35d37c2cee9..0d52f4ecf35 100644
--- a/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java
+++ b/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
-import mage.abilities.condition.common.CastFromHandSourceCondition;
+import mage.abilities.condition.common.CastFromHandSourcePermanentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.PopulateEffect;
@@ -32,7 +32,7 @@ public final class ScionOfVituGhazi extends CardImpl {
//When Scion of Vitu-Ghazi enters the battlefield, if you cast it from your hand, create a 1/1 white Bird creature token with flying, then populate.
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken()), false);
ability.addEffect(new PopulateEffect("then"));
- this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourceCondition.instance,
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourcePermanentCondition.instance,
"When {this} enters the battlefield, if you cast it from your hand, create a 1/1 white Bird creature token with flying, then populate."),
new CastFromHandWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/s/ScorchingLava.java b/Mage.Sets/src/mage/cards/s/ScorchingLava.java
index 6cf9e7255bc..6a16e3c70f5 100644
--- a/Mage.Sets/src/mage/cards/s/ScorchingLava.java
+++ b/Mage.Sets/src/mage/cards/s/ScorchingLava.java
@@ -1,4 +1,3 @@
-
package mage.cards.s;
import java.util.UUID;
@@ -34,14 +33,17 @@ public final class ScorchingLava extends CardImpl {
// Kicker {R}
this.addAbility(new KickerAbility("{R}"));
- // Scorching Lava deals 2 damage to any target. If Scorching Lava was kicked, that creature can't be regenerated this turn and if it would die this turn, exile it instead.
+ // Scorching Lava deals 2 damage to any target. If Scorching Lava was kicked,
+ // that creature can't be regenerated this turn and if it would die this turn, exile it instead.
this.getSpellAbility().addEffect(new DamageTargetEffect(2));
this.getSpellAbility().addEffect(new ConditionalContinuousRuleModifyingEffect(
- new CantRegenerateTargetEffect(Duration.EndOfTurn, "that creature"), new LockedInCondition(KickedCondition.instance)));
+ new CantRegenerateTargetEffect(Duration.EndOfTurn, "If Scorching Lava was kicked, "
+ + "\n" + "that creature "),
+ new LockedInCondition(KickedCondition.instance)));
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new ExileTargetIfDiesEffect(),
- new LockedInCondition(KickedCondition.instance)
- ).setText("and if it would die this turn, exile it instead"));
+ new LockedInCondition(KickedCondition.instance),
+ "and if it would die this turn, exile it instead."));
this.getSpellAbility().addTarget(new TargetAnyTarget());
}
@@ -59,7 +61,6 @@ class ScorchingLavaEffect extends OneShotEffect {
public ScorchingLavaEffect() {
super(Outcome.Exile);
- this.staticText = "and if it would die this turn, exile it instead";
}
public ScorchingLavaEffect(final ScorchingLavaEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/s/ScourAllPossibilities.java b/Mage.Sets/src/mage/cards/s/ScourAllPossibilities.java
index e3d67b370c0..6ce1b3d0f25 100644
--- a/Mage.Sets/src/mage/cards/s/ScourAllPossibilities.java
+++ b/Mage.Sets/src/mage/cards/s/ScourAllPossibilities.java
@@ -20,8 +20,8 @@ public final class ScourAllPossibilities extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}");
// Scry 2, then draw a card.
- this.getSpellAbility().addEffect(new ScryEffect(2).setText("scry 2,"));
- this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("then"));
+ this.getSpellAbility().addEffect(new ScryEffect(2, false));
+ this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy(", then"));
// Flashback {4}{U}
this.addAbility(new FlashbackAbility(new ManaCostsImpl("{4}{U}"), TimingRule.SORCERY));
diff --git a/Mage.Sets/src/mage/cards/s/ScourTheLaboratory.java b/Mage.Sets/src/mage/cards/s/ScourTheLaboratory.java
index 4b52a814ce4..ca30d924774 100644
--- a/Mage.Sets/src/mage/cards/s/ScourTheLaboratory.java
+++ b/Mage.Sets/src/mage/cards/s/ScourTheLaboratory.java
@@ -1,7 +1,6 @@
package mage.cards.s;
import java.util.UUID;
-
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.DeliriumCondition;
@@ -23,7 +22,7 @@ public final class ScourTheLaboratory extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{U}{U}");
// Delirium — Scour the Laboratory costs {2} less to cast if there are four or more card types among cards in your graveyard.
- Ability ability = new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(2, DeliriumCondition.instance));
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(2, DeliriumCondition.instance));
ability.setRuleAtTheTop(true);
ability.setAbilityWord(AbilityWord.DELIRIUM);
ability.addHint(DeliriumHint.instance);
diff --git a/Mage.Sets/src/mage/cards/s/ScourgeOfValkas.java b/Mage.Sets/src/mage/cards/s/ScourgeOfValkas.java
index c2332f8c6a0..e6e7f1c6c7c 100644
--- a/Mage.Sets/src/mage/cards/s/ScourgeOfValkas.java
+++ b/Mage.Sets/src/mage/cards/s/ScourgeOfValkas.java
@@ -2,7 +2,7 @@ package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
@@ -10,9 +10,12 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.filter.FilterPermanent;
-import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@@ -25,13 +28,7 @@ import java.util.UUID;
*/
public final class ScourgeOfValkas extends CardImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("{this} or another Dragon");
-
- static {
- filter.add(SubType.DRAGON.getPredicate());
- }
-
- private static final String rule = "Whenever {this} or another Dragon enters the battlefield under your control, it deals X damage to any target, where X is the number of Dragons you control.";
+ private static final FilterPermanent filter = new FilterPermanent(SubType.DRAGON, "Dragon");
public ScourgeOfValkas(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}{R}");
@@ -45,16 +42,17 @@ public final class ScourgeOfValkas extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// Whenever Scourge of Valkas or another Dragon enters the battlefield under your control, it deals X damage to any target, where X is the number of Dragons you control.
- Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new ScourgeOfValkasDamageEffect(), filter, false, rule);
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new ScourgeOfValkasDamageEffect(), filter, false, true
+ );
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
// {R}: Scourge of Valkas gets +1/+0 until end of turn.
- this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}")));
-
+ this.addAbility(new SimpleActivatedAbility(new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{R}")));
}
- public ScourgeOfValkas(final ScourgeOfValkas card) {
+ private ScourgeOfValkas(final ScourgeOfValkas card) {
super(card);
}
@@ -66,12 +64,14 @@ public final class ScourgeOfValkas extends CardImpl {
class ScourgeOfValkasDamageEffect extends OneShotEffect {
- public ScourgeOfValkasDamageEffect() {
+ private static final FilterPermanent filter = new FilterControlledPermanent(SubType.DRAGON, "");
+
+ ScourgeOfValkasDamageEffect() {
super(Outcome.Damage);
this.staticText = "it deals X damage to any target, where X is the number of Dragons you control";
}
- public ScourgeOfValkasDamageEffect(final ScourgeOfValkasDamageEffect effect) {
+ private ScourgeOfValkasDamageEffect(final ScourgeOfValkasDamageEffect effect) {
super(effect);
}
@@ -84,24 +84,23 @@ class ScourgeOfValkasDamageEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent enteringDragon = (Permanent) getValue("permanentEnteringBattlefield");
- if (controller != null && enteringDragon != null) {
- FilterPermanent filter = new FilterPermanent();
- filter.add(SubType.DRAGON.getPredicate());
- int dragons = game.getBattlefield().countAll(filter, source.getControllerId(), game);
- if (dragons > 0) {
- Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
- if (permanent != null) {
- permanent.damage(dragons, enteringDragon.getId(), game, false, true);
- } else {
- Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
- if (player != null
- && player.isInGame()) {
- player.damage(dragons, enteringDragon.getId(), game);
- }
- }
- }
+ if (controller == null || enteringDragon == null) {
+ return false;
+ }
+ int dragons = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
+ if (dragons < 1) {
return true;
}
- return false;
+ Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
+ if (permanent != null) {
+ permanent.damage(dragons, enteringDragon.getId(), game, false, true);
+ } else {
+ Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
+ if (player != null
+ && player.isInGame()) {
+ player.damage(dragons, enteringDragon.getId(), game);
+ }
+ }
+ return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/s/Scragnoth.java b/Mage.Sets/src/mage/cards/s/Scragnoth.java
index c6497821d74..d1a5604e187 100644
--- a/Mage.Sets/src/mage/cards/s/Scragnoth.java
+++ b/Mage.Sets/src/mage/cards/s/Scragnoth.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.keyword.ProtectionAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class Scragnoth extends CardImpl {
this.toughness = new MageInt(4);
// Scragnoth can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Protection from blue
this.addAbility(ProtectionAbility.from(ObjectColor.BLUE));
}
diff --git a/Mage.Sets/src/mage/cards/s/ScrapyardMongrel.java b/Mage.Sets/src/mage/cards/s/ScrapyardMongrel.java
index dc4727c6409..412f2bf00fa 100644
--- a/Mage.Sets/src/mage/cards/s/ScrapyardMongrel.java
+++ b/Mage.Sets/src/mage/cards/s/ScrapyardMongrel.java
@@ -26,7 +26,7 @@ public final class ScrapyardMongrel extends CardImpl {
public ScrapyardMongrel(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.color.setRed(true);
this.power = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/s/ScreamingShield.java b/Mage.Sets/src/mage/cards/s/ScreamingShield.java
index a31cb67e01a..0e37473c597 100644
--- a/Mage.Sets/src/mage/cards/s/ScreamingShield.java
+++ b/Mage.Sets/src/mage/cards/s/ScreamingShield.java
@@ -37,7 +37,7 @@ public final class ScreamingShield extends CardImpl {
Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(0, 3));
ability.addEffect(new GainAbilityAttachedEffect(
toAdd, AttachmentType.EQUIPMENT
- ).setText("and has \"{2}, {T}: Target player puts the top three cards of their library into their graveyard.\""));
+ ).setText("and has \"{2}, {T}: Target player mills three cards.\""));
this.addAbility(ability);
// Equip {3}
diff --git a/Mage.Sets/src/mage/cards/s/ScreechingBuzzard.java b/Mage.Sets/src/mage/cards/s/ScreechingBuzzard.java
index 0c4e2296165..a3424b3e168 100644
--- a/Mage.Sets/src/mage/cards/s/ScreechingBuzzard.java
+++ b/Mage.Sets/src/mage/cards/s/ScreechingBuzzard.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.discard.DiscardEachPlayerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class ScreechingBuzzard extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Screeching Buzzard dies, each opponent discards a card.
- this.addAbility(new DiesTriggeredAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT), false));
}
public ScreechingBuzzard(final ScreechingBuzzard card) {
diff --git a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java
index da04611f60d..87a8f4c538c 100644
--- a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java
+++ b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java
@@ -1,7 +1,6 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
@@ -14,16 +13,15 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
+import java.util.UUID;
+
/**
- *
* @author ayratn
*/
public final class ScreechingSilcaw extends CardImpl {
- private static final String rule = "Metalcraft — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard.";
-
public ScreechingSilcaw(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.BIRD);
this.power = new MageInt(1);
@@ -33,8 +31,11 @@ public final class ScreechingSilcaw extends CardImpl {
//"Metalcraft — Whenever Screeching Silcaw deals combat damage to a player, if you control three or more artifacts, that player puts the top four cards of their library into their graveyard.
TriggeredAbility conditional = new ConditionalInterveningIfTriggeredAbility(
- new DealsCombatDamageToAPlayerTriggeredAbility(new PutLibraryIntoGraveTargetEffect(4), false, true),
- MetalcraftCondition.instance, rule);
+ new DealsCombatDamageToAPlayerTriggeredAbility(
+ new PutLibraryIntoGraveTargetEffect(4), false, true
+ ), MetalcraftCondition.instance, "Metalcraft — Whenever {this} " +
+ "deals combat damage to a player, if you control three or more artifacts, that player mills four cards."
+ );
this.addAbility(conditional);
}
diff --git a/Mage.Sets/src/mage/cards/s/ScreechingSliver.java b/Mage.Sets/src/mage/cards/s/ScreechingSliver.java
index 908ef9eda5e..c91946e029b 100644
--- a/Mage.Sets/src/mage/cards/s/ScreechingSliver.java
+++ b/Mage.Sets/src/mage/cards/s/ScreechingSliver.java
@@ -37,7 +37,7 @@ public final class ScreechingSliver extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield,
- allSliversFilter, "All Slivers have \"{T}: Target player puts the top card of their library into their graveyard.\"")));
+ allSliversFilter, "All Slivers have \"{T}: Target player mills a card.\"")));
}
public ScreechingSliver(final ScreechingSliver card) {
diff --git a/Mage.Sets/src/mage/cards/s/ScuttlingDoomEngine.java b/Mage.Sets/src/mage/cards/s/ScuttlingDoomEngine.java
index acb9f784d43..52469546ce5 100644
--- a/Mage.Sets/src/mage/cards/s/ScuttlingDoomEngine.java
+++ b/Mage.Sets/src/mage/cards/s/ScuttlingDoomEngine.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleEvasionAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
@@ -41,7 +41,7 @@ public final class ScuttlingDoomEngine extends CardImpl {
// Scuttling Doom Engine can't be blocked by creatures with power 2 or less.
this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield)));
// When Scuttling Doom Engine dies, it deals 6 damage to target opponnent
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(6, "it"), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(6, "it"), false);
ability.addTarget(new TargetOpponentOrPlaneswalker());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/SearchTheCity.java b/Mage.Sets/src/mage/cards/s/SearchTheCity.java
index 57ad86e633e..0522121de16 100644
--- a/Mage.Sets/src/mage/cards/s/SearchTheCity.java
+++ b/Mage.Sets/src/mage/cards/s/SearchTheCity.java
@@ -157,7 +157,7 @@ class SearchTheCityExiledCardToHandEffect extends OneShotEffect {
ExileZone searchTheCityExileZone = game.getExile().getExileZone(source.getSourceId());
if (cardName != null && searchTheCityExileZone != null) {
for (Card card : searchTheCityExileZone.getCards(game)) {
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
if (card.moveToZone(Zone.HAND, source.getSourceId(), game, true)) {
game.informPlayers("Search the City: put " + card.getName() + " into owner's hand");
}
diff --git a/Mage.Sets/src/mage/cards/s/SeasonedHallowblade.java b/Mage.Sets/src/mage/cards/s/SeasonedHallowblade.java
new file mode 100644
index 00000000000..5d20277ce9b
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SeasonedHallowblade.java
@@ -0,0 +1,47 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.DiscardCardCost;
+import mage.abilities.effects.common.TapSourceEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.IndestructibleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SeasonedHallowblade extends CardImpl {
+
+ public SeasonedHallowblade(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WARRIOR);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(1);
+
+ // Discard a card: Tap Seasoned Hallowblade. It gains indestructible until end of turn.
+ Ability ability = new SimpleActivatedAbility(new TapSourceEffect(), new DiscardCardCost());
+ ability.addEffect(new GainAbilitySourceEffect(
+ IndestructibleAbility.getInstance(), Duration.EndOfTurn
+ ).setText("It gains indestructible until end of turn"));
+ this.addAbility(ability);
+ }
+
+ private SeasonedHallowblade(final SeasonedHallowblade card) {
+ super(card);
+ }
+
+ @Override
+ public SeasonedHallowblade copy() {
+ return new SeasonedHallowblade(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SeasonedPyromancer.java b/Mage.Sets/src/mage/cards/s/SeasonedPyromancer.java
index 5aed1a1767e..f1e705b89d0 100644
--- a/Mage.Sets/src/mage/cards/s/SeasonedPyromancer.java
+++ b/Mage.Sets/src/mage/cards/s/SeasonedPyromancer.java
@@ -16,7 +16,7 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
-import mage.game.permanent.token.YoungPyromancerElementalToken;
+import mage.game.permanent.token.RedElementalToken;
import mage.players.Player;
import java.util.UUID;
@@ -40,7 +40,7 @@ public final class SeasonedPyromancer extends CardImpl {
// {3}{R}{R}, Exile Seasoned Pyromancer from your graveyard: Create two 1/1 red Elemental creature tokens.
Ability ability = new SimpleActivatedAbility(
Zone.GRAVEYARD,
- new CreateTokenEffect(new YoungPyromancerElementalToken(), 2),
+ new CreateTokenEffect(new RedElementalToken(), 2),
new ManaCostsImpl("{3}{R}{R}")
);
ability.addCost(new ExileSourceFromGraveCost());
@@ -88,7 +88,7 @@ class SeasonedPyromancerEffect extends OneShotEffect {
if (nonlands == 0) {
return true;
}
- new YoungPyromancerElementalToken().putOntoBattlefield(
+ new RedElementalToken().putOntoBattlefield(
nonlands, game, source.getSourceId(), source.getControllerId()
);
return true;
diff --git a/Mage.Sets/src/mage/cards/s/SecureTheScene.java b/Mage.Sets/src/mage/cards/s/SecureTheScene.java
new file mode 100644
index 00000000000..60a79e6f4ad
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SecureTheScene.java
@@ -0,0 +1,68 @@
+package mage.cards.s;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.ExileTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.game.permanent.token.SoldierToken;
+import mage.game.permanent.token.Token;
+import mage.target.common.TargetNonlandPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SecureTheScene extends CardImpl {
+
+ public SecureTheScene(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}");
+
+ // Exile target nonland permanent. Its controller creates a 1/1 white Soldier creature token.
+ this.getSpellAbility().addEffect(new ExileTargetEffect());
+ this.getSpellAbility().addEffect(new SecureTheSceneEffect());
+ this.getSpellAbility().addTarget(new TargetNonlandPermanent());
+ }
+
+ private SecureTheScene(final SecureTheScene card) {
+ super(card);
+ }
+
+ @Override
+ public SecureTheScene copy() {
+ return new SecureTheScene(this);
+ }
+}
+
+class SecureTheSceneEffect extends OneShotEffect {
+
+ private static final Token token = new SoldierToken();
+
+ SecureTheSceneEffect() {
+ super(Outcome.PutCreatureInPlay);
+ this.staticText = "Its controller creates a 1/1 white Soldier creature token";
+ }
+
+ private SecureTheSceneEffect(final SecureTheSceneEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public SecureTheSceneEffect copy() {
+ return new SecureTheSceneEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Permanent permanent = game.getPermanentOrLKIBattlefield(source.getFirstTarget());
+ if (permanent == null) {
+ return false;
+ }
+ return token.putOntoBattlefield(1, game, source.getSourceId(), permanent.getControllerId());
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SeeTheTruth.java b/Mage.Sets/src/mage/cards/s/SeeTheTruth.java
new file mode 100644
index 00000000000..d348423e466
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SeeTheTruth.java
@@ -0,0 +1,82 @@
+package mage.cards.s;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.OneShotEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.Cards;
+import mage.cards.CardsImpl;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.common.TargetCardInLibrary;
+
+import java.util.UUID;
+import mage.filter.FilterCard;
+import mage.game.stack.Spell;
+
+/**
+ * @author TheElk801
+ */
+public final class SeeTheTruth extends CardImpl {
+
+ public SeeTheTruth(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}");
+
+ // Look at the top three cards of your library. Put one of those cards into your hand and the rest on the bottom of your library in any order. If this spell was cast from anywhere other than your hand, put each of those cards into your hand instead.
+ this.getSpellAbility().addEffect(new SeeTheTruthEffect());
+ }
+
+ private SeeTheTruth(final SeeTheTruth card) {
+ super(card);
+ }
+
+ @Override
+ public SeeTheTruth copy() {
+ return new SeeTheTruth(this);
+ }
+}
+
+class SeeTheTruthEffect extends OneShotEffect {
+
+ SeeTheTruthEffect() {
+ super(Outcome.Benefit);
+ staticText = "Look at the top three cards of your library. "
+ + "Put one of those cards into your hand and the rest on the bottom of your library in any order. "
+ + "If this spell was cast from anywhere other than your hand, "
+ + "put each of those cards into your hand instead.";
+ }
+
+ private SeeTheTruthEffect(final SeeTheTruthEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public SeeTheTruthEffect copy() {
+ return new SeeTheTruthEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ Player player = game.getPlayer(source.getControllerId());
+ Spell sourceSpell = game.getStack().getSpell(source.getId()); // Use id to get the correct spell in case of copied spells
+ if (player == null || sourceSpell == null) {
+ return false;
+ }
+ Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 3));
+ if (!cards.isEmpty()) {
+ if (sourceSpell.isCopy() || Zone.HAND.equals(sourceSpell.getFromZone())) { // A copied spell was NOT cast at all
+ TargetCardInLibrary target = new TargetCardInLibrary(new FilterCard("card to put into your hand"));
+ player.chooseTarget(outcome, cards, target, source, game);
+ cards.removeIf(target.getFirstTarget()::equals);
+ player.moveCards(game.getCard(target.getFirstTarget()), Zone.HAND, source, game);
+ player.putCardsOnBottomOfLibrary(cards, game, source, true);
+ } else {
+ player.moveCards(cards, Zone.HAND, source, game);
+ }
+ }
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SeedGuardian.java b/Mage.Sets/src/mage/cards/s/SeedGuardian.java
index ade4624f249..c268d4e1762 100644
--- a/Mage.Sets/src/mage/cards/s/SeedGuardian.java
+++ b/Mage.Sets/src/mage/cards/s/SeedGuardian.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.ReachAbility;
@@ -32,7 +32,7 @@ public final class SeedGuardian extends CardImpl {
// Reach
this.addAbility(ReachAbility.getInstance());
// When Seed Guardian dies, create an X/X green Elemental creature token, where X is the number of creature cards in your graveyard.
- this.addAbility(new DiesTriggeredAbility(new SeedGuardianEffect(), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new SeedGuardianEffect(), false));
}
public SeedGuardian(final SeedGuardian card) {
diff --git a/Mage.Sets/src/mage/cards/s/SeedguideAsh.java b/Mage.Sets/src/mage/cards/s/SeedguideAsh.java
index 660b6695dc9..cdb05821090 100644
--- a/Mage.Sets/src/mage/cards/s/SeedguideAsh.java
+++ b/Mage.Sets/src/mage/cards/s/SeedguideAsh.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -33,7 +33,7 @@ public final class SeedguideAsh extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// When Seedguide Ash dies, you may search your library for up to three Forest cards and put them onto the battlefield tapped. If you do, shuffle your library.
- this.addAbility(new DiesTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 3, filter), true, false, Outcome.PutLandInPlay), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 3, filter), true, false, Outcome.PutLandInPlay), true));
}
public SeedguideAsh(final SeedguideAsh card) {
diff --git a/Mage.Sets/src/mage/cards/s/SelflessSavior.java b/Mage.Sets/src/mage/cards/s/SelflessSavior.java
new file mode 100644
index 00000000000..fe9c603a64e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SelflessSavior.java
@@ -0,0 +1,56 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.SacrificeSourceCost;
+import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.keyword.IndestructibleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.permanent.AnotherPredicate;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SelflessSavior extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterControlledCreaturePermanent("another target creature");
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ }
+
+ public SelflessSavior(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
+
+ this.subtype.add(SubType.DOG);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ // Sacrifice Selfless Savior: Another target creature gains indestructible until end of turn.
+ Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(
+ IndestructibleAbility.getInstance(), Duration.EndOfTurn
+ ), new SacrificeSourceCost());
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(ability);
+ }
+
+ private SelflessSavior(final SelflessSavior card) {
+ super(card);
+ }
+
+ @Override
+ public SelflessSavior copy() {
+ return new SelflessSavior(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SellSwordBrute.java b/Mage.Sets/src/mage/cards/s/SellSwordBrute.java
index 3048cc10ae0..bdf0bae886f 100644
--- a/Mage.Sets/src/mage/cards/s/SellSwordBrute.java
+++ b/Mage.Sets/src/mage/cards/s/SellSwordBrute.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class SellSwordBrute extends CardImpl {
this.toughness = new MageInt(2);
// When Sell-Sword Brute dies, it deals 2 damage to you.
- this.addAbility(new DiesTriggeredAbility(new DamageControllerEffect(2, "it"), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DamageControllerEffect(2, "it"), false));
}
public SellSwordBrute(final SellSwordBrute card) {
diff --git a/Mage.Sets/src/mage/cards/s/SenatorLottDod.java b/Mage.Sets/src/mage/cards/s/SenatorLottDod.java
index 2c6f13cddcc..e771d963c34 100644
--- a/Mage.Sets/src/mage/cards/s/SenatorLottDod.java
+++ b/Mage.Sets/src/mage/cards/s/SenatorLottDod.java
@@ -53,7 +53,7 @@ class SenatorLottDodSpellsTargetingCreatureCostReductionEffect extends CostModif
public SenatorLottDodSpellsTargetingCreatureCostReductionEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- this.staticText = "Spell your opponents cast that target a creature you control cost {1} more to cast.";
+ this.staticText = "Spell your opponents cast that target a creature you control cost {1} more to cast";
}
protected SenatorLottDodSpellsTargetingCreatureCostReductionEffect(SenatorLottDodSpellsTargetingCreatureCostReductionEffect effect) {
@@ -96,7 +96,7 @@ class SenatorLottDodSpellsTargetingYouCostReductionEffect extends CostModificati
public SenatorLottDodSpellsTargetingYouCostReductionEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- this.staticText = "Spells your opponents cast that target you cost {2} more to cast.";
+ this.staticText = "Spells your opponents cast that target you cost {2} more to cast";
}
protected SenatorLottDodSpellsTargetingYouCostReductionEffect(SenatorLottDodSpellsTargetingYouCostReductionEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/s/SengirAutocrat.java b/Mage.Sets/src/mage/cards/s/SengirAutocrat.java
index 7420097d0af..89b3deabc17 100644
--- a/Mage.Sets/src/mage/cards/s/SengirAutocrat.java
+++ b/Mage.Sets/src/mage/cards/s/SengirAutocrat.java
@@ -1,9 +1,6 @@
-
package mage.cards.s;
-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.common.CreateTokenEffect;
@@ -12,17 +9,18 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.FilterPermanent;
import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.permanent.token.SerfToken;
+import java.util.UUID;
+
/**
- *
* @author Quercitron
*/
public final class SengirAutocrat extends CardImpl {
- private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Serf tokens");
+ private static final FilterPermanent filter = new FilterPermanent("Serf tokens");
static {
filter.add(SubType.SERF.getPredicate());
@@ -37,11 +35,10 @@ public final class SengirAutocrat extends CardImpl {
this.toughness = new MageInt(2);
// When Sengir Autocrat enters the battlefield, create three 0/1 black Serf creature tokens.
- Ability ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SerfToken(), 3));
- this.addAbility(ability);
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SerfToken(), 3)));
+
// When Sengir Autocrat leaves the battlefield, exile all Serf tokens.
- ability = new LeavesBattlefieldTriggeredAbility(new ExileAllEffect(filter), false);
- this.addAbility(ability);
+ this.addAbility(new LeavesBattlefieldTriggeredAbility(new ExileAllEffect(filter), false));
}
public SengirAutocrat(final SengirAutocrat card) {
diff --git a/Mage.Sets/src/mage/cards/s/SereneRemembrance.java b/Mage.Sets/src/mage/cards/s/SereneRemembrance.java
index b805b2f3b54..d674b47ff88 100644
--- a/Mage.Sets/src/mage/cards/s/SereneRemembrance.java
+++ b/Mage.Sets/src/mage/cards/s/SereneRemembrance.java
@@ -8,7 +8,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInASingleGraveyard;
@@ -23,10 +23,9 @@ public final class SereneRemembrance extends CardImpl {
public SereneRemembrance(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}");
-
// Shuffle Serene Remembrance and up to three target cards from a single graveyard into their owners' libraries.
this.getSpellAbility().addEffect(new SereneRemembranceEffect());
- this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, new FilterCard("up to three target cards from a single graveyard")));
+ this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 3, StaticFilters.FILTER_CARD_CARDS));
}
@@ -68,7 +67,6 @@ class SereneRemembranceEffect extends OneShotEffect {
for (Player player : game.getPlayers().values()) {
if (player.getGraveyard().contains(card.getId())) {
graveyardPlayer = player;
- player.getGraveyard().remove(card);
result |= card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
}
}
diff --git a/Mage.Sets/src/mage/cards/s/SerratedScorpion.java b/Mage.Sets/src/mage/cards/s/SerratedScorpion.java
index 425cc67965d..f95e3077efa 100644
--- a/Mage.Sets/src/mage/cards/s/SerratedScorpion.java
+++ b/Mage.Sets/src/mage/cards/s/SerratedScorpion.java
@@ -2,7 +2,7 @@ package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamagePlayersEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
@@ -26,7 +26,7 @@ public final class SerratedScorpion extends CardImpl {
this.toughness = new MageInt(2);
// When Serrated Scorpion dies, it deals 2 damage to each opponent and you gain 2 life.
- Ability ability = new DiesTriggeredAbility(new DamagePlayersEffect(
+ Ability ability = new DiesSourceTriggeredAbility(new DamagePlayersEffect(
2, TargetController.OPPONENT, "it"
));
ability.addEffect(new GainLifeEffect(2).concatBy("and"));
diff --git a/Mage.Sets/src/mage/cards/s/SerumRaker.java b/Mage.Sets/src/mage/cards/s/SerumRaker.java
index 2ccbb515931..9055a92de9e 100644
--- a/Mage.Sets/src/mage/cards/s/SerumRaker.java
+++ b/Mage.Sets/src/mage/cards/s/SerumRaker.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.discard.DiscardEachPlayerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -25,7 +25,7 @@ public final class SerumRaker extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(2);
this.addAbility(FlyingAbility.getInstance());
- this.addAbility(new DiesTriggeredAbility(new DiscardEachPlayerEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new DiscardEachPlayerEffect()));
}
public SerumRaker (final SerumRaker card) {
diff --git a/Mage.Sets/src/mage/cards/s/SerumTank.java b/Mage.Sets/src/mage/cards/s/SerumTank.java
index 59b4f5bbbe1..52875eee5c0 100644
--- a/Mage.Sets/src/mage/cards/s/SerumTank.java
+++ b/Mage.Sets/src/mage/cards/s/SerumTank.java
@@ -1,48 +1,44 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.TriggeredAbilityImpl;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.Effect;
+import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Zone;
import mage.counters.CounterType;
-import mage.game.Game;
-import mage.game.events.GameEvent;
-import mage.game.permanent.Permanent;
-import mage.target.targetpointer.FixedTarget;
+import mage.filter.StaticFilters;
+
+import java.util.UUID;
/**
- *
* @author CountAndromalius
*/
public final class SerumTank extends CardImpl {
public SerumTank(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// Whenever {this} or another artifact comes into play, put a charge counter on {this}.
- Effect effect = new AddCountersSourceEffect(CounterType.CHARGE.createInstance());
- effect.setText("put a charge counter on {this}");
- this.addAbility(new SerumTankTriggeredAbility(effect));
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), StaticFilters.FILTER_PERMANENT_ARTIFACT
+ ));
// {3}, {tap}, Remove a charge counter from {this}: Draw a card.
- Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{3}"));
- ability.addCost(new RemoveCountersSourceCost(CounterType.CHARGE.createInstance(1)));
+ Ability ability = new SimpleActivatedAbility(
+ new DrawCardSourceControllerEffect(1), new GenericManaCost(3)
+ );
ability.addCost(new TapSourceCost());
+ ability.addCost(new RemoveCountersSourceCost(CounterType.CHARGE.createInstance()));
this.addAbility(ability);
}
- public SerumTank(final SerumTank card) {
+ private SerumTank(final SerumTank card) {
super(card);
}
@@ -51,42 +47,3 @@ public final class SerumTank extends CardImpl {
return new SerumTank(this);
}
}
-
-class SerumTankTriggeredAbility extends TriggeredAbilityImpl {
-
- SerumTankTriggeredAbility(Effect effect) {
- super(Zone.BATTLEFIELD, effect, false);
- }
-
- SerumTankTriggeredAbility(final SerumTankTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public SerumTankTriggeredAbility copy() {
- return new SerumTankTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- UUID targetId = event.getTargetId();
- Permanent permanent = game.getPermanent(targetId);
- if (permanent.isArtifact()) {
- for (Effect effect : this.getEffects()) {
- effect.setTargetPointer(new FixedTarget(permanent, game));
- }
- return true;
- }
- return false;
- }
-
- @Override
- public String getRule() {
- return "Whenever {this} or another artifact enters the battlefield, put a charge counter on {this}.";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/s/ServantOfTheScale.java b/Mage.Sets/src/mage/cards/s/ServantOfTheScale.java
index 32aaf50a85a..f6454d2975c 100644
--- a/Mage.Sets/src/mage/cards/s/ServantOfTheScale.java
+++ b/Mage.Sets/src/mage/cards/s/ServantOfTheScale.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@@ -40,7 +40,7 @@ public final class ServantOfTheScale extends CardImpl {
"with a +1/+1 counter on it"));
// When Servant of the Scale dies, put X +1/+1 counters on target creature you control, where X is the number of +1/+1 counter on Servant of the Scale.
- Ability ability = new DiesTriggeredAbility(new ServantOfTheScaleEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new ServantOfTheScaleEffect(), false);
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/SethronHurloonGeneral.java b/Mage.Sets/src/mage/cards/s/SethronHurloonGeneral.java
new file mode 100644
index 00000000000..596757a7dd0
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SethronHurloonGeneral.java
@@ -0,0 +1,76 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.continuous.BoostControlledEffect;
+import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
+import mage.abilities.keyword.HasteAbility;
+import mage.abilities.keyword.MenaceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.SuperType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.permanent.TokenPredicate;
+import mage.game.permanent.token.MinotaurToken;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SethronHurloonGeneral extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterPermanent(SubType.MINOTAUR, "nontoken Minotaur");
+ private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(SubType.MINOTAUR, "");
+ private static final FilterPermanent filter3 = new FilterPermanent(SubType.MINOTAUR, "");
+
+ static {
+ filter.add(Predicates.not(TokenPredicate.instance));
+ }
+
+ public SethronHurloonGeneral(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.MINOTAUR);
+ this.subtype.add(SubType.WARRIOR);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(4);
+
+ // Whenever Sethron, Hurloon General or another nontoken Minotaur enters the battlefield under your control, create a 2/3 red Minotaur creature token.
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new CreateTokenEffect(new MinotaurToken()), filter, false, true
+ ));
+
+ // {2}{B/R}: Minotaurs you control get +1/+0 and gain menace and haste until end of turn.
+ Ability ability = new SimpleActivatedAbility(new BoostControlledEffect(
+ 1, 0, Duration.EndOfTurn, filter2
+ ).setText("Minotaurs you control get +1/+0"), new ManaCostsImpl("{2}{B/R}"));
+ ability.addEffect(new GainAbilityControlledEffect(
+ new MenaceAbility(), Duration.EndOfTurn, filter3
+ ).setText("and gain menace"));
+ ability.addEffect(new GainAbilityControlledEffect(
+ HasteAbility.getInstance(), Duration.EndOfTurn, filter3
+ ).setText("and haste until end of turn"));
+ this.addAbility(ability);
+ }
+
+ private SethronHurloonGeneral(final SethronHurloonGeneral card) {
+ super(card);
+ }
+
+ @Override
+ public SethronHurloonGeneral copy() {
+ return new SethronHurloonGeneral(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SewerNemesis.java b/Mage.Sets/src/mage/cards/s/SewerNemesis.java
index 7bfc1fa2fca..612a44b550f 100644
--- a/Mage.Sets/src/mage/cards/s/SewerNemesis.java
+++ b/Mage.Sets/src/mage/cards/s/SewerNemesis.java
@@ -114,7 +114,7 @@ class SewerNemesisTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever the chosen player casts a spell, that player puts the top card of their library into their graveyard.";
+ return "Whenever the chosen player casts a spell, that player mills a card.";
}
@Override
diff --git a/Mage.Sets/src/mage/cards/s/ShaakHerd.java b/Mage.Sets/src/mage/cards/s/ShaakHerd.java
index 96f3933057f..16852ebec07 100644
--- a/Mage.Sets/src/mage/cards/s/ShaakHerd.java
+++ b/Mage.Sets/src/mage/cards/s/ShaakHerd.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -33,7 +33,7 @@ public final class ShaakHerd extends CardImpl {
this.toughness = new MageInt(2);
// When Shaak Herd dies, you may return another target creature card from your graveyard to your hand.
- Ability ability = new DiesTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), true);
+ Ability ability = new DiesSourceTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), true);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/Shacklegeist.java b/Mage.Sets/src/mage/cards/s/Shacklegeist.java
new file mode 100644
index 00000000000..d5a633beca6
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/Shacklegeist.java
@@ -0,0 +1,65 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.CanBlockOnlyFlyingAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.TapTargetCost;
+import mage.abilities.effects.common.TapTargetEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.StaticFilters;
+import mage.filter.common.FilterControlledPermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.permanent.TappedPredicate;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetControlledPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class Shacklegeist extends CardImpl {
+
+ private static final FilterControlledPermanent filter
+ = new FilterControlledPermanent("untapped Spirits you control");
+
+ static {
+ filter.add(Predicates.not(TappedPredicate.instance));
+ filter.add(SubType.SPIRIT.getPredicate());
+ }
+
+ public Shacklegeist(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
+
+ this.subtype.add(SubType.SPIRIT);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Shacklegeist can block only creatures with flying.
+ this.addAbility(new CanBlockOnlyFlyingAbility());
+
+ // Tap two untapped Spirits you control: Tap target creature you don't control.
+ Ability ability = new SimpleActivatedAbility(
+ new TapTargetEffect(), new TapTargetCost(new TargetControlledPermanent(2, filter))
+ );
+ ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL));
+ this.addAbility(ability);
+ }
+
+ private Shacklegeist(final Shacklegeist card) {
+ super(card);
+ }
+
+ @Override
+ public Shacklegeist copy() {
+ return new Shacklegeist(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/ShadowSlice.java b/Mage.Sets/src/mage/cards/s/ShadowSlice.java
index a3ea77c054f..7a25b54a7a4 100644
--- a/Mage.Sets/src/mage/cards/s/ShadowSlice.java
+++ b/Mage.Sets/src/mage/cards/s/ShadowSlice.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.effects.common.CipherEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.cards.CardImpl;
@@ -9,15 +7,15 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class ShadowSlice extends CardImpl {
- public ShadowSlice (UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}");
-
+ public ShadowSlice(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}");
// Target Opponent loses 3 life.
this.getSpellAbility().addEffect(new LoseLifeTargetEffect(3));
@@ -33,7 +31,7 @@ public final class ShadowSlice extends CardImpl {
}
@Override
- public ShadowSlice copy() {
+ public ShadowSlice copy() {
return new ShadowSlice(this);
}
}
diff --git a/Mage.Sets/src/mage/cards/s/ShamanOfThePack.java b/Mage.Sets/src/mage/cards/s/ShamanOfThePack.java
index 167160264fd..929b0d6e901 100644
--- a/Mage.Sets/src/mage/cards/s/ShamanOfThePack.java
+++ b/Mage.Sets/src/mage/cards/s/ShamanOfThePack.java
@@ -1,13 +1,12 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
+import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -16,8 +15,9 @@ import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class ShamanOfThePack extends CardImpl {
@@ -30,7 +30,7 @@ public final class ShamanOfThePack extends CardImpl {
}
public ShamanOfThePack(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{G}");
this.subtype.add(SubType.ELF);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(3);
@@ -41,6 +41,7 @@ public final class ShamanOfThePack extends CardImpl {
effect.setText("target opponent loses life equal to the number of Elves you control");
Ability ability = new EntersBattlefieldTriggeredAbility(effect, false);
ability.addTarget(new TargetOpponent());
+ ability.addHint(new ValueHint("Elves you control", new PermanentsOnBattlefieldCount(filter)));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/ShamblingGoblin.java b/Mage.Sets/src/mage/cards/s/ShamblingGoblin.java
index ed512bf60f0..83fdf692a4a 100644
--- a/Mage.Sets/src/mage/cards/s/ShamblingGoblin.java
+++ b/Mage.Sets/src/mage/cards/s/ShamblingGoblin.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -35,7 +35,7 @@ public final class ShamblingGoblin extends CardImpl {
this.toughness = new MageInt(1);
// When Shambling Goblin dies, target creature an opponent controls gets -1/-1 until end of turn.
- Ability ability = new DiesTriggeredAbility(new BoostTargetEffect(-1,-1, Duration.EndOfTurn));
+ Ability ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(-1,-1, Duration.EndOfTurn));
ability.addTarget(new TargetCreaturePermanent(filterOpponentCreature));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/s/ShamblingSwarm.java b/Mage.Sets/src/mage/cards/s/ShamblingSwarm.java
index 84d5681765e..c6f445e9ec6 100644
--- a/Mage.Sets/src/mage/cards/s/ShamblingSwarm.java
+++ b/Mage.Sets/src/mage/cards/s/ShamblingSwarm.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.DistributeCountersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -26,7 +26,7 @@ public final class ShamblingSwarm extends CardImpl {
this.toughness = new MageInt(3);
// When Shambling Swarm dies, distribute three -1/-1 counters among one, two, or three target creatures. For each -1/-1 counter you put on a creature this way, remove a -1/-1 counter from that creature at the beginning of the next end step.
- Ability ability = new DiesTriggeredAbility(new DistributeCountersEffect(CounterType.M1M1, 3, true, "one, two, or three target creatures"), false);
+ Ability ability = new DiesSourceTriggeredAbility(new DistributeCountersEffect(CounterType.M1M1, 3, true, "one, two, or three target creatures"), false);
ability.addTarget(new TargetCreaturePermanentAmount(3));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/ShapeStealer.java b/Mage.Sets/src/mage/cards/s/ShapeStealer.java
index d2bc6f976b5..d21b0e2c984 100644
--- a/Mage.Sets/src/mage/cards/s/ShapeStealer.java
+++ b/Mage.Sets/src/mage/cards/s/ShapeStealer.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
@@ -37,7 +37,7 @@ public final class ShapeStealer extends CardImpl {
// each one in succession. The first trigger put on the stack will be the last to resolve,
// so that will set Shape Stealer's final power and toughness.
// Whenever Shape Stealer blocks or becomes blocked by a creature, change Shape Stealer's base power and toughness to that creature's power and toughness until end of turn.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new ShapeStealerEffect(), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new ShapeStealerEffect(), false));
}
public ShapeStealer(final ShapeStealer card) {
diff --git a/Mage.Sets/src/mage/cards/s/SharedTrauma.java b/Mage.Sets/src/mage/cards/s/SharedTrauma.java
index 915bbbeeb15..2f82c35a9bd 100644
--- a/Mage.Sets/src/mage/cards/s/SharedTrauma.java
+++ b/Mage.Sets/src/mage/cards/s/SharedTrauma.java
@@ -43,7 +43,7 @@ class SharedTraumaEffect extends OneShotEffect {
public SharedTraumaEffect() {
super(Outcome.Detriment);
- this.staticText = "Join forces — Starting with you, each player may pay any amount of mana. Each player puts the top X cards of their library into their graveyard, where X is the total amount of mana paid this way";
+ this.staticText = "Join forces — Starting with you, each player may pay any amount of mana. Each player mills X cards, where X is the total amount of mana paid this way";
}
public SharedTraumaEffect(final SharedTraumaEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/s/SharkTyphoon.java b/Mage.Sets/src/mage/cards/s/SharkTyphoon.java
index 51346842858..8753458c499 100644
--- a/Mage.Sets/src/mage/cards/s/SharkTyphoon.java
+++ b/Mage.Sets/src/mage/cards/s/SharkTyphoon.java
@@ -31,7 +31,7 @@ public final class SharkTyphoon extends CardImpl {
// Whenever you cast a noncreature spell, create an X/X blue Shark creature token with flying, where X is that spell's converted mana cost.
this.addAbility(new SpellCastControllerTriggeredAbility(
- new SharkTyphoonCastEffect(), StaticFilters.FILTER_SPELL_A_NON_CREATURE, false
+ new SharkTyphoonCastEffect(), StaticFilters.FILTER_SPELL_A_NON_CREATURE, false, true
));
// Cycling {X}{1}{U}
@@ -69,7 +69,7 @@ class SharkTyphoonCastEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
- Spell spell = game.getSpell(targetPointer.getFirst(game, source));
+ Spell spell = game.getSpell(getTargetPointer().getFirst(game, source));
int xValue = 0;
if (spell != null) {
xValue = spell.getConvertedManaCost();
diff --git a/Mage.Sets/src/mage/cards/s/ShatterAssumptions.java b/Mage.Sets/src/mage/cards/s/ShatterAssumptions.java
index bea5cab22d0..09dc73af6fd 100644
--- a/Mage.Sets/src/mage/cards/s/ShatterAssumptions.java
+++ b/Mage.Sets/src/mage/cards/s/ShatterAssumptions.java
@@ -3,7 +3,9 @@ package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.*;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
@@ -83,17 +85,14 @@ class ShatterAssumptionsEffect extends OneShotEffect {
if (player == null) {
return false;
}
- Cards cards = new CardsImpl(player.getHand());
- player.revealCards(source, cards, game);
+ player.revealCards(source, player.getHand(), game);
FilterCard f;
if (colorless) {
f = filter;
} else {
f = filter2;
}
- for (Card card : cards.getCards(f, source.getSourceId(), source.getControllerId(), game)) {
- player.discard(card, source, game);
- }
+ player.discard(new CardsImpl(player.getHand().getCards(f, game)), source, game);
return true;
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java b/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java
index 5afe8b026cb..edc7d925e23 100644
--- a/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java
+++ b/Mage.Sets/src/mage/cards/s/ShieldsOfVelisVel.java
@@ -78,7 +78,7 @@ class ShieldsOfVelisVelGainEffect extends ContinuousEffectImpl {
for (Iterator it = affectedObjectList.iterator(); it.hasNext();) {
Permanent permanent = it.next().getPermanent(game);
if (permanent != null) {
- permanent.addAbility(ChangelingAbility.getInstance(), source.getSourceId(), game, false);
+ permanent.addAbility(ChangelingAbility.getInstance(), source.getSourceId(), game);
} else {
it.remove();
}
diff --git a/Mage.Sets/src/mage/cards/s/ShiftingCeratops.java b/Mage.Sets/src/mage/cards/s/ShiftingCeratops.java
index 6a501a6451f..efc57339c04 100644
--- a/Mage.Sets/src/mage/cards/s/ShiftingCeratops.java
+++ b/Mage.Sets/src/mage/cards/s/ShiftingCeratops.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
@@ -40,7 +40,7 @@ public final class ShiftingCeratops extends CardImpl {
this.toughness = new MageInt(4);
// This spell can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Protection from blue
this.addAbility(ProtectionAbility.from(ObjectColor.BLUE));
diff --git a/Mage.Sets/src/mage/cards/s/ShiftingShadow.java b/Mage.Sets/src/mage/cards/s/ShiftingShadow.java
index e181f37a9d7..5f9f1e72ba1 100644
--- a/Mage.Sets/src/mage/cards/s/ShiftingShadow.java
+++ b/Mage.Sets/src/mage/cards/s/ShiftingShadow.java
@@ -71,12 +71,12 @@ public final class ShiftingShadow extends CardImpl {
class ShiftingShadowEffect extends OneShotEffect {
- private UUID auraId;
+ private final UUID auraId;
public ShiftingShadowEffect(UUID auraId) {
super(Outcome.PutCreatureInPlay);
this.staticText = "destroy this creature. Reveal cards from the top of your library until you reveal a creature card. "
- + "Put that card onto the battlefield and attach Shifting Shadow to it, then put all other cards revealed this way on the bottom of your library in a random order";
+ + "Put that card onto the battlefield and attach {this} to it, then put all other cards revealed this way on the bottom of your library in a random order";
this.auraId = auraId;
}
@@ -107,6 +107,11 @@ class ShiftingShadowEffect extends OneShotEffect {
}
if (aura != null) {
enchanted.destroy(source.getSourceId(), game, false);
+ // Because this effect has two steps, we have to call the processAction method here, so that triggered effects of the target going to graveyard go to the stack
+ // If we don't do it here, gained triggered effects to the target will be removed from the following moveCards method and the applyEffcts done there.
+ // Example: {@link org.mage.test.commander.duel.MairsilThePretenderTest#MairsilThePretenderTest Test}
+ game.getState().processAction(game);
+
Cards revealed = new CardsImpl();
Cards otherCards = new CardsImpl();
for (Card card : controller.getLibrary().getCards(game)) {
diff --git a/Mage.Sets/src/mage/cards/s/ShipwreckDowser.java b/Mage.Sets/src/mage/cards/s/ShipwreckDowser.java
new file mode 100644
index 00000000000..b68abcb0976
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/ShipwreckDowser.java
@@ -0,0 +1,51 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
+import mage.abilities.keyword.ProwessAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterCard;
+import mage.filter.common.FilterInstantOrSorceryCard;
+import mage.target.common.TargetCardInYourGraveyard;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ShipwreckDowser extends CardImpl {
+
+ private static final FilterCard filter
+ = new FilterInstantOrSorceryCard("instant or sorcery card from your graveyard");
+
+ public ShipwreckDowser(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
+
+ this.subtype.add(SubType.MERFOLK);
+ this.subtype.add(SubType.WIZARD);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Prowess
+ this.addAbility(new ProwessAbility());
+
+ // When Shipwreck Dowser enters the battlefield, return target instant or sorcery card from your graveyard to your hand.
+ Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
+ ability.addTarget(new TargetCardInYourGraveyard(filter));
+ this.addAbility(ability);
+ }
+
+ private ShipwreckDowser(final ShipwreckDowser card) {
+ super(card);
+ }
+
+ @Override
+ public ShipwreckDowser copy() {
+ return new ShipwreckDowser(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/ShivanPhoenix.java b/Mage.Sets/src/mage/cards/s/ShivanPhoenix.java
index 33d1dca830b..80425ea158f 100644
--- a/Mage.Sets/src/mage/cards/s/ShivanPhoenix.java
+++ b/Mage.Sets/src/mage/cards/s/ShivanPhoenix.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class ShivanPhoenix extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Shivan Phoenix dies, return Shivan Phoenix to its owner's hand.
- this.addAbility(new DiesTriggeredAbility(new ReturnToHandSourceEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new ReturnToHandSourceEffect()));
}
public ShivanPhoenix(final ShivanPhoenix card) {
diff --git a/Mage.Sets/src/mage/cards/s/ShoalSerpent.java b/Mage.Sets/src/mage/cards/s/ShoalSerpent.java
index 8769d560813..73a060cff2e 100644
--- a/Mage.Sets/src/mage/cards/s/ShoalSerpent.java
+++ b/Mage.Sets/src/mage/cards/s/ShoalSerpent.java
@@ -67,7 +67,7 @@ class ShoalSerpentEffect extends ContinuousEffectImpl {
switch (layer) {
case AbilityAddingRemovingEffects_6:
if (sublayer == SubLayer.NA) {
- permanent.getAbilities().removeIf(entry -> entry.getId().equals(DefenderAbility.getInstance().getId()));
+ permanent.removeAbility(DefenderAbility.getInstance(), source.getSourceId(), game);
}
break;
}
diff --git a/Mage.Sets/src/mage/cards/s/Shocker.java b/Mage.Sets/src/mage/cards/s/Shocker.java
index e988fd2caff..176afefbf0e 100644
--- a/Mage.Sets/src/mage/cards/s/Shocker.java
+++ b/Mage.Sets/src/mage/cards/s/Shocker.java
@@ -1,28 +1,26 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.game.Game;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author markedagain
*/
public final class Shocker extends CardImpl {
public Shocker(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.INSECT);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
@@ -40,14 +38,15 @@ public final class Shocker extends CardImpl {
return new Shocker(this);
}
}
+
class ShockerEffect extends OneShotEffect {
- public ShockerEffect() {
+ ShockerEffect() {
super(Outcome.Discard);
this.staticText = " that player discards all the cards in their hand, then draws that many cards";
}
- public ShockerEffect(final ShockerEffect effect) {
+ private ShockerEffect(final ShockerEffect effect) {
super(effect);
}
@@ -59,14 +58,11 @@ class ShockerEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source));
- if (targetPlayer != null) {
- int count = targetPlayer.getHand().size();
- for (Card card : targetPlayer.getHand().getCards(game)) {
- targetPlayer.discard(card, source, game);
- }
- targetPlayer.drawCards(count, source.getSourceId(), game);
- return false;
- }
+ if (targetPlayer == null) {
+ return false;
+ }
+ int count = targetPlayer.discard(targetPlayer.getHand(), source, game).size();
+ targetPlayer.drawCards(count, source.getSourceId(), game);
return true;
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/s/Showstopper.java b/Mage.Sets/src/mage/cards/s/Showstopper.java
index b4c5fc75e89..8fbc3a3f4ba 100644
--- a/Mage.Sets/src/mage/cards/s/Showstopper.java
+++ b/Mage.Sets/src/mage/cards/s/Showstopper.java
@@ -1,9 +1,8 @@
-
package mage.cards.s;
import java.util.UUID;
import mage.abilities.TriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
@@ -34,10 +33,8 @@ public final class Showstopper extends CardImpl {
public Showstopper (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}{R}");
-
-
// Until end of turn, creatures you control gain "When this creature dies, it deals 2 damage to target creature an opponent controls."
- TriggeredAbility ability = new DiesTriggeredAbility(new DamageTargetEffect(2, "it"), false);
+ TriggeredAbility ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(2, "it"), false);
Target target = new TargetCreaturePermanent(filter2);
ability.addTarget(target);
Effect effect = new GainAbilityControlledEffect(ability, Duration.EndOfTurn, filter);
diff --git a/Mage.Sets/src/mage/cards/s/ShredMemory.java b/Mage.Sets/src/mage/cards/s/ShredMemory.java
index f84304230cf..d3005cd6300 100644
--- a/Mage.Sets/src/mage/cards/s/ShredMemory.java
+++ b/Mage.Sets/src/mage/cards/s/ShredMemory.java
@@ -1,27 +1,27 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.keyword.TransmuteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.filter.FilterCard;
+import mage.filter.StaticFilters;
import mage.target.common.TargetCardInASingleGraveyard;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class ShredMemory extends CardImpl {
public ShredMemory(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}");
// Exile up to four target cards from a single graveyard.
this.getSpellAbility().addEffect(new ExileTargetEffect());
- this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 4, new FilterCard("cards")));
+ this.getSpellAbility().addTarget(new TargetCardInASingleGraveyard(0, 4, StaticFilters.FILTER_CARD_CARDS));
+
// Transmute {1}{B}{B}
this.addAbility(new TransmuteAbility("{1}{B}{B}"));
}
diff --git a/Mage.Sets/src/mage/cards/s/Shriekgeist.java b/Mage.Sets/src/mage/cards/s/Shriekgeist.java
index fb41104d802..9c0b1c8c0d6 100644
--- a/Mage.Sets/src/mage/cards/s/Shriekgeist.java
+++ b/Mage.Sets/src/mage/cards/s/Shriekgeist.java
@@ -80,6 +80,6 @@ class ShriekgeistTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever {this} deals combat damage to a player, that player puts the top two cards of their library into their graveyard.";
+ return "Whenever {this} deals combat damage to a player, that player mills two cards.";
}
}
diff --git a/Mage.Sets/src/mage/cards/s/SickeningDreams.java b/Mage.Sets/src/mage/cards/s/SickeningDreams.java
index 3a74c9e7eec..ac2d709f11d 100644
--- a/Mage.Sets/src/mage/cards/s/SickeningDreams.java
+++ b/Mage.Sets/src/mage/cards/s/SickeningDreams.java
@@ -47,7 +47,7 @@ class SickeningDreamsAdditionalCost extends VariableCostImpl {
SickeningDreamsAdditionalCost() {
super("cards to discard");
- this.text = "as an additional cost to cast this spell, discard X cards";
+ this.text = "discard X cards";
}
SickeningDreamsAdditionalCost(final SickeningDreamsAdditionalCost cost) {
diff --git a/Mage.Sets/src/mage/cards/s/SidarKondoOfJamuraa.java b/Mage.Sets/src/mage/cards/s/SidarKondoOfJamuraa.java
index f3db71d472b..6bbd1ab410c 100644
--- a/Mage.Sets/src/mage/cards/s/SidarKondoOfJamuraa.java
+++ b/Mage.Sets/src/mage/cards/s/SidarKondoOfJamuraa.java
@@ -80,8 +80,8 @@ class SidarKondoOfJamuraaCantBlockCreaturesSourceEffect extends RestrictionEffec
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
- if (permanent.hasAbility(FlyingAbility.getInstance().getId(), game)
- || permanent.hasAbility(ReachAbility.getInstance().getId(), game)) {
+ if (permanent.hasAbility(FlyingAbility.getInstance(), game)
+ || permanent.hasAbility(ReachAbility.getInstance(), game)) {
return false;
}
return game.getOpponents(source.getControllerId()).contains(permanent.getControllerId());
diff --git a/Mage.Sets/src/mage/cards/s/SidisiBroodTyrant.java b/Mage.Sets/src/mage/cards/s/SidisiBroodTyrant.java
index 933cbb20ce9..b4bca16a137 100644
--- a/Mage.Sets/src/mage/cards/s/SidisiBroodTyrant.java
+++ b/Mage.Sets/src/mage/cards/s/SidisiBroodTyrant.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
@@ -73,13 +71,9 @@ class SidisiBroodTyrantTriggeredAbility extends TriggeredAbilityImpl {
if (zEvent != null && Zone.LIBRARY == zEvent.getFromZone() && Zone.GRAVEYARD == zEvent.getToZone() && zEvent.getCards() != null) {
for (Card card : zEvent.getCards()) {
if (card != null) {
-
UUID cardOwnerId = card.getOwnerId();
- Set cardType = card.getCardType();
-
if (cardOwnerId != null
&& card.isOwnedBy(getControllerId())
- && cardType != null
&& card.isCreature()) {
return true;
}
diff --git a/Mage.Sets/src/mage/cards/s/SiegeStriker.java b/Mage.Sets/src/mage/cards/s/SiegeStriker.java
new file mode 100644
index 00000000000..33bfd4cc6fb
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SiegeStriker.java
@@ -0,0 +1,99 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.keyword.DoubleStrikeAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.Predicates;
+import mage.filter.predicate.permanent.TappedPredicate;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author mikalinn777
+ */
+public final class SiegeStriker extends CardImpl {
+
+ public SiegeStriker(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.SOLDIER);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ // Double Strike
+ this.addAbility(DoubleStrikeAbility.getInstance());
+
+ // Whenever Siege Striker attacks, you may tap any number of untapped creatures you control. Siege Striker gets +1/+1 until end of turn for each creature tapped this way.
+ this.addAbility(new AttacksTriggeredAbility(
+ new SiegeStrikerEffect(), true
+ ));
+
+ }
+
+ public SiegeStriker(final SiegeStriker card) {
+ super(card);
+ }
+
+ @Override
+ public SiegeStriker copy() {
+ return new SiegeStriker(this);
+ }
+}
+
+class SiegeStrikerEffect extends OneShotEffect {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creatures you control");
+
+ static {
+ filter.add(TargetController.YOU.getControllerPredicate());
+ filter.add(Predicates.not(TappedPredicate.instance));
+ }
+
+ public SiegeStrikerEffect() {
+ super(Outcome.GainLife);
+ staticText = "you may tap any number of untapped creatures you control. "
+ + "{this} gets +1/+1 until end of turn for each creature tapped this way";
+ }
+
+ public SiegeStrikerEffect(SiegeStrikerEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ int tappedAmount = 0;
+ TargetCreaturePermanent target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true);
+ if (target.canChoose(source.getControllerId(), game)
+ && target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), game)) {
+ for (UUID creatureId : target.getTargets()) {
+ Permanent creature = game.getPermanent(creatureId);
+ if (creature != null) {
+ creature.tap(game);
+ tappedAmount++;
+ }
+ }
+ }
+ if (tappedAmount > 0) {
+ game.addEffect(new BoostSourceEffect(tappedAmount, tappedAmount, Duration.EndOfTurn), source);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public SiegeStrikerEffect copy() {
+ return new SiegeStrikerEffect(this);
+ }
+
+}
diff --git a/Mage.Sets/src/mage/cards/s/SigiledContender.java b/Mage.Sets/src/mage/cards/s/SigiledContender.java
new file mode 100644
index 00000000000..9e89d6bf837
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SigiledContender.java
@@ -0,0 +1,50 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.SourceHasCounterCondition;
+import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SigiledContender extends CardImpl {
+
+ private static final Condition condition = new SourceHasCounterCondition(CounterType.P1P1);
+
+ public SigiledContender(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WARRIOR);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Sigiled Contender has lifelink as long as it has a +1/+1 counter on it.
+ this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
+ new GainAbilitySourceEffect(
+ LifelinkAbility.getInstance(), Duration.WhileOnBattlefield
+ ), condition, "{this} has lifelink as long as it has a +1/+1 counter on it"
+ )));
+ }
+
+ private SigiledContender(final SigiledContender card) {
+ super(card);
+ }
+
+ @Override
+ public SigiledContender copy() {
+ return new SigiledContender(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SilentChantZubera.java b/Mage.Sets/src/mage/cards/s/SilentChantZubera.java
index b2d0ec1e0bc..b3d36bc8428 100644
--- a/Mage.Sets/src/mage/cards/s/SilentChantZubera.java
+++ b/Mage.Sets/src/mage/cards/s/SilentChantZubera.java
@@ -5,7 +5,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.GainLifeEffect;
@@ -29,7 +29,7 @@ public final class SilentChantZubera extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(2);
- Ability ability = new DiesTriggeredAbility(new GainLifeEffect(new SilentChantZuberaDynamicValue()));
+ Ability ability = new DiesSourceTriggeredAbility(new GainLifeEffect(new SilentChantZuberaDynamicValue()));
this.addAbility(ability, new ZuberasDiedWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/s/SilkenfistFighter.java b/Mage.Sets/src/mage/cards/s/SilkenfistFighter.java
index 4d8c1d64cb0..bd7c4a52273 100644
--- a/Mage.Sets/src/mage/cards/s/SilkenfistFighter.java
+++ b/Mage.Sets/src/mage/cards/s/SilkenfistFighter.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.UntapSourceEffect;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class SilkenfistFighter extends CardImpl {
// Whenever Silkenfist Fighter becomes blocked, untap it.
Effect effect = new UntapSourceEffect();
effect.setText("untap it");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public SilkenfistFighter(final SilkenfistFighter card) {
diff --git a/Mage.Sets/src/mage/cards/s/SilkenfistOrder.java b/Mage.Sets/src/mage/cards/s/SilkenfistOrder.java
index 1d6b9ff506d..5f76079d5f8 100644
--- a/Mage.Sets/src/mage/cards/s/SilkenfistOrder.java
+++ b/Mage.Sets/src/mage/cards/s/SilkenfistOrder.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.UntapSourceEffect;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class SilkenfistOrder extends CardImpl {
// Whenever Silkenfist Order becomes blocked, untap it.
Effect effect = new UntapSourceEffect();
effect.setText("untap it");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public SilkenfistOrder(final SilkenfistOrder card) {
diff --git a/Mage.Sets/src/mage/cards/s/SilverbackShaman.java b/Mage.Sets/src/mage/cards/s/SilverbackShaman.java
index d33b3e2867e..794d0a67e70 100644
--- a/Mage.Sets/src/mage/cards/s/SilverbackShaman.java
+++ b/Mage.Sets/src/mage/cards/s/SilverbackShaman.java
@@ -1,7 +1,7 @@
package mage.cards.s;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class SilverbackShaman extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// When Silverback Shaman dies, draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1)));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)));
}
private SilverbackShaman(final SilverbackShaman card) {
diff --git a/Mage.Sets/src/mage/cards/s/SilversmoteGhoul.java b/Mage.Sets/src/mage/cards/s/SilversmoteGhoul.java
new file mode 100644
index 00000000000..85d5dd02880
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SilversmoteGhoul.java
@@ -0,0 +1,64 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.YouGainedLifeCondition;
+import mage.abilities.costs.common.SacrificeSourceCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
+import mage.abilities.hint.ConditionHint;
+import mage.abilities.hint.Hint;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.watchers.common.PlayerGainedLifeWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SilversmoteGhoul extends CardImpl {
+
+ private static final Condition condition = new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2);
+ private static final Hint hint = new ConditionHint(condition, "You gained 3 or more life this turn");
+
+ public SilversmoteGhoul(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
+
+ this.subtype.add(SubType.ZOMBIE);
+ this.subtype.add(SubType.VAMPIRE);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(1);
+
+ // At the beginning of your end step, if you gained 3 or more life this turn, return Silversmote Ghoul from your graveyard to the battlefield tapped.
+ this.addAbility(new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfEndStepTriggeredAbility(
+ Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(true),
+ TargetController.YOU, null, false
+ ), condition, "At the beginning of your end step, " +
+ "if you gained 3 or more life this turn, return {this} from your graveyard to the battlefield tapped."
+ ).addHint(hint), new PlayerGainedLifeWatcher());
+
+ // {1}{B}, Sacrifice Silversmote Ghoul: Draw a card.
+ Ability ability = new SimpleActivatedAbility(
+ new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{1}{B}")
+ );
+ ability.addCost(new SacrificeSourceCost());
+ this.addAbility(ability);
+ }
+
+ private SilversmoteGhoul(final SilversmoteGhoul card) {
+ super(card);
+ }
+
+ @Override
+ public SilversmoteGhoul copy() {
+ return new SilversmoteGhoul(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SinsOfThePast.java b/Mage.Sets/src/mage/cards/s/SinsOfThePast.java
index 21aa8edb355..35177017ea8 100644
--- a/Mage.Sets/src/mage/cards/s/SinsOfThePast.java
+++ b/Mage.Sets/src/mage/cards/s/SinsOfThePast.java
@@ -20,6 +20,7 @@ import mage.target.common.TargetCardInYourGraveyard;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
/**
* @author emerald000
@@ -65,8 +66,8 @@ class SinsOfThePastEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Card card = game.getCard(this.getTargetPointer().getFirst(game, source));
if (card != null) {
- ContinuousEffect effect = new SinsOfThePastCastFromGraveyardEffect();
- effect.setTargetPointer(new FixedTarget(card.getId()));
+ ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.GRAVEYARD, TargetController.YOU, Duration.EndOfTurn, true);;
+ effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source);
effect = new SinsOfThePastReplacementEffect(card.getId());
game.addEffect(effect, source);
@@ -76,39 +77,6 @@ class SinsOfThePastEffect extends OneShotEffect {
}
}
-class SinsOfThePastCastFromGraveyardEffect extends AsThoughEffectImpl {
-
- SinsOfThePastCastFromGraveyardEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.PlayForFree);
- }
-
- SinsOfThePastCastFromGraveyardEffect(final SinsOfThePastCastFromGraveyardEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public SinsOfThePastCastFromGraveyardEffect copy() {
- return new SinsOfThePastCastFromGraveyardEffect(this);
- }
-
- @Override
- public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
- if (sourceId.equals(this.getTargetPointer().getFirst(game, source)) && affectedControllerId.equals(source.getControllerId())) {
- Player player = game.getPlayer(affectedControllerId);
- if(player != null) {
- player.setCastSourceIdWithAlternateMana(sourceId, null, null);
- return true;
- }
- }
- return false;
- }
-}
-
class SinsOfThePastReplacementEffect extends ReplacementEffectImpl {
private final UUID cardId;
diff --git a/Mage.Sets/src/mage/cards/s/SireOfInsanity.java b/Mage.Sets/src/mage/cards/s/SireOfInsanity.java
index 7a9f1af074e..90ece9fc954 100644
--- a/Mage.Sets/src/mage/cards/s/SireOfInsanity.java
+++ b/Mage.Sets/src/mage/cards/s/SireOfInsanity.java
@@ -1,43 +1,39 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.OnEventTriggeredAbility;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
+import mage.constants.TargetController;
import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
-
-
public final class SireOfInsanity extends CardImpl {
- public SireOfInsanity (UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{R}");
+ public SireOfInsanity(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{R}");
this.subtype.add(SubType.DEMON);
-
this.power = new MageInt(6);
this.toughness = new MageInt(4);
// At the beginning of each end step, each player discards their hand.
- this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each end step", true, new SireOfInsanityEffect()));
-
+ this.addAbility(new BeginningOfEndStepTriggeredAbility(
+ new SireOfInsanityEffect(), TargetController.ANY, false
+ ));
}
- public SireOfInsanity (final SireOfInsanity card) {
+ private SireOfInsanity(final SireOfInsanity card) {
super(card);
}
@@ -54,7 +50,7 @@ class SireOfInsanityEffect extends OneShotEffect {
staticText = "each player discards their hand";
}
- SireOfInsanityEffect(final SireOfInsanityEffect effect) {
+ private SireOfInsanityEffect(final SireOfInsanityEffect effect) {
super(effect);
}
@@ -67,9 +63,7 @@ class SireOfInsanityEffect extends OneShotEffect {
for (UUID playerId : game.getState().getPlayersInRange(sourcePlayer.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
- for (Card c : player.getHand().getCards(game)) {
- player.discard(c, source, game);
- }
+ player.discard(player.getHand(), source, game);
}
}
return true;
diff --git a/Mage.Sets/src/mage/cards/s/SirenOfTheSilentSong.java b/Mage.Sets/src/mage/cards/s/SirenOfTheSilentSong.java
index 9bb077784a8..9bde3310b1e 100644
--- a/Mage.Sets/src/mage/cards/s/SirenOfTheSilentSong.java
+++ b/Mage.Sets/src/mage/cards/s/SirenOfTheSilentSong.java
@@ -34,7 +34,7 @@ public final class SirenOfTheSilentSong extends CardImpl {
// Inspired — Whenever Siren of the Silent Song becomes untapped, each opponent discards a card, then puts the top card of their library into their graveyard.
Ability ability = new InspiredAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT));
Effect effect = new PutTopCardOfLibraryIntoGraveEachPlayerEffect(1, TargetController.OPPONENT);
- effect.setText(", then puts the top card of their library into their graveyard");
+ effect.setText(", then mills a card");
ability.addEffect(effect);
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/SirenReaver.java b/Mage.Sets/src/mage/cards/s/SirenReaver.java
index a9c1fea7ba2..edce1c538f8 100644
--- a/Mage.Sets/src/mage/cards/s/SirenReaver.java
+++ b/Mage.Sets/src/mage/cards/s/SirenReaver.java
@@ -1,4 +1,3 @@
-
package mage.cards.s;
import java.util.UUID;
@@ -31,7 +30,7 @@ public final class SirenReaver extends CardImpl {
this.toughness = new MageInt(2);
// Raid — Siren Reaver costs {1} less to cast if you attacked this turn.
- Ability ability = new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(1, RaidCondition.instance));
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(1, RaidCondition.instance));
ability.setAbilityWord(AbilityWord.RAID);
ability.setRuleAtTheTop(true);
this.addAbility(ability, new PlayerAttackedWatcher());
diff --git a/Mage.Sets/src/mage/cards/s/SithMindseer.java b/Mage.Sets/src/mage/cards/s/SithMindseer.java
index 74a76a635f2..07fe6121a42 100644
--- a/Mage.Sets/src/mage/cards/s/SithMindseer.java
+++ b/Mage.Sets/src/mage/cards/s/SithMindseer.java
@@ -6,6 +6,8 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.HateCondition;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
+import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
@@ -13,6 +15,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
+import mage.constants.Zone;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.LifeLossOtherFromCombatWatcher;
@@ -29,11 +32,16 @@ public final class SithMindseer extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(3);
- // Hate — When Sith Mindseer enters the battlefield, if an opponent loses life from a source other than combat damage, gain control of target creature for as long as Sith Mindseer remains on the battlefield.
+ // Hate — When Sith Mindseer enters the battlefield, if an opponent loses life from a source other than combat damage,
+ // gain control of target creature for as long as Sith Mindseer remains on the battlefield.
Ability ability = new ConditionalInterveningIfTriggeredAbility(
- new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.WhileOnBattlefield)),
+ new EntersBattlefieldTriggeredAbility(new ConditionalContinuousEffect(
+ new GainControlTargetEffect(Duration.Custom, true),
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD),
+ "gain control of target creature for as long as {this} remains on the battlefield")),
HateCondition.instance,
- "Hate — When Sith Mindseer enters the battlefield, if an opponent loses life from a source other than combat damage, gain control of target creature for as long as Sith Mindseer remains on the battlefield.");
+ "Hate — When {this} enters the battlefield, if an opponent loses life from a source other than combat damage,"
+ + " gain control of target creature for as long as {this} remains on the battlefield.");
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability, new LifeLossOtherFromCombatWatcher());
}
diff --git a/Mage.Sets/src/mage/cards/s/SkillBorrower.java b/Mage.Sets/src/mage/cards/s/SkillBorrower.java
index 60f9d873634..0fefe34ec97 100644
--- a/Mage.Sets/src/mage/cards/s/SkillBorrower.java
+++ b/Mage.Sets/src/mage/cards/s/SkillBorrower.java
@@ -1,26 +1,19 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.ActivatedAbility;
import mage.abilities.StaticAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.ContinuousEffectImpl;
+import mage.abilities.effects.common.GainActivatedAbilitiesOfTopCardEffect;
import mage.abilities.effects.common.continuous.PlayWithTheTopCardRevealedEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Layer;
-import mage.constants.Outcome;
-import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.Zone;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
+import mage.filter.FilterCard;
+import mage.filter.predicate.Predicates;
+
+import java.util.UUID;
/**
*
@@ -54,8 +47,14 @@ public final class SkillBorrower extends CardImpl {
class SkillBorrowerAbility extends StaticAbility {
+ private static final FilterCard filter = new FilterCard("an artifact or creature card");
+
+ static {
+ filter.add(Predicates.or(CardType.CREATURE.getPredicate(), CardType.ARTIFACT.getPredicate()));
+ }
+
public SkillBorrowerAbility() {
- super(Zone.BATTLEFIELD, new SkillBorrowerEffect());
+ super(Zone.BATTLEFIELD, new GainActivatedAbilitiesOfTopCardEffect(filter));
}
public SkillBorrowerAbility(SkillBorrowerAbility ability) {
@@ -66,47 +65,5 @@ class SkillBorrowerAbility extends StaticAbility {
public SkillBorrowerAbility copy() {
return new SkillBorrowerAbility(this);
}
-
- @Override
- public String getRule() {
- return "As long as the top card of your library is an artifact or creature card, {this} has all activated abilities of that card";
- }
}
-class SkillBorrowerEffect extends ContinuousEffectImpl {
-
- public SkillBorrowerEffect() {
- super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
- staticText = "As long as the top card of your library is an artifact or creature card, {this} has all activated abilities of that card";
- }
-
- public SkillBorrowerEffect(final SkillBorrowerEffect effect) {
- super(effect);
- }
-
- @Override
- public SkillBorrowerEffect copy() {
- return new SkillBorrowerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
- Card card = player.getLibrary().getFromTop(game);
- if (card != null && (card.isCreature() || card.isArtifact())) {
- Permanent permanent = game.getPermanent(source.getSourceId());
- if (permanent != null) {
- for (Ability ability : card.getAbilities(game)) {
- if (ability instanceof ActivatedAbility) {
- permanent.addAbility(ability, source.getSourceId(), game);
- }
- }
- return true;
- }
- }
- }
- return false;
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/s/SkullRend.java b/Mage.Sets/src/mage/cards/s/SkullRend.java
index 9b521c87947..e2a3f3ec399 100644
--- a/Mage.Sets/src/mage/cards/s/SkullRend.java
+++ b/Mage.Sets/src/mage/cards/s/SkullRend.java
@@ -2,7 +2,6 @@ package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@@ -10,24 +9,24 @@ import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
+import java.util.List;
import java.util.Objects;
import java.util.UUID;
+import java.util.stream.Collectors;
/**
- * @author LevelX2
+ * @author TheElk801
*/
public final class SkullRend extends CardImpl {
public SkullRend(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{R}");
-
// Skull Rend deals 2 damage to each opponent. Those players each discard two cards at random.
this.getSpellAbility().addEffect(new SkullRendEffect());
-
}
- public SkullRend(final SkullRend card) {
+ private SkullRend(final SkullRend card) {
super(card);
}
@@ -38,39 +37,29 @@ public final class SkullRend extends CardImpl {
private static class SkullRendEffect extends OneShotEffect {
- public SkullRendEffect() {
+ private SkullRendEffect() {
super(Outcome.Damage);
staticText = "{this} deals 2 damage to each opponent. Those players each discard two cards at random";
}
- public SkullRendEffect(final SkullRendEffect effect) {
+ private SkullRendEffect(final SkullRendEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
- if (!Objects.equals(playerId, source.getControllerId())) {
- Player opponent = game.getPlayer(playerId);
- if (opponent != null) {
- // damage
- opponent.damage(2, source.getSourceId(), game);
- // discard 2 cards at random
- int amount = Math.min(2, opponent.getHand().size());
- for (int i = 0; i < amount; i++) {
- Card card = opponent.getHand().getRandom(game);
- if (card != null) {
- opponent.discard(card, source, game);
- }
- }
- }
- }
- }
- return true;
+ List opponents = game
+ .getOpponents(source.getControllerId())
+ .stream().map(game::getPlayer)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ for (Player opponent : opponents) {
+ opponent.damage(2, source.getSourceId(), game);
}
- return false;
+ for (Player opponent : opponents) {
+ opponent.discard(2, true, source, game);
+ }
+ return true;
}
@Override
@@ -78,4 +67,4 @@ public final class SkullRend extends CardImpl {
return new SkullRendEffect(this);
}
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/s/Skylasher.java b/Mage.Sets/src/mage/cards/s/Skylasher.java
index af737ceda6d..0d0f8c8df88 100644
--- a/Mage.Sets/src/mage/cards/s/Skylasher.java
+++ b/Mage.Sets/src/mage/cards/s/Skylasher.java
@@ -5,7 +5,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.ProtectionAbility;
import mage.abilities.keyword.ReachAbility;
@@ -30,7 +30,7 @@ public final class Skylasher extends CardImpl {
// Flash
this.addAbility(FlashAbility.getInstance());
// Skylasher can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Reach, protection from blue
this.addAbility(ReachAbility.getInstance());
this.addAbility(ProtectionAbility.from(ObjectColor.BLUE));
diff --git a/Mage.Sets/src/mage/cards/s/SkymarchBloodletter.java b/Mage.Sets/src/mage/cards/s/SkymarchBloodletter.java
index e7207e3f96f..904f841ac98 100644
--- a/Mage.Sets/src/mage/cards/s/SkymarchBloodletter.java
+++ b/Mage.Sets/src/mage/cards/s/SkymarchBloodletter.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -15,8 +13,9 @@ import mage.constants.SubType;
import mage.target.Target;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class SkymarchBloodletter extends CardImpl {
@@ -34,7 +33,7 @@ public final class SkymarchBloodletter extends CardImpl {
// When Skymarch Bloodletters enters the battlefield, target opponent loses 1 life and you gain 1 life.
Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeTargetEffect(1), false);
- ability.addEffect(new GainLifeEffect(1).setText("and you gain 1 life"));
+ ability.addEffect(new GainLifeEffect(1).concatBy("and"));
Target target = new TargetOpponent();
ability.addTarget(target);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java b/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java
index c7119a81835..1ab4b0e8392 100644
--- a/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java
+++ b/Mage.Sets/src/mage/cards/s/SkyriderPatrol.java
@@ -1,37 +1,38 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.DoIfCostPaid;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
+import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
-import mage.constants.SubType;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
-import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
-import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.target.TargetPermanent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class SkyriderPatrol extends CardImpl {
+ private static final FilterControlledCreaturePermanent filter
+ = new FilterControlledCreaturePermanent("another creature you control");
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ }
+
public SkyriderPatrol(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}");
@@ -44,20 +45,19 @@ public final class SkyriderPatrol extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// At the beginning of combat on your turn, you may pay {G}{U}. When you do, put a +1/+1 counter on another target creature you control, and that creature gains flying until end of turn.
- this.addAbility(new BeginningOfCombatTriggeredAbility(
- new DoIfCostPaid(
- new SkyriderPatrolCreateReflexiveTriggerEffect(),
- new ManaCostsImpl("{G}{U}"),
- "Pay {G}{U} to put a +1/+1 counter on another"
- + " creature you control and give it flying?"
- ).setText("you may pay {G}{U}. When you do, "
- + "put a +1/+1 counter on another target creature you control, "
- + "and that creature gains flying until end of turn."),
- TargetController.YOU, false
- ));
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false,
+ "put a +1/+1 counter on another target creature you control, " +
+ "and that creature gains flying until end of turn"
+ );
+ ability.addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn));
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(new BeginningOfCombatTriggeredAbility(new DoWhenCostPaid(
+ ability, new ManaCostsImpl("{G}{U}"), "Pay {G}{U}?"
+ ), TargetController.YOU, false));
}
- public SkyriderPatrol(final SkyriderPatrol card) {
+ private SkyriderPatrol(final SkyriderPatrol card) {
super(card);
}
@@ -66,71 +66,3 @@ public final class SkyriderPatrol extends CardImpl {
return new SkyriderPatrol(this);
}
}
-
-class SkyriderPatrolCreateReflexiveTriggerEffect extends OneShotEffect {
-
- public SkyriderPatrolCreateReflexiveTriggerEffect() {
- super(Outcome.Benefit);
- }
-
- public SkyriderPatrolCreateReflexiveTriggerEffect(final SkyriderPatrolCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public SkyriderPatrolCreateReflexiveTriggerEffect copy() {
- return new SkyriderPatrolCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new SkyriderPatrolReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class SkyriderPatrolReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- private static final FilterControlledCreaturePermanent filter
- = new FilterControlledCreaturePermanent("another creature you control");
-
- static {
- filter.add(AnotherPredicate.instance);
- }
-
- public SkyriderPatrolReflexiveTriggeredAbility() {
- super(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), Duration.OneUse, true);
- this.addEffect(new GainAbilityTargetEffect(
- FlyingAbility.getInstance(),
- Duration.EndOfTurn
- ));
- this.addTarget(new TargetPermanent(filter));
- }
-
- public SkyriderPatrolReflexiveTriggeredAbility(final SkyriderPatrolReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public SkyriderPatrolReflexiveTriggeredAbility copy() {
- return new SkyriderPatrolReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When you pay {G}{U}, put a +1/+1 counter "
- + "on another target creature you control, "
- + "and that creature gains flying until end of turn.";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/s/SkywaySniper.java b/Mage.Sets/src/mage/cards/s/SkywaySniper.java
new file mode 100644
index 00000000000..362fae650ae
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SkywaySniper.java
@@ -0,0 +1,57 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.abilities.keyword.ReachAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SkywaySniper extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterCreaturePermanent("creature with flying");
+
+ static {
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ }
+
+ public SkywaySniper(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}");
+
+ this.subtype.add(SubType.ELF);
+ this.subtype.add(SubType.ARCHER);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(2);
+
+ // Reach
+ this.addAbility(ReachAbility.getInstance());
+
+ // {2}{G}: Skyway Sniper deals 1 damage to target creature with flying.
+ Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl("{2}{G}"));
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(ability);
+ }
+
+ private SkywaySniper(final SkywaySniper card) {
+ super(card);
+ }
+
+ @Override
+ public SkywaySniper copy() {
+ return new SkywaySniper(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SlashingTiger.java b/Mage.Sets/src/mage/cards/s/SlashingTiger.java
index 6f40799b4ba..a0a963a28d7 100644
--- a/Mage.Sets/src/mage/cards/s/SlashingTiger.java
+++ b/Mage.Sets/src/mage/cards/s/SlashingTiger.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class SlashingTiger extends CardImpl {
this.toughness = new MageInt(3);
// Whenever Slashing Tiger becomes blocked, it gets +2/+2 until end of turn.
- this.addAbility(new BecomesBlockedTriggeredAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn), false));
}
public SlashingTiger(final SlashingTiger card) {
diff --git a/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java b/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java
index b68d8d3a68e..5a687fed346 100644
--- a/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java
+++ b/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.condition.common.HellbentCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
@@ -32,7 +32,7 @@ public final class SlaughterhouseBouncer extends CardImpl {
// Hellbent - When Slaughterhouse Bouncer dies, if you have no cards in hand, target creature gets -3/-3 until end of turn.
Ability ability = new ConditionalInterveningIfTriggeredAbility(
- new DiesTriggeredAbility(new BoostTargetEffect(-3, -3, Duration.EndOfTurn)),
+ new DiesSourceTriggeredAbility(new BoostTargetEffect(-3, -3, Duration.EndOfTurn)),
HellbentCondition.instance,
"When {this} dies, if you have no cards in hand, target creature gets -3/-3 until end of turn."
);
diff --git a/Mage.Sets/src/mage/cards/s/SlingbowTrap.java b/Mage.Sets/src/mage/cards/s/SlingbowTrap.java
index 87f3856419e..8fcc5cd8a91 100644
--- a/Mage.Sets/src/mage/cards/s/SlingbowTrap.java
+++ b/Mage.Sets/src/mage/cards/s/SlingbowTrap.java
@@ -61,7 +61,7 @@ enum SlingbowTrapCondition implements Condition {
for (UUID attackingCreatureId : game.getCombat().getAttackers()) {
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
if (attackingCreature != null) {
- if (attackingCreature.getColor(game).isBlack() && attackingCreature.hasAbility(FlyingAbility.getInstance().getId(), game)) {
+ if (attackingCreature.getColor(game).isBlack() && attackingCreature.hasAbility(FlyingAbility.getInstance(), game)) {
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/s/SlinkingGiant.java b/Mage.Sets/src/mage/cards/s/SlinkingGiant.java
index 3d83f4a134c..07a3d03ff2d 100644
--- a/Mage.Sets/src/mage/cards/s/SlinkingGiant.java
+++ b/Mage.Sets/src/mage/cards/s/SlinkingGiant.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.keyword.WitherAbility;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class SlinkingGiant extends CardImpl {
this.addAbility(WitherAbility.getInstance());
// Whenever Slinking Giant blocks or becomes blocked, it gets -3/-0 until end of turn.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new BoostSourceEffect(-3, 0, Duration.EndOfTurn), false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(new BoostSourceEffect(-3, 0, Duration.EndOfTurn), false));
}
public SlinkingGiant(final SlinkingGiant card) {
diff --git a/Mage.Sets/src/mage/cards/s/SlithStrider.java b/Mage.Sets/src/mage/cards/s/SlithStrider.java
index b1b9474e73a..73845b1475e 100644
--- a/Mage.Sets/src/mage/cards/s/SlithStrider.java
+++ b/Mage.Sets/src/mage/cards/s/SlithStrider.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@@ -25,7 +25,7 @@ public final class SlithStrider extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
- this.addAbility(new BecomesBlockedTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), false));
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), false));
}
diff --git a/Mage.Sets/src/mage/cards/s/SmolderingEfreet.java b/Mage.Sets/src/mage/cards/s/SmolderingEfreet.java
index 56fed80827b..642e6020317 100644
--- a/Mage.Sets/src/mage/cards/s/SmolderingEfreet.java
+++ b/Mage.Sets/src/mage/cards/s/SmolderingEfreet.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DamageControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class SmolderingEfreet extends CardImpl {
this.toughness = new MageInt(2);
// When Smoldering Efreet dies, it deals 2 damage to you.
- this.addAbility(new DiesTriggeredAbility(new DamageControllerEffect(2, "it"), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new DamageControllerEffect(2, "it"), false));
}
public SmolderingEfreet(final SmolderingEfreet card) {
diff --git a/Mage.Sets/src/mage/cards/s/SnickeringSquirrel.java b/Mage.Sets/src/mage/cards/s/SnickeringSquirrel.java
index bc72bae2dd4..8cce1e89f7d 100644
--- a/Mage.Sets/src/mage/cards/s/SnickeringSquirrel.java
+++ b/Mage.Sets/src/mage/cards/s/SnickeringSquirrel.java
@@ -1,4 +1,3 @@
-
package mage.cards.s;
import java.util.UUID;
@@ -55,11 +54,13 @@ class SnickeringSquirrelEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
-
- if (controller != null) {
+ Player dieRoller = game.getPlayer(event.getPlayerId());
+ if (controller != null && dieRoller != null) {
Permanent permanent = game.getPermanent(source.getSourceId());
- if (permanent != null && permanent.canTap() && !permanent.isTapped()) {
- if (controller.chooseUse(Outcome.AIDontUseIt, "Do you want to tap this to increase the result of a die any player rolled by 1?", null, "Yes", "No", source, game)) {
+ if (permanent != null && !permanent.isTapped()) {
+ if (controller.chooseUse(Outcome.AIDontUseIt, "Do you want to tap this to increase the result of a die ("
+ + event.getAmount() + ") "
+ + dieRoller.getName() + " rolled by 1?", null, "Yes", "No", source, game)) {
permanent.tap(game);
// ignore planar dies (dice roll amount of planar dies is equal to 0)
if (event.getAmount() > 0) {
diff --git a/Mage.Sets/src/mage/cards/s/SnortingGahr.java b/Mage.Sets/src/mage/cards/s/SnortingGahr.java
index 6a972e4a19e..d830c18f838 100644
--- a/Mage.Sets/src/mage/cards/s/SnortingGahr.java
+++ b/Mage.Sets/src/mage/cards/s/SnortingGahr.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.CardImpl;
@@ -28,7 +28,7 @@ public final class SnortingGahr extends CardImpl {
// Whenever Snorting Gahr becomes blocked, it gets +2/+2 until end of turn.
Effect effect = new BoostSourceEffect(2, 2, Duration.EndOfTurn);
effect.setText("it gets +2/+2 until end of turn");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public SnortingGahr(final SnortingGahr card) {
diff --git a/Mage.Sets/src/mage/cards/s/SnowHound.java b/Mage.Sets/src/mage/cards/s/SnowHound.java
index e671b458028..1b9e1212b58 100644
--- a/Mage.Sets/src/mage/cards/s/SnowHound.java
+++ b/Mage.Sets/src/mage/cards/s/SnowHound.java
@@ -35,7 +35,7 @@ public final class SnowHound extends CardImpl {
public SnowHound(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(1);
this.toughness = new MageInt(1);
diff --git a/Mage.Sets/src/mage/cards/s/SolRing.java b/Mage.Sets/src/mage/cards/s/SolRing.java
index 9b836f10fa9..55431f5ba13 100644
--- a/Mage.Sets/src/mage/cards/s/SolRing.java
+++ b/Mage.Sets/src/mage/cards/s/SolRing.java
@@ -18,6 +18,8 @@ public final class SolRing extends CardImpl {
public SolRing(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}");
+
+ // Tap: Add {C}{C}
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.ColorlessMana(2), new TapSourceCost()));
}
diff --git a/Mage.Sets/src/mage/cards/s/SolemnSimulacrum.java b/Mage.Sets/src/mage/cards/s/SolemnSimulacrum.java
index e80c292346b..2783e4d2e37 100644
--- a/Mage.Sets/src/mage/cards/s/SolemnSimulacrum.java
+++ b/Mage.Sets/src/mage/cards/s/SolemnSimulacrum.java
@@ -2,7 +2,7 @@
package mage.cards.s;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
@@ -26,7 +26,7 @@ public final class SolemnSimulacrum extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true), true));
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
}
public SolemnSimulacrum(final SolemnSimulacrum card) {
diff --git a/Mage.Sets/src/mage/cards/s/Somnophore.java b/Mage.Sets/src/mage/cards/s/Somnophore.java
index 33a3b13a178..208db0abfbd 100644
--- a/Mage.Sets/src/mage/cards/s/Somnophore.java
+++ b/Mage.Sets/src/mage/cards/s/Somnophore.java
@@ -6,6 +6,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.condition.common.SourceOnBattlefieldCondition;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
import mage.abilities.effects.ContinuousRuleModifyingEffect;
import mage.abilities.effects.Effect;
@@ -44,7 +45,7 @@ public final class Somnophore extends CardImpl {
// Whenever Somnophore deals damage to a player, tap target creature that player controls. That creature doesn't untap during its controller's untap step for as long as Somnophore remains on the battlefield.
ContinuousRuleModifyingEffect skipUntapEffect = new DontUntapInControllersUntapStepTargetEffect(Duration.WhileOnBattlefield);
skipUntapEffect.setText("That creature doesn't untap during its controller's untap step for as long as {this} remains on the battlefield");
- ConditionalContinuousRuleModifyingEffect effect = new ConditionalContinuousRuleModifyingEffect(skipUntapEffect, SourceOnBattlefieldCondition.instance);
+ ConditionalContinuousRuleModifyingEffect effect = new ConditionalContinuousRuleModifyingEffect(skipUntapEffect, new SourceRemainsInZoneCondition(Zone.BATTLEFIELD));
Ability ability = new SomnophoreTriggeredAbility(new TapTargetEffect());
ability.addTarget(new TargetCreaturePermanent());
ability.addEffect(effect);
diff --git a/Mage.Sets/src/mage/cards/s/SongOfBlood.java b/Mage.Sets/src/mage/cards/s/SongOfBlood.java
index d786f476dda..9838614994a 100644
--- a/Mage.Sets/src/mage/cards/s/SongOfBlood.java
+++ b/Mage.Sets/src/mage/cards/s/SongOfBlood.java
@@ -1,22 +1,17 @@
package mage.cards.s;
-import java.util.Set;
-import java.util.UUID;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
-import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
@@ -24,8 +19,10 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
+import java.util.Objects;
+import java.util.UUID;
+
/**
- *
* @author spjspj
*/
public final class SongOfBlood extends CardImpl {
@@ -38,7 +35,7 @@ public final class SongOfBlood extends CardImpl {
this.getSpellAbility().addEffect(new SongOfBloodEffect());
}
- public SongOfBlood(final SongOfBlood card) {
+ private SongOfBlood(final SongOfBlood card) {
super(card);
}
@@ -50,13 +47,14 @@ public final class SongOfBlood extends CardImpl {
class SongOfBloodEffect extends OneShotEffect {
- public SongOfBloodEffect() {
+ SongOfBloodEffect() {
super(Outcome.LoseLife);
- this.staticText = "Put the top four cards of your library into your graveyard.";
+ this.staticText = "Mill four cards. Whenever a creature attacks this turn, " +
+ "it gets +1/+0 until end of turn for each creature card put into your graveyard this way.";
}
- public SongOfBloodEffect(final SongOfBloodEffect effect) {
+ private SongOfBloodEffect(final SongOfBloodEffect effect) {
super(effect);
}
@@ -68,36 +66,35 @@ class SongOfBloodEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Cards cardsToGraveyard = new CardsImpl();
- cardsToGraveyard.addAll(controller.getLibrary().getTopCards(game, 4));
- if (!cardsToGraveyard.isEmpty()) {
- Set movedCards = controller.moveCardsToGraveyardWithInfo(cardsToGraveyard.getCards(game), source, game, Zone.LIBRARY);
- Cards cardsMoved = new CardsImpl();
- cardsMoved.addAll(movedCards);
- int creatures = cardsMoved.count(StaticFilters.FILTER_CARD_CREATURE, game);
- if (creatures > 0) {
- // Setup a delayed trigger to give +X/+0 to any creature attacking this turn..
- DelayedTriggeredAbility delayedAbility = new SongOfBloodTriggeredAbility(creatures);
- game.addDelayedTriggeredAbility(delayedAbility, source);
- }
- }
- return true;
+ if (controller == null) {
+ return false;
}
- return false;
+ int creatures = controller
+ .millCards(4, source, game)
+ .getCards(game)
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(card -> game.getState().getZone(card.getId()) == Zone.GRAVEYARD)
+ .filter(MageObject::isCreature)
+ .mapToInt(x -> 1)
+ .sum();
+ // Setup a delayed trigger to give +X/+0 to any creature attacking this turn..
+ DelayedTriggeredAbility delayedAbility = new SongOfBloodTriggeredAbility(creatures);
+ game.addDelayedTriggeredAbility(delayedAbility, source);
+ return true;
}
}
class SongOfBloodTriggeredAbility extends DelayedTriggeredAbility {
- int booster;
+ private final int booster;
- public SongOfBloodTriggeredAbility(int booster) {
+ SongOfBloodTriggeredAbility(int booster) {
super(new BoostTargetEffect(booster, 0, Duration.EndOfTurn), Duration.EndOfTurn, false);
this.booster = booster;
}
- public SongOfBloodTriggeredAbility(SongOfBloodTriggeredAbility ability) {
+ private SongOfBloodTriggeredAbility(SongOfBloodTriggeredAbility ability) {
super(ability);
this.booster = ability.booster;
}
@@ -126,6 +123,6 @@ class SongOfBloodTriggeredAbility extends DelayedTriggeredAbility {
@Override
public String getRule() {
- return "Whenever a creature attacks this turn, it gets +1/+0 (+" + booster + "/0) until end of turn for each creature card put into your graveyard this way.";
+ return "Whenever a creature attacks this turn, it gets +" + booster + "/0 until end of turn.";
}
}
diff --git a/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java b/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java
index ce6b7187a35..14e5f342f88 100644
--- a/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java
+++ b/Mage.Sets/src/mage/cards/s/SongOfTheDryads.java
@@ -1,4 +1,3 @@
-
package mage.cards.s;
import java.util.UUID;
@@ -11,11 +10,12 @@ import mage.abilities.mana.GreenManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
+import mage.constants.DependencyType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
@@ -28,7 +28,7 @@ import mage.target.TargetPermanent;
public final class SongOfTheDryads extends CardImpl {
public SongOfTheDryads(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}");
this.subtype.add(SubType.AURA);
// Enchant permanent
@@ -58,6 +58,7 @@ class BecomesColorlessForestLandEffect extends ContinuousEffectImpl {
public BecomesColorlessForestLandEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
this.staticText = "Enchanted permanent is a colorless Forest land";
+ dependencyTypes.add(DependencyType.BecomeForest);
}
public BecomesColorlessForestLandEffect(final BecomesColorlessForestLandEffect effect) {
@@ -89,10 +90,10 @@ class BecomesColorlessForestLandEffect extends ContinuousEffectImpl {
permanent.getColor(game).setRed(false);
break;
case AbilityAddingRemovingEffects_6:
- permanent.removeAllAbilities(source.getSourceId(), game);
permanent.addAbility(new GreenManaAbility(), source.getSourceId(), game);
break;
case TypeChangingEffects_4:
+ permanent.removeAllAbilities(source.getSourceId(), game);
permanent.getCardType().clear();
permanent.addCardType(CardType.LAND);
permanent.getSubtype(game).clear();
diff --git a/Mage.Sets/src/mage/cards/s/SorcerousSpyglass.java b/Mage.Sets/src/mage/cards/s/SorcerousSpyglass.java
index 1e1735f9a22..6db68ce6e59 100644
--- a/Mage.Sets/src/mage/cards/s/SorcerousSpyglass.java
+++ b/Mage.Sets/src/mage/cards/s/SorcerousSpyglass.java
@@ -1,8 +1,5 @@
-
package mage.cards.s;
-import java.util.Optional;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
@@ -11,18 +8,17 @@ import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.AbilityType;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import mage.util.CardUtil;
+
+import java.util.Optional;
+import java.util.UUID;
/**
- *
* @author TheElk801
*/
public final class SorcerousSpyglass extends CardImpl {
@@ -110,13 +106,12 @@ class SorcerousSpyglassActivationEffect extends ContinuousRuleModifyingEffectImp
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
MageObject object = game.getObject(event.getSourceId());
+ String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
Optional ability = game.getAbility(event.getTargetId(), event.getSourceId());
if (ability.isPresent() && object != null) {
- if (game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId()) // controller in range
+ return game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId()) // controller in range
&& ability.get().getAbilityType() != AbilityType.MANA
- && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) {
- return true;
- }
+ && CardUtil.haveSameNames(object, cardName, game);
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/s/SorinImperiousBloodlord.java b/Mage.Sets/src/mage/cards/s/SorinImperiousBloodlord.java
index 038ddf9ead3..8c720fcb43f 100644
--- a/Mage.Sets/src/mage/cards/s/SorinImperiousBloodlord.java
+++ b/Mage.Sets/src/mage/cards/s/SorinImperiousBloodlord.java
@@ -1,12 +1,15 @@
package mage.cards.s;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.*;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.DoWhenCostPaid;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.LifelinkAbility;
@@ -21,7 +24,6 @@ import mage.filter.FilterCard;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetControlledCreaturePermanent;
@@ -58,11 +60,16 @@ public final class SorinImperiousBloodlord extends CardImpl {
this.addAbility(ability);
// +1: You may sacrifice a Vampire. When you do, Sorin, Imperious Bloodlord deals 3 damage to any target and you gain 3 life.
- this.addAbility(new LoyaltyAbility(new DoIfCostPaid(
- new SorinImperiousBloodlordCreateReflexiveTriggerEffect(),
- new SacrificeTargetCost(new TargetControlledPermanent(filter))
- ).setText("You may sacrifice a Vampire. " +
- "When you do, {this} deals 3 damage to any target and you gain 3 life."
+ ReflexiveTriggeredAbility triggeredAbility = new ReflexiveTriggeredAbility(
+ new DamageTargetEffect(3), false,
+ "{this} deals 3 damage to any target and you gain 3 life"
+ );
+ triggeredAbility.addEffect(new GainLifeEffect(3));
+ triggeredAbility.addTarget(new TargetAnyTarget());
+ this.addAbility(new LoyaltyAbility(new DoWhenCostPaid(
+ triggeredAbility,
+ new SacrificeTargetCost(new TargetControlledPermanent(filter)),
+ "Sacrifice a Vampire?"
), 1));
// −3: You may put a Vampire creature card from your hand onto the battlefield.
@@ -110,58 +117,3 @@ class SorinImperiousBloodlordEffect extends OneShotEffect {
return true;
}
}
-
-class SorinImperiousBloodlordCreateReflexiveTriggerEffect extends OneShotEffect {
-
- SorinImperiousBloodlordCreateReflexiveTriggerEffect() {
- super(Benefit);
- }
-
- private SorinImperiousBloodlordCreateReflexiveTriggerEffect(final SorinImperiousBloodlordCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public SorinImperiousBloodlordCreateReflexiveTriggerEffect copy() {
- return new SorinImperiousBloodlordCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new SorinImperiousBloodlordReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class SorinImperiousBloodlordReflexiveTriggeredAbility extends DelayedTriggeredAbility {
- SorinImperiousBloodlordReflexiveTriggeredAbility() {
- super(new DamageTargetEffect(3), Duration.OneUse, true);
- this.addEffect(new GainLifeEffect(3));
- this.addTarget(new TargetAnyTarget());
- }
-
- private SorinImperiousBloodlordReflexiveTriggeredAbility(final SorinImperiousBloodlordReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public SorinImperiousBloodlordReflexiveTriggeredAbility copy() {
- return new SorinImperiousBloodlordReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "{this} deals 3 damage to any target and you gain 3 life";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/s/SorinLordOfInnistrad.java b/Mage.Sets/src/mage/cards/s/SorinLordOfInnistrad.java
index 7a89e3f455b..d65929f660e 100644
--- a/Mage.Sets/src/mage/cards/s/SorinLordOfInnistrad.java
+++ b/Mage.Sets/src/mage/cards/s/SorinLordOfInnistrad.java
@@ -101,7 +101,7 @@ class SorinLordOfInnistradEffect extends OneShotEffect {
}
}
}
- game.applyEffects();
+ game.getState().processAction(game);
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
return controller.moveCards(toBattlefield, Zone.BATTLEFIELD, source, game);
diff --git a/Mage.Sets/src/mage/cards/s/SoulOfRavnica.java b/Mage.Sets/src/mage/cards/s/SoulOfRavnica.java
index 070cac316f3..e0ae6486e05 100644
--- a/Mage.Sets/src/mage/cards/s/SoulOfRavnica.java
+++ b/Mage.Sets/src/mage/cards/s/SoulOfRavnica.java
@@ -2,25 +2,18 @@
package mage.cards.s;
import mage.MageInt;
-import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.ExileSourceFromGraveCost;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DrawCardForEachColorAmongControlledPermanentsEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
-import mage.constants.Outcome;
import mage.constants.Zone;
-import mage.game.Game;
-import mage.game.permanent.Permanent;
-import mage.players.Player;
-import java.util.HashSet;
-import java.util.Set;
import java.util.UUID;
/**
@@ -38,11 +31,12 @@ public final class SoulOfRavnica extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
+
// {5}{U}{U}: Draw a card for each color among permanents you control.
- this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new SoulOfRavnicaEffect(), new ManaCostsImpl("{5}{U}{U}")));
+ this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardForEachColorAmongControlledPermanentsEffect(), new ManaCostsImpl("{5}{U}{U}")));
// {5}{U}{U}, Exile Soul of Ravnica from your graveyard: Draw a card for each color among permanents you control.
- Ability ability = new SimpleActivatedAbility(Zone.GRAVEYARD, new SoulOfRavnicaEffect(), new ManaCostsImpl("{5}{U}{U}"));
+ Ability ability = new SimpleActivatedAbility(Zone.GRAVEYARD, new DrawCardForEachColorAmongControlledPermanentsEffect(), new ManaCostsImpl("{5}{U}{U}"));
ability.addCost(new ExileSourceFromGraveCost());
this.addAbility(ability);
}
@@ -57,47 +51,3 @@ public final class SoulOfRavnica extends CardImpl {
}
}
-class SoulOfRavnicaEffect extends OneShotEffect {
-
- public SoulOfRavnicaEffect() {
- super(Outcome.DrawCard);
- this.staticText = "Draw a card for each color among permanents you control";
- }
-
- public SoulOfRavnicaEffect(final SoulOfRavnicaEffect effect) {
- super(effect);
- }
-
- @Override
- public SoulOfRavnicaEffect copy() {
- return new SoulOfRavnicaEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller != null) {
- Set colors = new HashSet<>();
- for (Permanent permanent : game.getBattlefield().getAllActivePermanents(controller.getId())) {
- if (permanent.getColor(game).isBlack()) {
- colors.add(ObjectColor.BLACK);
- }
- if (permanent.getColor(game).isBlue()) {
- colors.add(ObjectColor.BLUE);
- }
- if (permanent.getColor(game).isRed()) {
- colors.add(ObjectColor.RED);
- }
- if (permanent.getColor(game).isGreen()) {
- colors.add(ObjectColor.GREEN);
- }
- if (permanent.getColor(game).isWhite()) {
- colors.add(ObjectColor.WHITE);
- }
- }
- controller.drawCards(colors.size(), source.getSourceId(), game);
- return true;
- }
- return false;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/s/SoulSear.java b/Mage.Sets/src/mage/cards/s/SoulSear.java
new file mode 100644
index 00000000000..af843a50005
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SoulSear.java
@@ -0,0 +1,38 @@
+package mage.cards.s;
+
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect;
+import mage.abilities.keyword.IndestructibleAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.target.common.TargetCreatureOrPlaneswalker;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SoulSear extends CardImpl {
+
+ public SoulSear(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
+
+ // Soul Sear deals 5 damage to target creature or planeswalker. That permanent loses indestructible until end of turn.
+ this.getSpellAbility().addEffect(new DamageTargetEffect(5));
+ this.getSpellAbility().addEffect(new LoseAbilityTargetEffect(
+ IndestructibleAbility.getInstance(), Duration.EndOfTurn
+ ).setText("That permanent loses indestructible until end of turn"));
+ this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker());
+ }
+
+ private SoulSear(final SoulSear card) {
+ super(card);
+ }
+
+ @Override
+ public SoulSear copy() {
+ return new SoulSear(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SoulbrightFlamekin.java b/Mage.Sets/src/mage/cards/s/SoulbrightFlamekin.java
index c4fa17cb3af..95f3198e030 100644
--- a/Mage.Sets/src/mage/cards/s/SoulbrightFlamekin.java
+++ b/Mage.Sets/src/mage/cards/s/SoulbrightFlamekin.java
@@ -6,7 +6,9 @@ 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.IfAbilityHasResolvedXTimesEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
+import mage.abilities.hint.common.AbilityResolutionCountHint;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -37,8 +39,9 @@ public final class SoulbrightFlamekin extends CardImpl {
Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(
TrampleAbility.getInstance(), Duration.EndOfTurn
), new ManaCostsImpl("{2}"));
- ability.addEffect(new SoulbrightFlamekinEffect());
+ ability.addEffect(new IfAbilityHasResolvedXTimesEffect(Outcome.PutManaInPool, 3, new SoulbrightFlamekinEffect()));
ability.addTarget(new TargetCreaturePermanent());
+ ability.addHint(AbilityResolutionCountHint.instance);
this.addAbility(ability, new AbilityResolvedWatcher());
}
@@ -56,8 +59,7 @@ class SoulbrightFlamekinEffect extends OneShotEffect {
SoulbrightFlamekinEffect() {
super(Outcome.Damage);
- this.staticText = "If this is the third time this ability has resolved this turn, " +
- "you may add {R}{R}{R}{R}{R}{R}{R}{R}";
+ this.staticText = "you may add {R}{R}{R}{R}{R}{R}{R}{R}";
}
private SoulbrightFlamekinEffect(final SoulbrightFlamekinEffect effect) {
@@ -72,14 +74,10 @@ class SoulbrightFlamekinEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
- AbilityResolvedWatcher watcher = game.getState().getWatcher(AbilityResolvedWatcher.class);
- if (controller == null
- || watcher == null
- || !watcher.checkActivations(source, game)
- || !controller.chooseUse(Outcome.PutManaInPool, "Add {R}{R}{R}{R}{R}{R}{R}{R}}?", source, game)) {
- return false;
+ if (controller != null && controller.chooseUse(Outcome.PutManaInPool, "Add {R}{R}{R}{R}{R}{R}{R}{R}?", source, game)) {
+ controller.getManaPool().addMana(Mana.RedMana(8), game, source);
+ return true;
}
- controller.getManaPool().addMana(Mana.RedMana(8), game, source);
- return true;
+ return false;
}
}
diff --git a/Mage.Sets/src/mage/cards/s/SoulcageFiend.java b/Mage.Sets/src/mage/cards/s/SoulcageFiend.java
index 669c4cacf30..71c179f86d9 100644
--- a/Mage.Sets/src/mage/cards/s/SoulcageFiend.java
+++ b/Mage.Sets/src/mage/cards/s/SoulcageFiend.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.LoseLifeAllPlayersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -23,7 +23,7 @@ public final class SoulcageFiend extends CardImpl {
this.toughness = new MageInt(2);
// When Soulcage Fiend dies, each player loses 3 life.
- this.addAbility(new DiesTriggeredAbility(new LoseLifeAllPlayersEffect(3)));
+ this.addAbility(new DiesSourceTriggeredAbility(new LoseLifeAllPlayersEffect(3)));
}
public SoulcageFiend(final SoulcageFiend card) {
diff --git a/Mage.Sets/src/mage/cards/s/Soulstinger.java b/Mage.Sets/src/mage/cards/s/Soulstinger.java
index 955da0d7cdf..56204981e3a 100644
--- a/Mage.Sets/src/mage/cards/s/Soulstinger.java
+++ b/Mage.Sets/src/mage/cards/s/Soulstinger.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
@@ -43,7 +43,7 @@ public final class Soulstinger extends CardImpl {
new CountersSourceCount(CounterType.M1M1),
Outcome.Detriment);
effect.setText("you may put a -1/-1 counter on target creature for each -1/-1 counter on {this}");
- ability = new DiesTriggeredAbility(effect, true);
+ ability = new DiesSourceTriggeredAbility(effect, true);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/SowerOfTemptation.java b/Mage.Sets/src/mage/cards/s/SowerOfTemptation.java
index 3607841e7bf..9800a91148c 100644
--- a/Mage.Sets/src/mage/cards/s/SowerOfTemptation.java
+++ b/Mage.Sets/src/mage/cards/s/SowerOfTemptation.java
@@ -6,6 +6,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.SourceOnBattlefieldCondition;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
@@ -16,6 +17,7 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.Zone;
import mage.game.Game;
import mage.target.common.TargetCreaturePermanent;
@@ -78,7 +80,7 @@ class SowerOfTemptationGainControlEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(
new GainControlTargetEffect(Duration.Custom),
- SourceOnBattlefieldCondition.instance,
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD),
"gain control of target creature for as long as {this} remains on the battlefield");
game.addEffect(effect, source);
return false;
diff --git a/Mage.Sets/src/mage/cards/s/SparkhunterMasticore.java b/Mage.Sets/src/mage/cards/s/SparkhunterMasticore.java
new file mode 100644
index 00000000000..46afd30c0ef
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SparkhunterMasticore.java
@@ -0,0 +1,65 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.DiscardCardCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.IndestructibleAbility;
+import mage.abilities.keyword.ProtectionAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.filter.FilterObject;
+import mage.target.common.TargetPlaneswalkerPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SparkhunterMasticore extends CardImpl {
+
+ private static final FilterObject filter = new FilterObject("planeswalkers");
+
+ static {
+ filter.add(CardType.PLANESWALKER.getPredicate());
+ }
+
+ public SparkhunterMasticore(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
+
+ this.subtype.add(SubType.MASTICORE);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(4);
+
+ // As an additional cost to cast this spell, discard a card.
+ this.getSpellAbility().addCost(new DiscardCardCost());
+
+ // Protection from planeswalkers
+ this.addAbility(new ProtectionAbility(filter));
+
+ // {1}: Sparkhunter Masticore deals 1 damage to target planeswalker.
+ Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new GenericManaCost(1));
+ ability.addTarget(new TargetPlaneswalkerPermanent());
+ this.addAbility(ability);
+
+ // {3}: Sparkhunter Masticore gains indestructible until end of turn.
+ this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect(
+ IndestructibleAbility.getInstance(), Duration.EndOfTurn
+ ), new GenericManaCost(3)));
+ }
+
+ private SparkhunterMasticore(final SparkhunterMasticore card) {
+ super(card);
+ }
+
+ @Override
+ public SparkhunterMasticore copy() {
+ return new SparkhunterMasticore(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SparktongueDragon.java b/Mage.Sets/src/mage/cards/s/SparktongueDragon.java
index ae8dae4410c..5396b970d15 100644
--- a/Mage.Sets/src/mage/cards/s/SparktongueDragon.java
+++ b/Mage.Sets/src/mage/cards/s/SparktongueDragon.java
@@ -1,28 +1,21 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
-import mage.abilities.effects.common.DoIfCostPaid;
-import mage.abilities.effects.common.SendOptionUsedEventEffect;
-import mage.constants.SubType;
+import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.game.Game;
-import mage.game.events.GameEvent;
+import mage.constants.SubType;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class SparktongueDragon extends CardImpl {
@@ -38,16 +31,18 @@ public final class SparktongueDragon extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Sparktongue Dragon enters the battlefield, you may pay {2}{R}. When you do, it deals 3 damage to any target.
- this.addAbility(new EntersBattlefieldTriggeredAbility(
- new DoIfCostPaid(
- new SparktongueDragonCreateReflexiveTriggerEffect(),
- new ManaCostsImpl("{2}{R}"),
- "Pay {2}{R} to deal 3 damage?"
- ).setText("you may pay {2}{R}. When you do, it deals 3 damage to any target")
- ));
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new DamageTargetEffect(3), false,
+ "it deals 3 damage to any target"
+ );
+ ability.addTarget(new TargetAnyTarget());
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new DoWhenCostPaid(
+ ability, new ManaCostsImpl("{2}{R}"),
+ "Pay {2}{R} to deal 3 damage?"
+ )));
}
- public SparktongueDragon(final SparktongueDragon card) {
+ private SparktongueDragon(final SparktongueDragon card) {
super(card);
}
@@ -56,59 +51,3 @@ public final class SparktongueDragon extends CardImpl {
return new SparktongueDragon(this);
}
}
-
-class SparktongueDragonCreateReflexiveTriggerEffect extends OneShotEffect {
-
- public SparktongueDragonCreateReflexiveTriggerEffect() {
- super(Outcome.Benefit);
- this.staticText = "When you do, it deals 3 damage to any target";
- }
-
- public SparktongueDragonCreateReflexiveTriggerEffect(final SparktongueDragonCreateReflexiveTriggerEffect effect) {
- super(effect);
- }
-
- @Override
- public SparktongueDragonCreateReflexiveTriggerEffect copy() {
- return new SparktongueDragonCreateReflexiveTriggerEffect(this);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- game.addDelayedTriggeredAbility(new SparktongueDragonReflexiveTriggeredAbility(), source);
- return new SendOptionUsedEventEffect().apply(game, source);
- }
-}
-
-class SparktongueDragonReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- public SparktongueDragonReflexiveTriggeredAbility() {
- super(new DamageTargetEffect(3), Duration.OneUse, true);
- this.addTarget(new TargetAnyTarget());
- }
-
- public SparktongueDragonReflexiveTriggeredAbility(final SparktongueDragonReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public SparktongueDragonReflexiveTriggeredAbility copy() {
- return new SparktongueDragonReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When you pay {2}{R}, {this} deals 3 damage to any target";
- }
-}
diff --git a/Mage.Sets/src/mage/cards/s/SparringConstruct.java b/Mage.Sets/src/mage/cards/s/SparringConstruct.java
index fd9626d107e..18022974cd0 100644
--- a/Mage.Sets/src/mage/cards/s/SparringConstruct.java
+++ b/Mage.Sets/src/mage/cards/s/SparringConstruct.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class SparringConstruct extends CardImpl {
this.toughness = new MageInt(1);
// When Sparring Construct dies, put a +1/+1 counter on target creature you control.
- Ability ability = new DiesTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false);
+ Ability ability = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false);
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/SparringGolem.java b/Mage.Sets/src/mage/cards/s/SparringGolem.java
index 8bf7eb23cb0..191eb036734 100644
--- a/Mage.Sets/src/mage/cards/s/SparringGolem.java
+++ b/Mage.Sets/src/mage/cards/s/SparringGolem.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.BlockedCreatureCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
@@ -29,7 +29,7 @@ public final class SparringGolem extends CardImpl {
BlockedCreatureCount value = new BlockedCreatureCount();
Effect effect = new BoostSourceEffect(value, value, Duration.EndOfTurn, true);
effect.setText("it gets +1/+1 until end of turn for each creature blocking it");
- this.addAbility(new BecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BecomesBlockedSourceTriggeredAbility(effect, false));
}
public SparringGolem(final SparringGolem card) {
diff --git a/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java b/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java
new file mode 100644
index 00000000000..b269c73a90e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java
@@ -0,0 +1,79 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.MainPhaseStackEmptyCondition;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.decorator.ConditionalActivatedAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.abilities.keyword.VigilanceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.permanent.token.AngelToken;
+import mage.players.Player;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SpeakerOfTheHeavens extends CardImpl {
+
+ public SpeakerOfTheHeavens(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ // Vigilance
+ this.addAbility(VigilanceAbility.getInstance());
+
+ // Lifelink
+ this.addAbility(LifelinkAbility.getInstance());
+
+ // {T}: Create a 4/4 white Angel creature token with flying. Activate this ability only if you have at least 7 more life than your starting life total and only any time you could cast a sorcery.
+ this.addAbility(new ConditionalActivatedAbility(
+ Zone.BATTLEFIELD, new CreateTokenEffect(new AngelToken()),
+ new TapSourceCost(), SpeakerOfTheHeavensCondition.instance
+ ));
+ }
+
+ private SpeakerOfTheHeavens(final SpeakerOfTheHeavens card) {
+ super(card);
+ }
+
+ @Override
+ public SpeakerOfTheHeavens copy() {
+ return new SpeakerOfTheHeavens(this);
+ }
+}
+
+enum SpeakerOfTheHeavensCondition implements Condition {
+ instance;
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ if (!MainPhaseStackEmptyCondition.instance.apply(game, source)
+ || !game.isActivePlayer(source.getControllerId())) {
+ return false;
+ }
+ Player player = game.getPlayer(source.getControllerId());
+ if (player == null || player.getLife() < game.getLife() + 7) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "if you have at least 7 more life than your starting life total and only any time you could cast a sorcery";
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/s/SpectralReserves.java b/Mage.Sets/src/mage/cards/s/SpectralReserves.java
index feb8019187a..22caf3fa9c8 100644
--- a/Mage.Sets/src/mage/cards/s/SpectralReserves.java
+++ b/Mage.Sets/src/mage/cards/s/SpectralReserves.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.GainLifeEffect;
@@ -10,17 +8,18 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.game.permanent.token.SpiritWhiteToken;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class SpectralReserves extends CardImpl {
public SpectralReserves(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}");
// Create two 1/1 white Spirit creature tokens with flying. You gain 2 life.
- Effect effect = new CreateTokenEffect(new SpiritWhiteToken("EMN"), 2);
+ Effect effect = new CreateTokenEffect(new SpiritWhiteToken(), 2);
effect.setText("Create two 1/1 white Spirit creature tokens with flying");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(new GainLifeEffect(2));
diff --git a/Mage.Sets/src/mage/cards/s/Spelljack.java b/Mage.Sets/src/mage/cards/s/Spelljack.java
index f966eb20915..7ea471aee72 100644
--- a/Mage.Sets/src/mage/cards/s/Spelljack.java
+++ b/Mage.Sets/src/mage/cards/s/Spelljack.java
@@ -6,6 +6,7 @@ import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -13,6 +14,7 @@ import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.constants.ZoneDetail;
import mage.game.Game;
@@ -71,7 +73,7 @@ class SpelljackEffect extends OneShotEffect {
if (stackObject != null && game.getStack().counter(targetId, source.getSourceId(), game, Zone.EXILED, false, ZoneDetail.NONE)) {
Card card = ((Spell) stackObject).getCard();
if (card != null) {
- ContinuousEffect effect = new SpelljackCastFromExileEffect();
+ ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, TargetController.YOU, Duration.Custom, true);
effect.setTargetPointer(new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId())));
game.addEffect(effect, source);
}
@@ -81,50 +83,3 @@ class SpelljackEffect extends OneShotEffect {
return false;
}
}
-
-class SpelljackCastFromExileEffect extends AsThoughEffectImpl {
-
- SpelljackCastFromExileEffect() {
- super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
- staticText = "You may cast that card without paying its mana cost as long as it remains exiled";
- }
-
- SpelljackCastFromExileEffect(final SpelljackCastFromExileEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source) {
- return true;
- }
-
- @Override
- public SpelljackCastFromExileEffect copy() {
- return new SpelljackCastFromExileEffect(this);
- }
-
- @Override
- public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
- if (affectedControllerId.equals(source.getControllerId())) {
- if (getTargetPointer().getFirst(game, source) == null) {
- this.discard();
- return false;
- }
- if (sourceId.equals(getTargetPointer().getFirst(game, source))) {
- Card card = game.getCard(sourceId);
- if (card != null) {
- if (game.getState().getZone(sourceId) == Zone.EXILED) {
- Player player = game.getPlayer(affectedControllerId);
- if(player != null) {
- player.setCastSourceIdWithAlternateMana(sourceId, null, null);
- }
- return true;
- } else {
- this.discard();
- }
- }
- }
- }
- return false;
- }
-}
diff --git a/Mage.Sets/src/mage/cards/s/SpellweaverHelix.java b/Mage.Sets/src/mage/cards/s/SpellweaverHelix.java
index 25c5b0f25f3..5eeed09130b 100644
--- a/Mage.Sets/src/mage/cards/s/SpellweaverHelix.java
+++ b/Mage.Sets/src/mage/cards/s/SpellweaverHelix.java
@@ -1,6 +1,5 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
@@ -23,13 +22,14 @@ import mage.target.common.TargetCardInASingleGraveyard;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class SpellweaverHelix extends CardImpl {
- private static final FilterCard filter = new FilterCard("sorcery cards from a single graveyard");
+ private static final FilterCard filter = new FilterCard("sorcery cards");
static {
filter.add(CardType.SORCERY.getPredicate());
diff --git a/Mage.Sets/src/mage/cards/s/SpellweaverVolute.java b/Mage.Sets/src/mage/cards/s/SpellweaverVolute.java
index 971f423f3cf..7f6b4fd2d0a 100644
--- a/Mage.Sets/src/mage/cards/s/SpellweaverVolute.java
+++ b/Mage.Sets/src/mage/cards/s/SpellweaverVolute.java
@@ -90,7 +90,7 @@ class SpellweaverVoluteEffect extends OneShotEffect {
&& controller.chooseUse(Outcome.Copy, "Create a copy of " + enchantedCard.getName() + '?', source, game)) {
Card copiedCard = game.copyCard(enchantedCard, source, source.getControllerId());
if (copiedCard != null) {
- ownerEnchanted.getGraveyard().add(copiedCard);
+ controller.getGraveyard().add(copiedCard);
game.getState().setZone(copiedCard.getId(), Zone.GRAVEYARD);
if (controller.chooseUse(Outcome.PlayForFree, "Cast the copied card without paying mana cost?", source, game)) {
if (copiedCard.getSpellAbility() != null) {
diff --git a/Mage.Sets/src/mage/cards/s/SpellwildOuphe.java b/Mage.Sets/src/mage/cards/s/SpellwildOuphe.java
index ac7dbe287ca..047ca525799 100644
--- a/Mage.Sets/src/mage/cards/s/SpellwildOuphe.java
+++ b/Mage.Sets/src/mage/cards/s/SpellwildOuphe.java
@@ -1,22 +1,19 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.target.Target;
-import mage.util.CardUtil;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+
+import java.util.UUID;
/**
- *
* @author LevelX2 & L_J
*/
public final class SpellwildOuphe extends CardImpl {
@@ -27,8 +24,10 @@ public final class SpellwildOuphe extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(3);
- // Spells that target Elderwood Scion cost {2} less to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellwildOupheCostReductionEffect()));
+ // Spells that target Spellwild Ouphe cost {2} less to cast.
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(-2, new FilterCard("Spells"), TargetController.ANY))
+ );
}
public SpellwildOuphe(final SpellwildOuphe card) {
@@ -39,48 +38,4 @@ public final class SpellwildOuphe extends CardImpl {
public SpellwildOuphe copy() {
return new SpellwildOuphe(this);
}
-}
-
-class SpellwildOupheCostReductionEffect extends CostModificationEffectImpl {
-
- private static final String effectText = "Spells that target {this} cost {2} less to cast";
-
- SpellwildOupheCostReductionEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = effectText;
- }
-
- SpellwildOupheCostReductionEffect(SpellwildOupheCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, 2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
- Mode mode = abilityToModify.getModes().get(modeId);
- for (Target target : mode.getTargets()) {
- for (UUID targetUUID : target.getTargets()) {
- if (targetUUID.equals(source.getSourceId())) {
- return true;
- }
- }
- }
- }
- }
- return false;
- }
-
- @Override
- public SpellwildOupheCostReductionEffect copy() {
- return new SpellwildOupheCostReductionEffect(this);
- }
-
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/s/SphereOfResistance.java b/Mage.Sets/src/mage/cards/s/SphereOfResistance.java
index 0e5c8303fe6..c1326f4da88 100644
--- a/Mage.Sets/src/mage/cards/s/SphereOfResistance.java
+++ b/Mage.Sets/src/mage/cards/s/SphereOfResistance.java
@@ -1,25 +1,28 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.TargetController;
import mage.constants.Zone;
+import mage.filter.FilterCard;
+
+import java.util.UUID;
/**
- *
* @author Plopman
*/
public final class SphereOfResistance extends CardImpl {
public SphereOfResistance(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// Spells cost {1} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasementAllEffect(1)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostIncreasingAllEffect(1, new FilterCard("Spells"), TargetController.ANY))
+ );
}
public SphereOfResistance(final SphereOfResistance card) {
diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java b/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java
index 690a8c7f3b9..102695ce817 100644
--- a/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java
+++ b/Mage.Sets/src/mage/cards/s/SphinxOfNewPrahv.java
@@ -1,20 +1,17 @@
package mage.cards.s;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
-import mage.game.Game;
-import mage.players.Player;
-import mage.target.Target;
-import mage.util.CardUtil;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
import java.util.UUID;
@@ -37,7 +34,9 @@ public final class SphinxOfNewPrahv extends CardImpl {
this.addAbility(VigilanceAbility.getInstance());
// Spells your opponents cast that target Sphinx of New Prahv cost {2} more to cast.
- this.addAbility(new SimpleStaticAbility(new SphinxOfNewPrahvCostIncreaseEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(2, new FilterCard("Spells"), TargetController.OPPONENT))
+ );
}
private SphinxOfNewPrahv(final SphinxOfNewPrahv card) {
@@ -49,49 +48,3 @@ public final class SphinxOfNewPrahv extends CardImpl {
return new SphinxOfNewPrahv(this);
}
}
-
-class SphinxOfNewPrahvCostIncreaseEffect extends CostModificationEffectImpl {
-
- SphinxOfNewPrahvCostIncreaseEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Spells your opponents cast that target {this} cost {2} more to cast";
- }
-
- private SphinxOfNewPrahvCostIncreaseEffect(SphinxOfNewPrahvCostIncreaseEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- Player controller = game.getPlayer(source.getControllerId());
- if (controller == null
- || !(abilityToModify instanceof SpellAbility)
- || !controller.hasOpponent(abilityToModify.getControllerId(), game)) {
- return false;
- }
- for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
- Mode mode = abilityToModify.getModes().get(modeId);
- for (Target target : mode.getTargets()) {
- for (UUID targetUUID : target.getTargets()) {
- if (targetUUID.equals(source.getSourceId())) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- @Override
- public SphinxOfNewPrahvCostIncreaseEffect copy() {
- return new SphinxOfNewPrahvCostIncreaseEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java b/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java
index 038b3928859..678629eaeed 100644
--- a/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java
+++ b/Mage.Sets/src/mage/cards/s/SphinxOfTheFinalWord.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.CantBeCounteredControlledEffect;
import mage.abilities.keyword.FlyingAbility;
@@ -37,7 +37,7 @@ public final class SphinxOfTheFinalWord extends CardImpl {
this.toughness = new MageInt(5);
// Sphinx of the Final Word can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Flying
this.addAbility(FlyingAbility.getInstance());
diff --git a/Mage.Sets/src/mage/cards/s/SphinxsTutelage.java b/Mage.Sets/src/mage/cards/s/SphinxsTutelage.java
index 1b5868ca4e0..372f47facf9 100644
--- a/Mage.Sets/src/mage/cards/s/SphinxsTutelage.java
+++ b/Mage.Sets/src/mage/cards/s/SphinxsTutelage.java
@@ -1,7 +1,7 @@
package mage.cards.s;
-import java.util.UUID;
+import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.DrawCardControllerTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@@ -11,8 +11,6 @@ import mage.abilities.effects.common.DrawDiscardControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.cards.Cards;
-import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@@ -20,8 +18,11 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
/**
- *
* @author LevelX2
*/
public final class SphinxsTutelage extends CardImpl {
@@ -52,7 +53,7 @@ class SphinxsTutelageEffect extends OneShotEffect {
public SphinxsTutelageEffect() {
super(Outcome.Benefit);
- this.staticText = "target opponent puts the top two cards of their library into their graveyard. If they're both nonland cards that share a color, repeat this process";
+ this.staticText = "target opponent mills two cards. If two nonland cards that share a color were milled this way, repeat this process.";
}
public SphinxsTutelageEffect(final SphinxsTutelageEffect effect) {
@@ -67,10 +68,11 @@ class SphinxsTutelageEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source));
- boolean colorShared;
+
if (targetPlayer != null) {
int possibleIterations = targetPlayer.getLibrary().size() / 2;
int iteration = 0;
+ boolean colorShared;
do {
iteration++;
if (iteration > possibleIterations + 20) {
@@ -82,20 +84,35 @@ class SphinxsTutelageEffect extends OneShotEffect {
return true;
}
colorShared = false;
- Cards cards = new CardsImpl(targetPlayer.getLibrary().getTopCards(game, 2));
- Card card1 = null;
- for (Card card : cards.getCards(game)) {
- if (card.isLand()) {
+ List cards = targetPlayer
+ .millCards(2, source, game)
+ .getCards(game)
+ .stream()
+ .filter(card -> !card.isLand())
+ .collect(Collectors.toList());
+ if (cards.size() < 2) {
+ break;
+ }
+ for (int i = 0; i < cards.size(); i++) {
+ if (colorShared) {
break;
}
- if (card1 == null) {
- card1 = card;
- } else {
- colorShared = card1.getColor(game).shares(card.getColor(game));
+ ObjectColor color1 = cards.get(i).getColor(game);
+ if (color1.isColorless()) {
+ continue;
+ }
+ for (int j = 0; j < cards.size(); j++) {
+ if (i >= j) {
+ continue;
+ }
+ ObjectColor color2 = cards.get(j).getColor(game);
+ if (color1.shares(color2)) {
+ colorShared = true;
+ break;
+ }
}
}
- targetPlayer.moveCards(cards, Zone.GRAVEYARD, source, game);
- } while (colorShared && targetPlayer.isInGame());
+ } while (colorShared);
return true;
}
return false;
diff --git a/Mage.Sets/src/mage/cards/s/SpinalCentipede.java b/Mage.Sets/src/mage/cards/s/SpinalCentipede.java
index 9d5073b48bf..7e8c8347a93 100644
--- a/Mage.Sets/src/mage/cards/s/SpinalCentipede.java
+++ b/Mage.Sets/src/mage/cards/s/SpinalCentipede.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
@@ -26,7 +26,7 @@ public final class SpinalCentipede extends CardImpl {
this.toughness = new MageInt(2);
// When Spinal Centipede dies, put a +1/+1 counter on target creature you control.
- Ability ability = new DiesTriggeredAbility(new AddCountersTargetEffect(
+ Ability ability = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(
CounterType.P1P1.createInstance()
), false);
ability.addTarget(new TargetControlledCreaturePermanent());
diff --git a/Mage.Sets/src/mage/cards/s/SpinedMegalodon.java b/Mage.Sets/src/mage/cards/s/SpinedMegalodon.java
new file mode 100644
index 00000000000..b740d87914a
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SpinedMegalodon.java
@@ -0,0 +1,41 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.effects.keyword.ScryEffect;
+import mage.abilities.keyword.HexproofAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SpinedMegalodon extends CardImpl {
+
+ public SpinedMegalodon(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}");
+
+ this.subtype.add(SubType.SHARK);
+ this.power = new MageInt(5);
+ this.toughness = new MageInt(7);
+
+ // Hexproof
+ this.addAbility(HexproofAbility.getInstance());
+
+ // Whenever Spined Megalodon attacks, scry 1.
+ this.addAbility(new AttacksTriggeredAbility(new ScryEffect(1), false));
+ }
+
+ private SpinedMegalodon(final SpinedMegalodon card) {
+ super(card);
+ }
+
+ @Override
+ public SpinedMegalodon copy() {
+ return new SpinedMegalodon(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SpiritBonds.java b/Mage.Sets/src/mage/cards/s/SpiritBonds.java
index 2827034a87b..2bdb334f1f6 100644
--- a/Mage.Sets/src/mage/cards/s/SpiritBonds.java
+++ b/Mage.Sets/src/mage/cards/s/SpiritBonds.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@@ -25,8 +23,9 @@ import mage.game.permanent.token.SpiritWhiteToken;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetControlledPermanent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class SpiritBonds extends CardImpl {
@@ -42,16 +41,16 @@ public final class SpiritBonds extends CardImpl {
}
public SpiritBonds(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
// Whenever a nontoken creature enters the battlefield under your control, you may pay {W}. If you do, but a 1/1 white Spirit creature token with flying into play.
- this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new DoIfCostPaid(new CreateTokenEffect(new SpiritWhiteToken("M15")), new ManaCostsImpl("{W}")), filterNontoken, false));
-
+ this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new DoIfCostPaid(new CreateTokenEffect(new SpiritWhiteToken()), new ManaCostsImpl("{W}")), filterNontoken, false));
+
// {1}{W}, Sacrifice a Spirit: Target non-Spirit creature you control gains indestructible until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{1}{W}"));
- ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(1,1,filterSpirit, true)));
+ ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(1, 1, filterSpirit, true)));
ability.addTarget(new TargetControlledCreaturePermanent(filter));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/SpiritOfMalevolence.java b/Mage.Sets/src/mage/cards/s/SpiritOfMalevolence.java
new file mode 100644
index 00000000000..bd49a418710
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SpiritOfMalevolence.java
@@ -0,0 +1,41 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DiesSourceTriggeredAbility;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.effects.common.LoseLifeOpponentsEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SpiritOfMalevolence extends CardImpl {
+
+ public SpiritOfMalevolence(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
+
+ this.subtype.add(SubType.SPIRIT);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(1);
+
+ // When Spirit of Malevolence dies, each opponent loses 1 life and you gain 1 life.
+ Ability ability = new DiesSourceTriggeredAbility(new LoseLifeOpponentsEffect(1));
+ ability.addEffect(new GainLifeEffect(1).concatBy("and"));
+ this.addAbility(ability);
+ }
+
+ private SpiritOfMalevolence(final SpiritOfMalevolence card) {
+ super(card);
+ }
+
+ @Override
+ public SpiritOfMalevolence copy() {
+ return new SpiritOfMalevolence(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SpitefulPrankster.java b/Mage.Sets/src/mage/cards/s/SpitefulPrankster.java
new file mode 100644
index 00000000000..b0e11ae8e33
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SpitefulPrankster.java
@@ -0,0 +1,56 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DiesCreatureTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.common.MyTurnCondition;
+import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.hint.common.MyTurnHint;
+import mage.abilities.keyword.FirstStrikeAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.target.common.TargetPlayerOrPlaneswalker;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SpitefulPrankster extends CardImpl {
+
+ public SpitefulPrankster(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
+
+ this.subtype.add(SubType.DEVIL);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(2);
+
+ // As long as it's your turn, Spiteful Prankster has first strike.
+ this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
+ new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield),
+ MyTurnCondition.instance, "As long as it's your turn, {this} has first strike."
+ )).addHint(MyTurnHint.instance));
+
+ // Whenever another creature dies, Spiteful Prankster deals 1 damage to target player or planeswalker.
+ Ability ability = new DiesCreatureTriggeredAbility(
+ new DamageTargetEffect(1), false, true
+ );
+ ability.addTarget(new TargetPlayerOrPlaneswalker());
+ this.addAbility(ability);
+ }
+
+ private SpitefulPrankster(final SpitefulPrankster card) {
+ super(card);
+ }
+
+ @Override
+ public SpitefulPrankster copy() {
+ return new SpitefulPrankster(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SpittingSlug.java b/Mage.Sets/src/mage/cards/s/SpittingSlug.java
index 6907a53aaba..4b521896922 100644
--- a/Mage.Sets/src/mage/cards/s/SpittingSlug.java
+++ b/Mage.Sets/src/mage/cards/s/SpittingSlug.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
@@ -39,7 +39,7 @@ public final class SpittingSlug extends CardImpl {
this.toughness = new MageInt(4);
// Whenever Spitting Slug blocks or becomes blocked, you may pay {1}{G}. If you do, Spitting Slug gains first strike until end of turn. Otherwise, each creature blocking or blocked by Spitting Slug gains first strike until end of turn.
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(
new DoIfCostPaid(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn),
new SpittingSlugEffect(),
new ManaCostsImpl("{1}{G}")).setText("you may pay {1}{G}. If you do, {this} gains first strike until end of turn. Otherwise, each creature blocking or blocked by {this} gains first strike until end of turn"),
diff --git a/Mage.Sets/src/mage/cards/s/SpoilsOfTheVault.java b/Mage.Sets/src/mage/cards/s/SpoilsOfTheVault.java
index 153bc570f73..3466f128b5d 100644
--- a/Mage.Sets/src/mage/cards/s/SpoilsOfTheVault.java
+++ b/Mage.Sets/src/mage/cards/s/SpoilsOfTheVault.java
@@ -68,7 +68,7 @@ class SpoilsOfTheVaultEffect extends OneShotEffect {
for (Card card : controller.getLibrary().getCards(game)) {
if (card != null) {
cardsToReveal.add(card);
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
controller.moveCards(card, Zone.HAND, source, game);
break;
} else {
diff --git a/Mage.Sets/src/mage/cards/s/SporewebWeaver.java b/Mage.Sets/src/mage/cards/s/SporewebWeaver.java
new file mode 100644
index 00000000000..77aeed621e3
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SporewebWeaver.java
@@ -0,0 +1,50 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.DealtDamageToSourceTriggeredAbility;
+import mage.abilities.effects.common.CreateTokenEffect;
+import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.keyword.HexproofFromBlueAbility;
+import mage.abilities.keyword.ReachAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.game.permanent.token.SaprolingToken;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SporewebWeaver extends CardImpl {
+
+ public SporewebWeaver(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
+
+ this.subtype.add(SubType.SPIDER);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(4);
+
+ // Reach
+ this.addAbility(ReachAbility.getInstance());
+
+ // Hexproof from blue
+ this.addAbility(HexproofFromBlueAbility.getInstance());
+
+ // Whenever Sporeweb Weaver is dealt damage, you gain 1 life and create a 1/1 green Saproling creature token.
+ Ability ability = new DealtDamageToSourceTriggeredAbility(new GainLifeEffect(1), false);
+ ability.addEffect(new CreateTokenEffect(new SaprolingToken()).concatBy("and"));
+ this.addAbility(ability);
+ }
+
+ private SporewebWeaver(final SporewebWeaver card) {
+ super(card);
+ }
+
+ @Override
+ public SporewebWeaver copy() {
+ return new SporewebWeaver(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SproutingThrinax.java b/Mage.Sets/src/mage/cards/s/SproutingThrinax.java
index fd5fe9af5d2..a5b5f5d2314 100644
--- a/Mage.Sets/src/mage/cards/s/SproutingThrinax.java
+++ b/Mage.Sets/src/mage/cards/s/SproutingThrinax.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -28,7 +28,7 @@ public final class SproutingThrinax extends CardImpl {
this.power = new MageInt(3);
this.toughness = new MageInt(3);
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(saprolingToken, 3), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(saprolingToken, 3), false));
}
public SproutingThrinax(final SproutingThrinax card) {
diff --git a/Mage.Sets/src/mage/cards/s/Squeeze.java b/Mage.Sets/src/mage/cards/s/Squeeze.java
index 3dabaa83dcb..2605970a044 100644
--- a/Mage.Sets/src/mage/cards/s/Squeeze.java
+++ b/Mage.Sets/src/mage/cards/s/Squeeze.java
@@ -1,35 +1,34 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.Effect;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
+import java.util.UUID;
+
/**
- *
* @author fireshoes
*/
public final class Squeeze extends CardImpl {
-
+
private static final FilterCard filter = new FilterCard("Sorcery spells");
-
+
static {
filter.add(CardType.SORCERY.getPredicate());
}
public Squeeze(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}");
// Sorcery spells cost {3} more to cast.
- Effect effect = new SpellsCostIncreasementAllEffect(filter, 3);
- effect.setText("Sorcery spells cost {3} more to cast");
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostIncreasingAllEffect(3, filter, TargetController.ANY))
+ );
}
public Squeeze(final Squeeze card) {
diff --git a/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java b/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java
index 81a49dc5284..9e0df8ed14c 100644
--- a/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java
+++ b/Mage.Sets/src/mage/cards/s/StarfieldOfNyx.java
@@ -12,7 +12,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterCard;
-import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledPermanent;
import mage.filter.common.FilterEnchantmentPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.AnotherPredicate;
@@ -47,15 +47,15 @@ public final class StarfieldOfNyx extends CardImpl {
public StarfieldOfNyx(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}");
- // At the beginning of your upkeep, you may return target enchantment card
+ // At the beginning of your upkeep, you may return target enchantment card
// from your graveyard to the battlefield.
Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD,
new ReturnFromGraveyardToBattlefieldTargetEffect(), TargetController.YOU, true);
ability.addTarget(new TargetCardInGraveyard(filterGraveyardEnchantment));
this.addAbility(ability);
- // As long as you control five or more enchantments, each other non-Aura enchantment
- // you control is a creature in addition to its other types and has base power and
+ // As long as you control five or more enchantments, each other non-Aura enchantment
+ // you control is a creature in addition to its other types and has base power and
// base toughness each equal to its converted mana cost.
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(
new StarfieldOfNyxEffect(), new PermanentsOnTheBattlefieldCondition(
@@ -74,13 +74,13 @@ public final class StarfieldOfNyx extends CardImpl {
static class StarfieldOfNyxEffect extends ContinuousEffectImpl {
- private static final FilterPermanent filter
- = new FilterPermanent("Each other non-Aura enchantment you control");
- private static final FilterEnchantmentPermanent filter2
- = new FilterEnchantmentPermanent();
+ private static final FilterControlledPermanent filter
+ = new FilterControlledPermanent("Each other non-Aura enchantment you control");
static {
- filter2.add(TargetController.YOU.getControllerPredicate());
+ filter.add(CardType.ENCHANTMENT.getPredicate());
+ filter.add(Predicates.not(SubType.AURA.getPredicate()));
+ filter.add(AnotherPredicate.instance);
}
public StarfieldOfNyxEffect() {
@@ -91,8 +91,14 @@ public final class StarfieldOfNyx extends CardImpl {
this.dependendToTypes.add(DependencyType.EnchantmentAddingRemoving); // Enchanted Evening
this.dependendToTypes.add(DependencyType.AuraAddingRemoving); // Cloudform
+ this.dependendToTypes.add(DependencyType.BecomeForest); // Song of the Dryads
+ this.dependendToTypes.add(DependencyType.BecomeMountain);
+ this.dependendToTypes.add(DependencyType.BecomePlains);
+ this.dependendToTypes.add(DependencyType.BecomeSwamp);
+ this.dependendToTypes.add(DependencyType.BecomeIsland);
this.dependencyTypes.add(DependencyType.BecomeCreature); // Conspiracy
+
}
public StarfieldOfNyxEffect(final StarfieldOfNyxEffect effect) {
@@ -106,9 +112,6 @@ public final class StarfieldOfNyx extends CardImpl {
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
- filter.add(CardType.ENCHANTMENT.getPredicate());
- filter.add(Predicates.not(SubType.AURA.getPredicate()));
- filter.add(AnotherPredicate.instance);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter,
source.getControllerId(), source.getSourceId(), game)) {
switch (layer) {
diff --git a/Mage.Sets/src/mage/cards/s/StaunchShieldmate.java b/Mage.Sets/src/mage/cards/s/StaunchShieldmate.java
new file mode 100644
index 00000000000..68f108e0edd
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/StaunchShieldmate.java
@@ -0,0 +1,33 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class StaunchShieldmate extends CardImpl {
+
+ public StaunchShieldmate(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
+
+ this.subtype.add(SubType.DWARF);
+ this.subtype.add(SubType.SOLDIER);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(3);
+ }
+
+ private StaunchShieldmate(final StaunchShieldmate card) {
+ super(card);
+ }
+
+ @Override
+ public StaunchShieldmate copy() {
+ return new StaunchShieldmate(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SteadfastSentry.java b/Mage.Sets/src/mage/cards/s/SteadfastSentry.java
index e118f863b54..8d5ecc10936 100644
--- a/Mage.Sets/src/mage/cards/s/SteadfastSentry.java
+++ b/Mage.Sets/src/mage/cards/s/SteadfastSentry.java
@@ -2,7 +2,7 @@ package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
@@ -31,7 +31,7 @@ public final class SteadfastSentry extends CardImpl {
this.addAbility(VigilanceAbility.getInstance());
// When Steadfast Sentry dies, put a +1/+1 counter on target creature you control.
- Ability ability = new DiesTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
+ Ability ability = new DiesSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/s/SteelPlumeMarshal.java b/Mage.Sets/src/mage/cards/s/SteelPlumeMarshal.java
new file mode 100644
index 00000000000..0bb3a3dcc3c
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SteelPlumeMarshal.java
@@ -0,0 +1,58 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.effects.common.continuous.BoostAllEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+import mage.filter.predicate.permanent.AttackingPredicate;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SteelPlumeMarshal extends CardImpl {
+
+ private static final FilterCreaturePermanent filter
+ = new FilterCreaturePermanent("attacking creatures you control with flying");
+
+ static {
+ filter.add(AttackingPredicate.instance);
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ filter.add(TargetController.YOU.getControllerPredicate());
+ }
+
+ public SteelPlumeMarshal(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
+
+ this.subtype.add(SubType.BIRD);
+ this.subtype.add(SubType.SOLDIER);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Whenever Steel-Plume Marshal attacks, other attacking creatures you control with flying get +2/+2 until end of turn.
+ this.addAbility(new AttacksTriggeredAbility(new BoostAllEffect(
+ 2, 2, Duration.EndOfTurn, filter, true
+ ), false));
+ }
+
+ private SteelPlumeMarshal(final SteelPlumeMarshal card) {
+ super(card);
+ }
+
+ @Override
+ public SteelPlumeMarshal copy() {
+ return new SteelPlumeMarshal(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SternMentor.java b/Mage.Sets/src/mage/cards/s/SternMentor.java
index f920d8448ea..997d6be1487 100644
--- a/Mage.Sets/src/mage/cards/s/SternMentor.java
+++ b/Mage.Sets/src/mage/cards/s/SternMentor.java
@@ -22,7 +22,8 @@ import mage.target.TargetPlayer;
*/
public final class SternMentor extends CardImpl {
- private static final String ruleText = "As long as {this} is paired with another creature, each of those creatures has \"{T}: Target player puts the top two cards of their library into their graveyard.\"";
+ private static final String ruleText = "As long as {this} is paired with another creature, " +
+ "each of those creatures has \"{T}: Target player mills two cards.\"";
public SternMentor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}");
diff --git a/Mage.Sets/src/mage/cards/s/StitcherGeralf.java b/Mage.Sets/src/mage/cards/s/StitcherGeralf.java
index 9c84a668d3c..bbfc44d0d0d 100644
--- a/Mage.Sets/src/mage/cards/s/StitcherGeralf.java
+++ b/Mage.Sets/src/mage/cards/s/StitcherGeralf.java
@@ -56,7 +56,7 @@ class StitcherGeralfEffect extends OneShotEffect {
public StitcherGeralfEffect() {
super(Outcome.PutCreatureInPlay);
- this.staticText = "Each player puts the top three cards of their library into their graveyard. Exile up to two creature cards put into graveyards this way. Create an X/X blue Zombie creature token, where X is the total power of the cards exiled this way";
+ this.staticText = "Each player mills three cards. Exile up to two creature cards put into graveyards this way. Create an X/X blue Zombie creature token, where X is the total power of the cards exiled this way";
}
public StitcherGeralfEffect(final StitcherGeralfEffect effect) {
@@ -76,10 +76,10 @@ class StitcherGeralfEffect extends OneShotEffect {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId);
if (player != null) {
- cards.addAll(player.getLibrary().getTopCards(game, 3));
+ cards.addAll(player.millCards(3,source,game));
}
}
- controller.moveCards(cards, Zone.GRAVEYARD, source, game);
+ cards.removeIf(uuid -> game.getState().getZone(uuid)!=Zone.GRAVEYARD);
TargetCard target = new TargetCard(0, 2, Zone.GRAVEYARD, new FilterCreatureCard("creature cards to exile"));
controller.chooseTarget(outcome, cards, target, source, game);
int power = 0;
diff --git a/Mage.Sets/src/mage/cards/s/StoicRebuttal.java b/Mage.Sets/src/mage/cards/s/StoicRebuttal.java
index a9340141640..81352927b01 100644
--- a/Mage.Sets/src/mage/cards/s/StoicRebuttal.java
+++ b/Mage.Sets/src/mage/cards/s/StoicRebuttal.java
@@ -1,5 +1,3 @@
-
-
package mage.cards.s;
import java.util.UUID;
@@ -21,14 +19,14 @@ import mage.target.TargetSpell;
public final class StoicRebuttal extends CardImpl {
public StoicRebuttal(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{U}");
// Metalcraft — Stoic Rebuttal costs {1} less to cast if you control three or more artifacts.
- Ability ability = new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(1, MetalcraftCondition.instance));
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(1, MetalcraftCondition.instance));
ability.setRuleAtTheTop(true);
ability.setAbilityWord(AbilityWord.METALCRAFT);
this.addAbility(ability);
-
+
// Counter target spell.
this.getSpellAbility().addTarget(new TargetSpell());
this.getSpellAbility().addEffect(new CounterTargetEffect());
diff --git a/Mage.Sets/src/mage/cards/s/StokeTheFlames.java b/Mage.Sets/src/mage/cards/s/StokeTheFlames.java
index 39cd33c84c9..bffdfd33b85 100644
--- a/Mage.Sets/src/mage/cards/s/StokeTheFlames.java
+++ b/Mage.Sets/src/mage/cards/s/StokeTheFlames.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.ConvokeAbility;
import mage.cards.CardImpl;
@@ -9,19 +7,19 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.common.TargetAnyTarget;
+import java.util.UUID;
+
/**
- *
* @author Quercitron
*/
public final class StokeTheFlames extends CardImpl {
public StokeTheFlames(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}{R}");
-
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}{R}");
// Convoke
this.addAbility(new ConvokeAbility());
-
+
// Stoke the Flames deals 4 damage to any target.
this.getSpellAbility().addEffect(new DamageTargetEffect(4));
this.getSpellAbility().addTarget(new TargetAnyTarget());
diff --git a/Mage.Sets/src/mage/cards/s/StolenGoods.java b/Mage.Sets/src/mage/cards/s/StolenGoods.java
index c6588a53285..0cecd5c0876 100644
--- a/Mage.Sets/src/mage/cards/s/StolenGoods.java
+++ b/Mage.Sets/src/mage/cards/s/StolenGoods.java
@@ -1,4 +1,3 @@
-
package mage.cards.s;
import java.util.UUID;
@@ -74,7 +73,7 @@ class StolenGoodsEffect extends OneShotEffect {
if (card != null) {
ContinuousEffect effect = new StolenGoodsCastFromExileEffect();
- effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
+ effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source);
}
return true;
@@ -105,17 +104,11 @@ class StolenGoodsCastFromExileEffect extends AsThoughEffectImpl {
}
@Override
- public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
- if (sourceId != null && sourceId.equals(getTargetPointer().getFirst(game, source))
+ public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
+ if (objectId != null && objectId.equals(getTargetPointer().getFirst(game, source))
&& affectedControllerId.equals(source.getControllerId())) {
- Card card = game.getCard(sourceId);
- if (card != null && game.getState().getZone(sourceId) == Zone.EXILED) {
- Player player = game.getPlayer(affectedControllerId);
- if (player != null) {
- player.setCastSourceIdWithAlternateMana(sourceId, null, card.getSpellAbility().getCosts());
- return true;
- }
- }
+ allowCardToPlayWithoutMana(objectId, source, affectedControllerId, game);
+ return true;
}
return false;
}
diff --git a/Mage.Sets/src/mage/cards/s/StoneHavenPilgrim.java b/Mage.Sets/src/mage/cards/s/StoneHavenPilgrim.java
new file mode 100644
index 00000000000..f1f2685ffb9
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/StoneHavenPilgrim.java
@@ -0,0 +1,56 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.AttacksTriggeredAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.filter.StaticFilters;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class StoneHavenPilgrim extends CardImpl {
+
+ private static final Condition condition
+ = new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT);
+
+ public StoneHavenPilgrim(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
+
+ this.subtype.add(SubType.KOR);
+ this.subtype.add(SubType.CLERIC);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // Whenever Stone Haven Pilgrim attacks, if you control an artifact or enchantment, Stone Haven Pilgrim gets +1/+1 and gains lifelink until end of turn.
+ Ability ability = new ConditionalInterveningIfTriggeredAbility(
+ new AttacksTriggeredAbility(
+ new BoostSourceEffect(1, 1, Duration.EndOfTurn), false
+ ), condition, "Whenever {this} attacks, if you control an artifact or enchantment, " +
+ "{this} gets +1/+1 and gains lifelink until end of turn."
+ );
+ ability.addEffect(new GainAbilitySourceEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn));
+ this.addAbility(ability);
+ }
+
+ private StoneHavenPilgrim(final StoneHavenPilgrim card) {
+ super(card);
+ }
+
+ @Override
+ public StoneHavenPilgrim copy() {
+ return new StoneHavenPilgrim(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/StonebrowKrosanHero.java b/Mage.Sets/src/mage/cards/s/StonebrowKrosanHero.java
index 468f5855e0f..c5ffaa03273 100644
--- a/Mage.Sets/src/mage/cards/s/StonebrowKrosanHero.java
+++ b/Mage.Sets/src/mage/cards/s/StonebrowKrosanHero.java
@@ -1,7 +1,6 @@
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility;
import mage.abilities.effects.Effect;
@@ -10,19 +9,21 @@ import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
+import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.AbilityPredicate;
+import java.util.UUID;
+
/**
*
* @author emerald000
*/
public final class StonebrowKrosanHero extends CardImpl {
- private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control with trample");
+ private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(" creature you control with trample");
static {
filter.add(new AbilityPredicate(TrampleAbility.class));
}
diff --git a/Mage.Sets/src/mage/cards/s/StonybrookBanneret.java b/Mage.Sets/src/mage/cards/s/StonybrookBanneret.java
index 70b28e219cf..3c6a09327f5 100644
--- a/Mage.Sets/src/mage/cards/s/StonybrookBanneret.java
+++ b/Mage.Sets/src/mage/cards/s/StonybrookBanneret.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
@@ -14,8 +12,9 @@ import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class StonybrookBanneret extends CardImpl {
@@ -29,7 +28,7 @@ public final class StonybrookBanneret extends CardImpl {
}
public StonybrookBanneret(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.MERFOLK);
this.subtype.add(SubType.WIZARD);
@@ -38,6 +37,7 @@ public final class StonybrookBanneret extends CardImpl {
// Islandwalk
this.addAbility(new IslandwalkAbility());
+
// Merfolk spells and Wizard spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
}
diff --git a/Mage.Sets/src/mage/cards/s/StormCaller.java b/Mage.Sets/src/mage/cards/s/StormCaller.java
new file mode 100644
index 00000000000..0fbd4f64b15
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/StormCaller.java
@@ -0,0 +1,41 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.DamagePlayersEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class StormCaller extends CardImpl {
+
+ public StormCaller(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
+
+ this.subtype.add(SubType.OGRE);
+ this.subtype.add(SubType.SHAMAN);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(2);
+
+ // When Storm Caller enters the battlefield, it deals 2 damage to each opponent.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(
+ new DamagePlayersEffect(2, TargetController.OPPONENT, "it")
+ ));
+ }
+
+ private StormCaller(final StormCaller card) {
+ super(card);
+ }
+
+ @Override
+ public StormCaller copy() {
+ return new StormCaller(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/StormscapeFamiliar.java b/Mage.Sets/src/mage/cards/s/StormscapeFamiliar.java
index 31f5d317783..d09f512d5f4 100644
--- a/Mage.Sets/src/mage/cards/s/StormscapeFamiliar.java
+++ b/Mage.Sets/src/mage/cards/s/StormscapeFamiliar.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
@@ -16,8 +14,9 @@ import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class StormscapeFamiliar extends CardImpl {
@@ -31,7 +30,7 @@ public final class StormscapeFamiliar extends CardImpl {
}
public StormscapeFamiliar(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.BIRD);
this.power = new MageInt(1);
@@ -39,6 +38,7 @@ public final class StormscapeFamiliar extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
+
// White spells and black spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
}
diff --git a/Mage.Sets/src/mage/cards/s/StormsurgeKraken.java b/Mage.Sets/src/mage/cards/s/StormsurgeKraken.java
index f28520f1816..50b685b9350 100644
--- a/Mage.Sets/src/mage/cards/s/StormsurgeKraken.java
+++ b/Mage.Sets/src/mage/cards/s/StormsurgeKraken.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.abilityword.LieutenantAbility;
-import mage.abilities.common.BecomesBlockedTriggeredAbility;
+import mage.abilities.common.BecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
@@ -32,7 +32,7 @@ public final class StormsurgeKraken extends CardImpl {
this.addAbility(HexproofAbility.getInstance());
// Lieutenant - As long as you control your commander, Stormsurge Kraken gets +2/+2 and has "Whenever Stormsurge Kraken becomes blocked, you may draw two cards."
- ContinuousEffect effect = new GainAbilitySourceEffect(new BecomesBlockedTriggeredAbility(new DrawCardSourceControllerEffect(2), true), Duration.WhileOnBattlefield);
+ ContinuousEffect effect = new GainAbilitySourceEffect(new BecomesBlockedSourceTriggeredAbility(new DrawCardSourceControllerEffect(2), true), Duration.WhileOnBattlefield);
effect.setText("and has \"Whenever Stormsurge Kraken becomes blocked, you may draw two cards.\"");
this.addAbility(new LieutenantAbility(effect));
}
diff --git a/Mage.Sets/src/mage/cards/s/StormtideLeviathan.java b/Mage.Sets/src/mage/cards/s/StormtideLeviathan.java
index 40e76151eed..0c46713eafe 100644
--- a/Mage.Sets/src/mage/cards/s/StormtideLeviathan.java
+++ b/Mage.Sets/src/mage/cards/s/StormtideLeviathan.java
@@ -91,7 +91,7 @@ public final class StormtideLeviathan extends CardImpl {
// land abilities are intrinsic, so add them here, not in layer 6
if (!land.hasSubtype(SubType.ISLAND, game)) {
land.getSubtype(game).add(SubType.ISLAND);
- if (!land.getAbilities(game).contains(new BlueManaAbility())) {
+ if (!land.getAbilities(game).containsClass(BlueManaAbility.class)) {
land.addAbility(new BlueManaAbility(), source.getSourceId(), game);
}
}
diff --git a/Mage.Sets/src/mage/cards/s/StormwildCapridor.java b/Mage.Sets/src/mage/cards/s/StormwildCapridor.java
index de000f194d1..67d2bb9dea3 100644
--- a/Mage.Sets/src/mage/cards/s/StormwildCapridor.java
+++ b/Mage.Sets/src/mage/cards/s/StormwildCapridor.java
@@ -3,6 +3,7 @@ package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -13,9 +14,7 @@ import mage.constants.SubType;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.DamageCreatureEvent;
-import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
-import mage.game.events.PreventDamageEvent;
import mage.game.permanent.Permanent;
import java.util.UUID;
@@ -74,19 +73,14 @@ class StormwildCapridorEffect extends PreventionEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
- boolean retValue = false;
- GameEvent preventEvent = new PreventDamageEvent(source.getFirstTarget(), source.getSourceId(), source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage());
- int damage = event.getAmount();
- if (!game.replaceEvent(preventEvent)) {
- event.setAmount(0);
- game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), damage));
- retValue = true;
+ PreventionEffectData preventionEffectData = preventDamageAction(event, source, game);
+ if (preventionEffectData.getPreventedDamage() > 0) {
+ Permanent permanent = game.getPermanent(source.getSourceId());
+ if (permanent != null) {
+ permanent.addCounters(CounterType.P1P1.createInstance(preventionEffectData.getPreventedDamage()), source, game);
+ }
}
- Permanent permanent = game.getPermanent(source.getSourceId());
- if (permanent != null) {
- permanent.addCounters(CounterType.P1P1.createInstance(damage), source, game);
- }
- return retValue;
+ return preventionEffectData.isReplaced();
}
@Override
diff --git a/Mage.Sets/src/mage/cards/s/StormwingEntity.java b/Mage.Sets/src/mage/cards/s/StormwingEntity.java
new file mode 100644
index 00000000000..45e90a6e147
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/StormwingEntity.java
@@ -0,0 +1,108 @@
+package mage.cards.s;
+
+import java.util.HashSet;
+import java.util.Set;
+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.Condition;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.effects.keyword.ScryEffect;
+import mage.abilities.hint.ConditionHint;
+import mage.abilities.keyword.FlyingAbility;
+import mage.abilities.keyword.ProwessAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.constants.WatcherScope;
+import mage.constants.Zone;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.stack.Spell;
+import mage.watchers.Watcher;
+
+/**
+ * @author TheElk801
+ */
+public final class StormwingEntity extends CardImpl {
+
+ private static final ConditionHint hint = new ConditionHint(
+ StormwingEntityCondition.instance, "You cast an instant or sorcery spell this turn"
+ );
+
+ public StormwingEntity(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
+
+ this.subtype.add(SubType.ELEMENTAL);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // This spell costs {2}{U} less to cast if you've cast an instant or sorcery spell this turn.
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(
+ new ManaCostsImpl("{2}{U}"), StormwingEntityCondition.instance
+ )).setRuleAtTheTop(true).addHint(hint), new StormwingEntityWatcher());
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Prowess
+ this.addAbility(new ProwessAbility());
+
+ // When Stormwing Entity enters the battlefield, scry 2.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(2)));
+ }
+
+ private StormwingEntity(final StormwingEntity card) {
+ super(card);
+ }
+
+ @Override
+ public StormwingEntity copy() {
+ return new StormwingEntity(this);
+ }
+}
+
+enum StormwingEntityCondition implements Condition {
+ instance;
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ StormwingEntityWatcher watcher = game.getState().getWatcher(StormwingEntityWatcher.class);
+ return watcher != null && watcher.checkPlayer(source.getControllerId());
+ }
+}
+
+class StormwingEntityWatcher extends Watcher {
+
+ private final Set playerMap = new HashSet<>();
+
+ StormwingEntityWatcher() {
+ super(WatcherScope.GAME);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() != GameEvent.EventType.SPELL_CAST) {
+ return;
+ }
+ Spell spell = game.getSpell(event.getTargetId());
+ if (spell == null || !spell.isInstantOrSorcery()) {
+ return;
+ }
+ playerMap.add(event.getPlayerId());
+ }
+
+ @Override
+ public void reset() {
+ playerMap.clear();
+ super.reset();
+ }
+
+ boolean checkPlayer(UUID playerId) {
+ return playerMap.contains(playerId);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/Stratadon.java b/Mage.Sets/src/mage/cards/s/Stratadon.java
index 3394c00fb70..ce3a704473f 100644
--- a/Mage.Sets/src/mage/cards/s/Stratadon.java
+++ b/Mage.Sets/src/mage/cards/s/Stratadon.java
@@ -32,7 +32,7 @@ public final class Stratadon extends CardImpl {
this.toughness = new MageInt(5);
// Domain - Stratadon costs {1} less to cast for each basic land type among lands you control.
- this.addAbility(new SimpleStaticAbility(Zone.STACK, new StratadonCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.ALL, new StratadonCostReductionEffect()));
// Trample
this.addAbility(TrampleAbility.getInstance());
}
diff --git a/Mage.Sets/src/mage/cards/s/StreamOfConsciousness.java b/Mage.Sets/src/mage/cards/s/StreamOfConsciousness.java
index 24ac6e0dc4d..ed7fd756ed5 100644
--- a/Mage.Sets/src/mage/cards/s/StreamOfConsciousness.java
+++ b/Mage.Sets/src/mage/cards/s/StreamOfConsciousness.java
@@ -72,7 +72,6 @@ class StreamOfConsciousnessEffect extends OneShotEffect {
Card card = game.getCard(targetId);
if (card != null) {
if (player.getGraveyard().contains(card.getId())) {
- player.getGraveyard().remove(card);
card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true);
shuffle = true;
}
diff --git a/Mage.Sets/src/mage/cards/s/StromgaldSpy.java b/Mage.Sets/src/mage/cards/s/StromgaldSpy.java
index 94ead75870c..8bb0be3207d 100644
--- a/Mage.Sets/src/mage/cards/s/StromgaldSpy.java
+++ b/Mage.Sets/src/mage/cards/s/StromgaldSpy.java
@@ -5,6 +5,8 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
+import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect;
import mage.constants.SubType;
@@ -15,6 +17,7 @@ import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
+import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@@ -32,8 +35,14 @@ public final class StromgaldSpy extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(4);
- // Whenever Stromgald Spy attacks and isn't blocked, you may have defending player play with their hand revealed for as long as Stromgald Spy remains on the battlefield. If you do, Stromgald Spy assigns no combat damage this turn.
- Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(new StromgaldSpyEffect(), true, true);
+ // Whenever Stromgald Spy attacks and isn't blocked, you may have defending player play with their hand revealed
+ // for as long as Stromgald Spy remains on the battlefield. If you do, Stromgald Spy assigns no combat damage this turn.
+ Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(
+ new ConditionalContinuousEffect(
+ new StromgaldSpyEffect(),
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD),
+ "you may have defending player play with their hand revealed for as long as {this} remains on the battlefield"),
+ true, true);
ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true));
this.addAbility(ability);
}
@@ -51,8 +60,7 @@ public final class StromgaldSpy extends CardImpl {
class StromgaldSpyEffect extends ContinuousEffectImpl {
public StromgaldSpyEffect() {
- super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Detriment);
- this.staticText = "you may have defending player play with their hand revealed for as long as Stromgald Spy remains on the battlefield";
+ super(Duration.Custom, Layer.PlayerEffects, SubLayer.NA, Outcome.Detriment);
}
public StromgaldSpyEffect(final StromgaldSpyEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/s/SuChi.java b/Mage.Sets/src/mage/cards/s/SuChi.java
index b8c58ef91c0..d59bc7e0491 100644
--- a/Mage.Sets/src/mage/cards/s/SuChi.java
+++ b/Mage.Sets/src/mage/cards/s/SuChi.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.Mana;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.mana.BasicManaEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class SuChi extends CardImpl {
this.toughness = new MageInt(4);
// When Su-Chi dies, add {C}{C}{C}{C}.
- this.addAbility(new DiesTriggeredAbility(new BasicManaEffect(Mana.ColorlessMana(4)), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new BasicManaEffect(Mana.ColorlessMana(4)), false));
}
public SuChi(final SuChi card) {
diff --git a/Mage.Sets/src/mage/cards/s/SubiraTulzidiCaravanner.java b/Mage.Sets/src/mage/cards/s/SubiraTulzidiCaravanner.java
new file mode 100644
index 00000000000..4f5d497f83d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SubiraTulzidiCaravanner.java
@@ -0,0 +1,114 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.DelayedTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.costs.common.DiscardHandCost;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect;
+import mage.abilities.keyword.HasteAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.PowerPredicate;
+import mage.filter.predicate.permanent.AnotherPredicate;
+import mage.game.Game;
+import mage.game.events.DamagedPlayerEvent;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SubiraTulzidiCaravanner extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterCreaturePermanent("another creature with power 2 or less");
+
+ static {
+ filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3));
+ filter.add(AnotherPredicate.instance);
+ }
+
+ public SubiraTulzidiCaravanner(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.SHAMAN);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Haste
+ this.addAbility(HasteAbility.getInstance());
+
+ // {1}: Another target creature with power 2 or less can't be blocked this turn.
+ Ability ability = new SimpleActivatedAbility(
+ new CantBeBlockedTargetEffect(Duration.EndOfTurn)
+ .setText("another target creature with power 2 or less can't be blocked this turn"),
+ new GenericManaCost(1)
+ );
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(ability);
+
+ // {1}{R}, {T}, Discard your hand: Until end of turn, whenever a creature you control with power 2 or less deals combat damage to a player, draw a card.
+ ability = new SimpleActivatedAbility(new CreateDelayedTriggeredAbilityEffect(
+ new SubiraTulzidiCaravannerAbility()
+ ), new ManaCostsImpl("{1}{R}"));
+ ability.addCost(new TapSourceCost());
+ ability.addCost(new DiscardHandCost());
+ this.addAbility(ability);
+ }
+
+ private SubiraTulzidiCaravanner(final SubiraTulzidiCaravanner card) {
+ super(card);
+ }
+
+ @Override
+ public SubiraTulzidiCaravanner copy() {
+ return new SubiraTulzidiCaravanner(this);
+ }
+}
+
+class SubiraTulzidiCaravannerAbility extends DelayedTriggeredAbility {
+
+ SubiraTulzidiCaravannerAbility() {
+ super(new DrawCardSourceControllerEffect(1), Duration.EndOfTurn, false, false);
+ }
+
+ private SubiraTulzidiCaravannerAbility(final SubiraTulzidiCaravannerAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public boolean checkEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event;
+ if (!dEvent.isCombatDamage()) {
+ return false;
+ }
+ Permanent permanent = game.getPermanent(event.getSourceId());
+ return permanent != null
+ && permanent.isControlledBy(getControllerId())
+ && permanent.isCreature()
+ && permanent.getPower().getValue() <= 2;
+ }
+
+ @Override
+ public SubiraTulzidiCaravannerAbility copy() {
+ return new SubiraTulzidiCaravannerAbility(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SublimeEpiphany.java b/Mage.Sets/src/mage/cards/s/SublimeEpiphany.java
new file mode 100644
index 00000000000..39c8cbbc7f0
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SublimeEpiphany.java
@@ -0,0 +1,64 @@
+package mage.cards.s;
+
+import mage.abilities.Mode;
+import mage.abilities.effects.common.CounterTargetEffect;
+import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
+import mage.abilities.effects.common.DrawCardTargetEffect;
+import mage.abilities.effects.common.ReturnToHandTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.target.TargetPlayer;
+import mage.target.TargetSpell;
+import mage.target.common.TargetActivatedOrTriggeredAbility;
+import mage.target.common.TargetControlledCreaturePermanent;
+import mage.target.common.TargetNonlandPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SublimeEpiphany extends CardImpl {
+
+ public SublimeEpiphany(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{U}{U}");
+
+ // Choose one or more —
+ this.getSpellAbility().getModes().setMinModes(1);
+ this.getSpellAbility().getModes().setMaxModes(5);
+
+ // • Counter target spell
+ this.getSpellAbility().addEffect(new CounterTargetEffect());
+ this.getSpellAbility().addTarget(new TargetSpell());
+
+ // • Counter target activated or triggered ability.
+ Mode mode = new Mode(new CounterTargetEffect());
+ mode.addTarget(new TargetActivatedOrTriggeredAbility());
+ this.getSpellAbility().addMode(mode);
+
+ // • Return target nonland permanent to its owner's hand.
+ mode = new Mode(new ReturnToHandTargetEffect());
+ mode.addTarget(new TargetNonlandPermanent());
+ this.getSpellAbility().addMode(mode);
+
+ // • Create a token that's a copy of target creature you control.
+ mode = new Mode(new CreateTokenCopyTargetEffect());
+ mode.addTarget(new TargetControlledCreaturePermanent());
+ this.getSpellAbility().addMode(mode);
+
+ // • Target player draws a card.
+ mode = new Mode(new DrawCardTargetEffect(1));
+ mode.addTarget(new TargetPlayer());
+ this.getSpellAbility().addMode(mode);
+ }
+
+ private SublimeEpiphany(final SublimeEpiphany card) {
+ super(card);
+ }
+
+ @Override
+ public SublimeEpiphany copy() {
+ return new SublimeEpiphany(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SultaiEmissary.java b/Mage.Sets/src/mage/cards/s/SultaiEmissary.java
index cb615a363b5..29c91953fd4 100644
--- a/Mage.Sets/src/mage/cards/s/SultaiEmissary.java
+++ b/Mage.Sets/src/mage/cards/s/SultaiEmissary.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.keyword.ManifestEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class SultaiEmissary extends CardImpl {
this.toughness = new MageInt(1);
// When Sultai Emissary dies, manifest the top card of your library.
- this.addAbility(new DiesTriggeredAbility(new ManifestEffect(1)));
+ this.addAbility(new DiesSourceTriggeredAbility(new ManifestEffect(1)));
}
public SultaiEmissary(final SultaiEmissary card) {
diff --git a/Mage.Sets/src/mage/cards/s/SummonersEgg.java b/Mage.Sets/src/mage/cards/s/SummonersEgg.java
index 055eb812370..d4d249ec2c0 100644
--- a/Mage.Sets/src/mage/cards/s/SummonersEgg.java
+++ b/Mage.Sets/src/mage/cards/s/SummonersEgg.java
@@ -4,7 +4,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@@ -36,7 +36,7 @@ public final class SummonersEgg extends CardImpl {
// Imprint - When Summoner's Egg enters the battlefield, you may exile a card from your hand face down.
this.addAbility(new EntersBattlefieldTriggeredAbility(new SummonersEggImprintEffect(), true, "Imprint — "));
// When Summoner's Egg dies, turn the exiled card face up. If it's a creature card, put it onto the battlefield under your control.
- this.addAbility(new DiesTriggeredAbility(new SummonersEggPutOntoBattlefieldEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new SummonersEggPutOntoBattlefieldEffect()));
}
public SummonersEgg(final SummonersEgg card) {
diff --git a/Mage.Sets/src/mage/cards/s/SunderingStroke.java b/Mage.Sets/src/mage/cards/s/SunderingStroke.java
index fb3feb97f9e..da329bc2995 100644
--- a/Mage.Sets/src/mage/cards/s/SunderingStroke.java
+++ b/Mage.Sets/src/mage/cards/s/SunderingStroke.java
@@ -32,7 +32,7 @@ public final class SunderingStroke extends CardImpl {
));
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(7, 3));
this.getSpellAbility().addHint(new StaticHint(
- "(You have to choose how 7 damage is divided even if you spend seven red mana)"
+ "(You have to choose how 7 damage is divided even if you spend seven red mana.)"
));
}
diff --git a/Mage.Sets/src/mage/cards/s/SunscapeFamiliar.java b/Mage.Sets/src/mage/cards/s/SunscapeFamiliar.java
index 420701d6d9c..dfacbc06269 100644
--- a/Mage.Sets/src/mage/cards/s/SunscapeFamiliar.java
+++ b/Mage.Sets/src/mage/cards/s/SunscapeFamiliar.java
@@ -1,7 +1,5 @@
-
package mage.cards.s;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
@@ -16,8 +14,9 @@ import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class SunscapeFamiliar extends CardImpl {
@@ -31,7 +30,7 @@ public final class SunscapeFamiliar extends CardImpl {
}
public SunscapeFamiliar(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.WALL);
this.power = new MageInt(0);
@@ -39,6 +38,7 @@ public final class SunscapeFamiliar extends CardImpl {
// Defender
this.addAbility(DefenderAbility.getInstance());
+
// Green spells and blue spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
}
diff --git a/Mage.Sets/src/mage/cards/s/SupernaturalStamina.java b/Mage.Sets/src/mage/cards/s/SupernaturalStamina.java
index 3f67103eff5..b4667f2ab7a 100644
--- a/Mage.Sets/src/mage/cards/s/SupernaturalStamina.java
+++ b/Mage.Sets/src/mage/cards/s/SupernaturalStamina.java
@@ -1,7 +1,7 @@
package mage.cards.s;
import java.util.UUID;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
@@ -26,7 +26,7 @@ public final class SupernaturalStamina extends CardImpl {
.setText("Until end of turn, target creature gets +2/+0")
);
getSpellAbility().addEffect(new GainAbilityTargetEffect(
- new DiesTriggeredAbility(
+ new DiesSourceTriggeredAbility(
new ReturnSourceFromGraveyardToBattlefieldEffect(true, true),
false),
Duration.EndOfTurn,
diff --git a/Mage.Sets/src/mage/cards/s/SupplyRunners.java b/Mage.Sets/src/mage/cards/s/SupplyRunners.java
new file mode 100644
index 00000000000..72ed35e23b3
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SupplyRunners.java
@@ -0,0 +1,50 @@
+package mage.cards.s;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.counter.AddCountersAllEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterControlledCreaturePermanent;
+import mage.filter.predicate.permanent.AnotherPredicate;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SupplyRunners extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterControlledCreaturePermanent("other creature you control");
+
+ static {
+ filter.add(AnotherPredicate.instance);
+ }
+
+ public SupplyRunners(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}");
+
+ this.subtype.add(SubType.DOG);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(2);
+
+ // When Supply Runners enters the battlefield, put a +1/+1 counter on each other creature you control.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(
+ new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter)
+ ));
+ }
+
+ private SupplyRunners(final SupplyRunners card) {
+ super(card);
+ }
+
+ @Override
+ public SupplyRunners copy() {
+ return new SupplyRunners(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SupremeVerdict.java b/Mage.Sets/src/mage/cards/s/SupremeVerdict.java
index e7249c4f7b1..7dd6932c060 100644
--- a/Mage.Sets/src/mage/cards/s/SupremeVerdict.java
+++ b/Mage.Sets/src/mage/cards/s/SupremeVerdict.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -21,7 +21,7 @@ public final class SupremeVerdict extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{W}{W}{U}");
// Supreme Verdict can't be countered.
- Ability ability = new CantBeCounteredAbility();
+ Ability ability = new CantBeCounteredSourceAbility();
ability.setRuleAtTheTop(true);
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/s/SurrakDragonclaw.java b/Mage.Sets/src/mage/cards/s/SurrakDragonclaw.java
index bb5cfb86242..8b38d589d55 100644
--- a/Mage.Sets/src/mage/cards/s/SurrakDragonclaw.java
+++ b/Mage.Sets/src/mage/cards/s/SurrakDragonclaw.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.CantBeCounteredControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
@@ -44,7 +44,7 @@ public final class SurrakDragonclaw extends CardImpl {
this.addAbility(FlashAbility.getInstance());
// Surrak Dragonclaw can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Creature spells you control can't be countered.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeCounteredControlledEffect(filterTarget, null, Duration.WhileOnBattlefield)));
diff --git a/Mage.Sets/src/mage/cards/s/SurveillingSprite.java b/Mage.Sets/src/mage/cards/s/SurveillingSprite.java
index 988c83be6f7..b27d88f50ec 100644
--- a/Mage.Sets/src/mage/cards/s/SurveillingSprite.java
+++ b/Mage.Sets/src/mage/cards/s/SurveillingSprite.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@@ -27,7 +27,7 @@ public final class SurveillingSprite extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Surveilling Sprite dies, you may draw a card.
- this.addAbility(new DiesTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
+ this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1), true));
}
public SurveillingSprite(final SurveillingSprite card) {
diff --git a/Mage.Sets/src/mage/cards/s/SwiftResponse.java b/Mage.Sets/src/mage/cards/s/SwiftResponse.java
new file mode 100644
index 00000000000..1deee7a4ba5
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/SwiftResponse.java
@@ -0,0 +1,41 @@
+package mage.cards.s;
+
+import mage.abilities.effects.common.DestroyTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.permanent.TappedPredicate;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class SwiftResponse extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterCreaturePermanent("tapped permanent");
+
+ static {
+ filter.add(TappedPredicate.instance);
+ }
+
+ public SwiftResponse(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
+
+ // Destroy target tapped creature.
+ this.getSpellAbility().addEffect(new DestroyTargetEffect());
+ this.getSpellAbility().addTarget(new TargetPermanent(filter));
+ }
+
+ private SwiftResponse(final SwiftResponse card) {
+ super(card);
+ }
+
+ @Override
+ public SwiftResponse copy() {
+ return new SwiftResponse(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/s/SwordOfBodyAndMind.java b/Mage.Sets/src/mage/cards/s/SwordOfBodyAndMind.java
index e412f9e57a6..ead24ed4389 100644
--- a/Mage.Sets/src/mage/cards/s/SwordOfBodyAndMind.java
+++ b/Mage.Sets/src/mage/cards/s/SwordOfBodyAndMind.java
@@ -100,6 +100,6 @@ class SwordOfBodyAndMindAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
- return "Whenever equipped creature deals combat damage to a player, you create a 2/2 green Wolf creature token and that player puts the top ten cards of their library into their graveyard.";
+ return "Whenever equipped creature deals combat damage to a player, you create a 2/2 green Wolf creature token and that player mills ten cards.";
}
}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/s/SylvanHierophant.java b/Mage.Sets/src/mage/cards/s/SylvanHierophant.java
index 80555a1adcf..ea72e04e610 100644
--- a/Mage.Sets/src/mage/cards/s/SylvanHierophant.java
+++ b/Mage.Sets/src/mage/cards/s/SylvanHierophant.java
@@ -2,7 +2,7 @@ package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
@@ -40,7 +40,7 @@ public final class SylvanHierophant extends CardImpl {
// When Sylvan Hierophant dies, exile Sylvan Hierophant, then return another target creature card from your graveyard to your hand.
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
- Ability ability = new DiesTriggeredAbility(new ExileSourceEffect(), false);
+ Ability ability = new DiesSourceTriggeredAbility(new ExileSourceEffect(), false);
ability.addEffect(effect);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/s/SymbioticBeast.java b/Mage.Sets/src/mage/cards/s/SymbioticBeast.java
index df9de72dce2..4f2d1b0cc00 100644
--- a/Mage.Sets/src/mage/cards/s/SymbioticBeast.java
+++ b/Mage.Sets/src/mage/cards/s/SymbioticBeast.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class SymbioticBeast extends CardImpl {
this.toughness = new MageInt(4);
// When Symbiotic Beast dies, create four 1/1 green Insect creature tokens.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new InsectToken(), 4)));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new InsectToken(), 4)));
}
public SymbioticBeast(final SymbioticBeast card) {
diff --git a/Mage.Sets/src/mage/cards/s/SymbioticElf.java b/Mage.Sets/src/mage/cards/s/SymbioticElf.java
index b2f3b8d408c..a40b1937672 100644
--- a/Mage.Sets/src/mage/cards/s/SymbioticElf.java
+++ b/Mage.Sets/src/mage/cards/s/SymbioticElf.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class SymbioticElf extends CardImpl {
this.toughness = new MageInt(2);
// When Symbiotic Elf dies, create two 1/1 green Insect creature tokens.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new InsectToken(), 2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new InsectToken(), 2)));
}
public SymbioticElf(final SymbioticElf card) {
diff --git a/Mage.Sets/src/mage/cards/s/SymbioticWurm.java b/Mage.Sets/src/mage/cards/s/SymbioticWurm.java
index 0cca8ae6d8f..45df2721dab 100644
--- a/Mage.Sets/src/mage/cards/s/SymbioticWurm.java
+++ b/Mage.Sets/src/mage/cards/s/SymbioticWurm.java
@@ -3,7 +3,7 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class SymbioticWurm extends CardImpl {
this.toughness = new MageInt(7);
// When Symbiotic Wurm dies, create seven 1/1 green Insect creature tokens.
- this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new InsectToken(), 7)));
+ this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new InsectToken(), 7)));
}
diff --git a/Mage.Sets/src/mage/cards/s/SyrElenoraTheDiscerning.java b/Mage.Sets/src/mage/cards/s/SyrElenoraTheDiscerning.java
index 0be67605193..558ccfb9096 100644
--- a/Mage.Sets/src/mage/cards/s/SyrElenoraTheDiscerning.java
+++ b/Mage.Sets/src/mage/cards/s/SyrElenoraTheDiscerning.java
@@ -1,23 +1,17 @@
package mage.cards.s;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.Mode;
-import mage.abilities.SpellAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.CardsInControllerHandCount;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.SetPowerSourceEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostModificationThatTargetSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
-import mage.game.Game;
-import mage.target.Target;
-import mage.util.CardUtil;
+import mage.filter.FilterCard;
-import java.util.Collection;
import java.util.UUID;
/**
@@ -43,7 +37,9 @@ public final class SyrElenoraTheDiscerning extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)));
// Spells your opponents cast that target Syr Elenora cost {2} more to cast.
- this.addAbility(new SimpleStaticAbility(new SyrElenoraTheDiscerningCostIncreaseEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
+ new SpellsCostModificationThatTargetSourceEffect(2, new FilterCard("Spells"), TargetController.OPPONENT))
+ );
}
private SyrElenoraTheDiscerning(final SyrElenoraTheDiscerning card) {
@@ -55,46 +51,3 @@ public final class SyrElenoraTheDiscerning extends CardImpl {
return new SyrElenoraTheDiscerning(this);
}
}
-
-class SyrElenoraTheDiscerningCostIncreaseEffect extends CostModificationEffectImpl {
-
- SyrElenoraTheDiscerningCostIncreaseEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Spells your opponents cast that target {this} cost {2} more to cast";
- }
-
- private SyrElenoraTheDiscerningCostIncreaseEffect(SyrElenoraTheDiscerningCostIncreaseEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- SpellAbility spellAbility = (SpellAbility) abilityToModify;
- CardUtil.adjustCost(spellAbility, -2);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (!(abilityToModify instanceof SpellAbility)
- || !game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
- return false;
- }
- return abilityToModify
- .getModes()
- .getSelectedModes()
- .stream()
- .map(uuid -> abilityToModify.getModes().get(uuid))
- .map(Mode::getTargets)
- .flatMap(Collection::stream)
- .map(Target::getTargets)
- .flatMap(Collection::stream)
- .anyMatch(uuid -> uuid.equals(source.getSourceId()));
- }
-
- @Override
- public SyrElenoraTheDiscerningCostIncreaseEffect copy() {
- return new SyrElenoraTheDiscerningCostIncreaseEffect(this);
- }
-
-}
diff --git a/Mage.Sets/src/mage/cards/s/SzadekLordOfSecrets.java b/Mage.Sets/src/mage/cards/s/SzadekLordOfSecrets.java
index 893008fa811..7feea17314e 100644
--- a/Mage.Sets/src/mage/cards/s/SzadekLordOfSecrets.java
+++ b/Mage.Sets/src/mage/cards/s/SzadekLordOfSecrets.java
@@ -54,7 +54,7 @@ class SzadekLordOfSecretsEffect extends ReplacementEffectImpl {
SzadekLordOfSecretsEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
- staticText = "If {this} would deal combat damage to a player, instead put that many +1/+1 counters on {this} and that player puts that many cards from the top of their library into their graveyard";
+ staticText = "If {this} would deal combat damage to a player, instead put that many +1/+1 counters on {this} and that player mills that many cards";
}
SzadekLordOfSecretsEffect(final SzadekLordOfSecretsEffect effect) {
@@ -71,7 +71,7 @@ class SzadekLordOfSecretsEffect extends ReplacementEffectImpl {
if (permanent != null) {
permanent.addCounters(CounterType.P1P1.createInstance(damageEvent.getAmount()), source, game);
if (damagedPlayer != null) {
- damagedPlayer.moveCards(damagedPlayer.getLibrary().getTopCards(game, damageEvent.getAmount()), Zone.GRAVEYARD, source, game);
+ damagedPlayer.millCards(damageEvent.getAmount(), source, game);
}
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TahngarthFirstMate.java b/Mage.Sets/src/mage/cards/t/TahngarthFirstMate.java
index 693bf559f08..a8c700033e5 100644
--- a/Mage.Sets/src/mage/cards/t/TahngarthFirstMate.java
+++ b/Mage.Sets/src/mage/cards/t/TahngarthFirstMate.java
@@ -133,7 +133,7 @@ class TahngarthFirstMateEffect extends OneShotEffect {
ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfCombat, player.getId());
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
- game.applyEffects();
+ game.getState().processAction(game);
return game.getCombat().addAttackerToCombat(permanent.getId(), target.getFirstTarget(), game);
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java
index 4aeaa230494..236ce4ff01d 100644
--- a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java
+++ b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java
@@ -150,7 +150,7 @@ class TaigamOjutaiMasterGainReboundEffect extends ContinuousEffectImpl {
}
private void addReboundAbility(Card card, Ability source, Game game) {
- boolean found = card.getAbilities(game).stream().anyMatch(ability -> ability instanceof ReboundAbility);
+ boolean found = card.getAbilities(game).containsClass(ReboundAbility.class);
if (!found) {
Ability ability = new ReboundAbility();
game.getState().addOtherAbility(card, ability);
diff --git a/Mage.Sets/src/mage/cards/t/TalruumChampion.java b/Mage.Sets/src/mage/cards/t/TalruumChampion.java
index abb97d8c057..96734c2cc17 100644
--- a/Mage.Sets/src/mage/cards/t/TalruumChampion.java
+++ b/Mage.Sets/src/mage/cards/t/TalruumChampion.java
@@ -3,7 +3,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect;
import mage.abilities.keyword.FirstStrikeAbility;
@@ -31,7 +31,7 @@ public final class TalruumChampion extends CardImpl {
// Whenever Talruum Champion blocks or becomes blocked by a creature, that creature loses first strike until end of turn.
Effect effect = new LoseAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn);
effect.setText("that creature loses first strike until end of turn");
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, false));
}
public TalruumChampion(final TalruumChampion card) {
diff --git a/Mage.Sets/src/mage/cards/t/TamiyosEpiphany.java b/Mage.Sets/src/mage/cards/t/TamiyosEpiphany.java
index bd626fa4f07..e924bb50218 100644
--- a/Mage.Sets/src/mage/cards/t/TamiyosEpiphany.java
+++ b/Mage.Sets/src/mage/cards/t/TamiyosEpiphany.java
@@ -17,8 +17,8 @@ public final class TamiyosEpiphany extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}");
// Scry 4, then draw two cards.
- this.getSpellAbility().addEffect(new ScryEffect(4).setText("scry 4,"));
- this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2).setText("then draw two cards"));
+ this.getSpellAbility().addEffect(new ScryEffect(4, false));
+ this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2).concatBy(", then"));
}
private TamiyosEpiphany(final TamiyosEpiphany card) {
diff --git a/Mage.Sets/src/mage/cards/t/TangleAsp.java b/Mage.Sets/src/mage/cards/t/TangleAsp.java
index ac1a74de788..a51b71dd67b 100644
--- a/Mage.Sets/src/mage/cards/t/TangleAsp.java
+++ b/Mage.Sets/src/mage/cards/t/TangleAsp.java
@@ -3,7 +3,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -30,7 +30,7 @@ public final class TangleAsp extends CardImpl {
// Whenever Tangle Asp blocks or becomes blocked by a creature, destroy that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true);
effect.setText("destroy that creature at end of combat");
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, false));
}
public TangleAsp(final TangleAsp card) {
diff --git a/Mage.Sets/src/mage/cards/t/Tarpan.java b/Mage.Sets/src/mage/cards/t/Tarpan.java
index 5529e42b62a..c3a83c1d78c 100644
--- a/Mage.Sets/src/mage/cards/t/Tarpan.java
+++ b/Mage.Sets/src/mage/cards/t/Tarpan.java
@@ -3,7 +3,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -24,7 +24,7 @@ public final class Tarpan extends CardImpl {
this.toughness = new MageInt(1);
// When Tarpan dies, you gain 1 life.
- this.addAbility(new DiesTriggeredAbility(new GainLifeEffect(1), false));
+ this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(1), false));
}
public Tarpan(final Tarpan card) {
diff --git a/Mage.Sets/src/mage/cards/t/TasigurTheGoldenFang.java b/Mage.Sets/src/mage/cards/t/TasigurTheGoldenFang.java
index 814b97225b1..af9604a1943 100644
--- a/Mage.Sets/src/mage/cards/t/TasigurTheGoldenFang.java
+++ b/Mage.Sets/src/mage/cards/t/TasigurTheGoldenFang.java
@@ -1,4 +1,3 @@
-
package mage.cards.t;
import mage.MageInt;
@@ -37,6 +36,7 @@ public final class TasigurTheGoldenFang extends CardImpl {
// Delve
this.addAbility(new DelveAbility());
+
// {2}{G/U}{G/U}: Put the top two cards of your library into your graveyard, then return a nonland card of an opponent's choice from your graveyard to your hand.
Ability ability = new SimpleActivatedAbility(new PutTopCardOfLibraryIntoGraveControllerEffect(2), new ManaCostsImpl("{2}{G/U}{G/U}"));
ability.addEffect(new TasigurTheGoldenFangEffect());
diff --git a/Mage.Sets/src/mage/cards/t/TatteredMummy.java b/Mage.Sets/src/mage/cards/t/TatteredMummy.java
index 92d4daecc1a..7dd0951593b 100644
--- a/Mage.Sets/src/mage/cards/t/TatteredMummy.java
+++ b/Mage.Sets/src/mage/cards/t/TatteredMummy.java
@@ -3,7 +3,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -25,7 +25,7 @@ public final class TatteredMummy extends CardImpl {
this.toughness = new MageInt(2);
// When Tattered Mummy dies, each opponent loses 2 life.
- this.addAbility(new DiesTriggeredAbility(new LoseLifeOpponentsEffect(2)));
+ this.addAbility(new DiesSourceTriggeredAbility(new LoseLifeOpponentsEffect(2)));
}
public TatteredMummy(final TatteredMummy card) {
diff --git a/Mage.Sets/src/mage/cards/t/TectonicGiant.java b/Mage.Sets/src/mage/cards/t/TectonicGiant.java
index 3f72f5440fa..b9e8d5a21f3 100644
--- a/Mage.Sets/src/mage/cards/t/TectonicGiant.java
+++ b/Mage.Sets/src/mage/cards/t/TectonicGiant.java
@@ -1,6 +1,8 @@
package mage.cards.t;
+import java.util.UUID;
import mage.MageInt;
+import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.TriggeredAbilityImpl;
@@ -10,19 +12,16 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamagePlayersEffect;
import mage.cards.*;
import mage.constants.*;
+import static mage.constants.Outcome.Benefit;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
-import mage.game.stack.StackObject;
+import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInExile;
import mage.target.targetpointer.FixedTarget;
-import java.util.UUID;
-
-import static mage.constants.Outcome.Benefit;
-
/**
* @author TheElk801
*/
@@ -75,12 +74,14 @@ class TectonicGiantTriggeredAbility extends TriggeredAbilityImpl {
case DECLARED_ATTACKERS:
return game.getCombat().getAttackers().contains(this.getSourceId());
case TARGETED:
- StackObject sourceObject = game.getStack().getStackObject(event.getSourceId());
- Player player = game.getPlayer(getControllerId());
- return sourceObject != null
- && player != null
- && player.hasOpponent(sourceObject.getControllerId(), game)
- && event.getTargetId().equals(getSourceId());
+ if (event.getTargetId().equals(getSourceId())) {
+ MageObject mageObject = game.getObject(event.getSourceId());
+ Player player = game.getPlayer(getControllerId());
+ return mageObject != null
+ && mageObject instanceof Spell
+ && player != null
+ && player.hasOpponent(((Spell) mageObject).getControllerId(), game);
+ }
}
return false;
}
@@ -100,8 +101,8 @@ class TectonicGiantEffect extends OneShotEffect {
TectonicGiantEffect() {
super(Benefit);
- staticText = "exile the top two cards of your library. Choose one of them. " +
- "Until the end of your next turn, you may play that card";
+ staticText = "exile the top two cards of your library. Choose one of them. "
+ + "Until the end of your next turn, you may play that card";
}
private TectonicGiantEffect(final TectonicGiantEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/t/TeferiMasterOfTime.java b/Mage.Sets/src/mage/cards/t/TeferiMasterOfTime.java
new file mode 100644
index 00000000000..3ba2279cb2e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TeferiMasterOfTime.java
@@ -0,0 +1,115 @@
+package mage.cards.t;
+
+import mage.abilities.Ability;
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.AsThoughEffectImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DrawDiscardControllerEffect;
+import mage.abilities.effects.common.PhaseOutTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.turn.TurnMod;
+import mage.target.TargetPermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TeferiMasterOfTime extends CardImpl {
+
+ public TeferiMasterOfTime(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{U}{U}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.TEFERI);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3));
+
+ // You may activate loyalty abilities of Teferi, Master of Time on any player's turn any time you could cast an instant.
+ this.addAbility(new SimpleStaticAbility(new TeferiMasterOfTimeActivationEffect()));
+
+ // +1: Draw a card, then discard a card.
+ this.addAbility(new LoyaltyAbility(new DrawDiscardControllerEffect(1, 1), 1));
+
+ // −3: Target creature you don't control phases out.
+ Ability ability = new LoyaltyAbility(new PhaseOutTargetEffect(), -3);
+ ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL));
+ this.addAbility(ability);
+
+ // −10: Take two extra turns after this one.
+ this.addAbility(new LoyaltyAbility(new TeferiMasterOfTimeTurnEffect(), -10));
+ }
+
+ private TeferiMasterOfTime(final TeferiMasterOfTime card) {
+ super(card);
+ }
+
+ @Override
+ public TeferiMasterOfTime copy() {
+ return new TeferiMasterOfTime(this);
+ }
+}
+
+class TeferiMasterOfTimeActivationEffect extends AsThoughEffectImpl {
+
+ TeferiMasterOfTimeActivationEffect() {
+ super(AsThoughEffectType.ACTIVATE_AS_INSTANT, Duration.EndOfGame, Outcome.Benefit);
+ staticText = "You may activate loyalty abilities of {this} " +
+ "on any player's turn any time you could cast an instant";
+ }
+
+ private TeferiMasterOfTimeActivationEffect(final TeferiMasterOfTimeActivationEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public TeferiMasterOfTimeActivationEffect copy() {
+ return new TeferiMasterOfTimeActivationEffect(this);
+ }
+
+ @Override
+ public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
+ return affectedAbility.isControlledBy(source.getControllerId())
+ && affectedAbility.getSourceId().equals(source.getSourceId())
+ && affectedAbility instanceof LoyaltyAbility;
+ }
+
+ @Override
+ public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
+ return false;
+ }
+}
+
+class TeferiMasterOfTimeTurnEffect extends OneShotEffect {
+
+ TeferiMasterOfTimeTurnEffect() {
+ super(Outcome.ExtraTurn);
+ staticText = "take two extra turns after this one";
+ }
+
+ private TeferiMasterOfTimeTurnEffect(final TeferiMasterOfTimeTurnEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public TeferiMasterOfTimeTurnEffect copy() {
+ return new TeferiMasterOfTimeTurnEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ game.getState().getTurnMods().add(new TurnMod(source.getControllerId(), false));
+ game.getState().getTurnMods().add(new TurnMod(source.getControllerId(), false));
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TeferiTimelessVoyager.java b/Mage.Sets/src/mage/cards/t/TeferiTimelessVoyager.java
new file mode 100644
index 00000000000..ec3ab59fc17
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TeferiTimelessVoyager.java
@@ -0,0 +1,140 @@
+package mage.cards.t;
+
+import mage.MageObjectReference;
+import mage.abilities.Ability;
+import mage.abilities.LoyaltyAbility;
+import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.PutOnLibraryTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.target.common.TargetCreaturePermanent;
+import mage.target.common.TargetOpponent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TeferiTimelessVoyager extends CardImpl {
+
+ public TeferiTimelessVoyager(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{U}{U}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.TEFERI);
+ this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4));
+
+ // +1: Draw a card.
+ this.addAbility(new LoyaltyAbility(new DrawCardSourceControllerEffect(1), 1));
+
+ // −3: Put target creature on top of its owner's library.
+ Ability ability = new LoyaltyAbility(new PutOnLibraryTargetEffect(true), -3);
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+
+ // −8: Each creature target opponent controls phases out. Until the end of your next turn, they can't phase in.
+ ability = new LoyaltyAbility(new TeferiTimelessVoyagerEffect(), -8);
+ ability.addTarget(new TargetOpponent());
+ this.addAbility(ability);
+ }
+
+ private TeferiTimelessVoyager(final TeferiTimelessVoyager card) {
+ super(card);
+ }
+
+ @Override
+ public TeferiTimelessVoyager copy() {
+ return new TeferiTimelessVoyager(this);
+ }
+}
+
+class TeferiTimelessVoyagerEffect extends OneShotEffect {
+
+ TeferiTimelessVoyagerEffect() {
+ super(Outcome.Benefit);
+ staticText = "each creature target opponent controls phases out. " +
+ "Until the end of your next turn, they can't phase in";
+ }
+
+ private TeferiTimelessVoyagerEffect(final TeferiTimelessVoyagerEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public TeferiTimelessVoyagerEffect copy() {
+ return new TeferiTimelessVoyagerEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ for (Permanent permanent : game
+ .getBattlefield()
+ .getAllActivePermanents(
+ StaticFilters.FILTER_PERMANENT_CREATURE, source.getFirstTarget(), game
+ )) {
+ MageObjectReference mor = new MageObjectReference(permanent, game);
+ permanent.phaseOut(game);
+ game.addEffect(new TeferiTimelessVoyagerPhaseEffect(mor), source);
+ }
+ return true;
+ }
+}
+
+class TeferiTimelessVoyagerPhaseEffect extends ContinuousRuleModifyingEffectImpl {
+
+ private int castOnTurn = 0;
+ private final MageObjectReference mor;
+
+ TeferiTimelessVoyagerPhaseEffect(MageObjectReference mor) {
+ super(Duration.Custom, Outcome.Neutral);
+ this.mor = mor;
+ }
+
+ private TeferiTimelessVoyagerPhaseEffect(final TeferiTimelessVoyagerPhaseEffect effect) {
+ super(effect);
+ this.castOnTurn = effect.castOnTurn;
+ this.mor = effect.mor;
+ }
+
+ @Override
+ public TeferiTimelessVoyagerPhaseEffect copy() {
+ return new TeferiTimelessVoyagerPhaseEffect(this);
+ }
+
+ @Override
+ public void init(Ability source, Game game) {
+ super.init(source, game);
+ castOnTurn = game.getTurnNum();
+ }
+
+ @Override
+ public boolean isInactive(Ability source, Game game) {
+ if (castOnTurn != game.getTurnNum() && game.getPhase().getStep().getType() == PhaseStep.END_TURN) {
+ return game.isActivePlayer(source.getControllerId());
+ }
+ return false;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.PHASE_IN;
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ return this.mor.refersTo(event.getTargetId(), game);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TeferisAgelessInsight.java b/Mage.Sets/src/mage/cards/t/TeferisAgelessInsight.java
new file mode 100644
index 00000000000..4f1d57dc941
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TeferisAgelessInsight.java
@@ -0,0 +1,86 @@
+package mage.cards.t;
+
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.effects.ReplacementEffectImpl;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.players.Player;
+import mage.watchers.common.CardsDrawnDuringDrawStepWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TeferisAgelessInsight extends CardImpl {
+
+ public TeferisAgelessInsight(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}");
+ this.addSuperType(SuperType.LEGENDARY);
+
+ // If you would draw a card except the first one you draw in each of your draw steps, draw two cards instead.
+ this.addAbility(new SimpleStaticAbility(new TeferisAgelessInsightEffect()), new CardsDrawnDuringDrawStepWatcher());
+ }
+
+ private TeferisAgelessInsight(final TeferisAgelessInsight card) {
+ super(card);
+ }
+
+ @Override
+ public TeferisAgelessInsight copy() {
+ return new TeferisAgelessInsight(this);
+ }
+}
+
+class TeferisAgelessInsightEffect extends ReplacementEffectImpl {
+
+ TeferisAgelessInsightEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.Neutral);
+ staticText = "If you draw a card except the first one you draw in each of your draw steps, draw two cards instead";
+ }
+
+ private TeferisAgelessInsightEffect(final TeferisAgelessInsightEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public TeferisAgelessInsightEffect copy() {
+ return new TeferisAgelessInsightEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return true;
+ }
+
+ @Override
+ public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller != null) {
+ controller.drawCards(2, event.getSourceId(), game, event.getAppliedEffects());
+ }
+ return true;
+ }
+
+ @Override
+ public boolean checksEventType(GameEvent event, Game game) {
+ return event.getType() == GameEvent.EventType.DRAW_CARD;
+ }
+
+ @Override
+ public boolean applies(GameEvent event, Ability source, Game game) {
+ if (!event.getPlayerId().equals(source.getControllerId())) {
+ return false;
+ }
+ if (!game.isActivePlayer(event.getPlayerId())
+ || game.getPhase().getStep().getType() != PhaseStep.DRAW) {
+ return true;
+ }
+ CardsDrawnDuringDrawStepWatcher watcher = game.getState().getWatcher(CardsDrawnDuringDrawStepWatcher.class);
+ return watcher != null && watcher.getAmountCardsDrawn(event.getPlayerId()) > 0;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TeferisProtege.java b/Mage.Sets/src/mage/cards/t/TeferisProtege.java
new file mode 100644
index 00000000000..cf392d9350b
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TeferisProtege.java
@@ -0,0 +1,45 @@
+package mage.cards.t;
+
+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.DrawDiscardControllerEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TeferisProtege extends CardImpl {
+
+ public TeferisProtege(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.WIZARD);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // {1}{U}, {T}: Draw a card, then discard a card.
+ Ability ability = new SimpleActivatedAbility(
+ new DrawDiscardControllerEffect(1, 1), new ManaCostsImpl("{1}{U}")
+ );
+ ability.addCost(new TapSourceCost());
+ this.addAbility(ability);
+ }
+
+ private TeferisProtege(final TeferisProtege card) {
+ super(card);
+ }
+
+ @Override
+ public TeferisProtege copy() {
+ return new TeferisProtege(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TeferisTutelage.java b/Mage.Sets/src/mage/cards/t/TeferisTutelage.java
new file mode 100644
index 00000000000..1b31489e790
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TeferisTutelage.java
@@ -0,0 +1,40 @@
+package mage.cards.t;
+
+import mage.abilities.Ability;
+import mage.abilities.common.DrawCardControllerTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.DrawDiscardControllerEffect;
+import mage.abilities.effects.common.PutLibraryIntoGraveTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.target.common.TargetOpponent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TeferisTutelage extends CardImpl {
+
+ public TeferisTutelage(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}");
+
+ // When Teferi's Tutelage enters the battlefield, draw a card, then discard a card.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawDiscardControllerEffect(1, 1)));
+
+ // Whenever you draw a card, target opponent mills two cards.
+ Ability ability = new DrawCardControllerTriggeredAbility(new PutLibraryIntoGraveTargetEffect(2), false);
+ ability.addTarget(new TargetOpponent());
+ this.addAbility(ability);
+ }
+
+ private TeferisTutelage(final TeferisTutelage card) {
+ super(card);
+ }
+
+ @Override
+ public TeferisTutelage copy() {
+ return new TeferisTutelage(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TeferisWavecaster.java b/Mage.Sets/src/mage/cards/t/TeferisWavecaster.java
new file mode 100644
index 00000000000..54725309f87
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TeferisWavecaster.java
@@ -0,0 +1,50 @@
+package mage.cards.t;
+
+import mage.MageInt;
+import mage.abilities.common.EntersBattlefieldTriggeredAbility;
+import mage.abilities.effects.common.search.SearchLibraryGraveyardPutInHandEffect;
+import mage.abilities.keyword.FlashAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.FilterCard;
+import mage.filter.predicate.mageobject.NamePredicate;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TeferisWavecaster extends CardImpl {
+
+ private static final FilterCard filter = new FilterCard("Teferi, Timeless Voyager");
+
+ static {
+ filter.add(new NamePredicate("Teferi, Timeless Voyager"));
+ }
+
+ public TeferisWavecaster(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
+
+ this.subtype.add(SubType.MERFOLK);
+ this.subtype.add(SubType.WIZARD);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Flash
+ this.addAbility(FlashAbility.getInstance());
+
+ // When Teferi's Wavecaster enters the battlefield, you may search your library and/or graveyard for a card named Teferi, Timeless Voyager, reveal it, and put it into your hand. If you search your library this way, shuffle it.
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryGraveyardPutInHandEffect(filter), true));
+ }
+
+ private TeferisWavecaster(final TeferisWavecaster card) {
+ super(card);
+ }
+
+ @Override
+ public TeferisWavecaster copy() {
+ return new TeferisWavecaster(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TeleminPerformance.java b/Mage.Sets/src/mage/cards/t/TeleminPerformance.java
index b1b7aca67ae..b01048d1733 100644
--- a/Mage.Sets/src/mage/cards/t/TeleminPerformance.java
+++ b/Mage.Sets/src/mage/cards/t/TeleminPerformance.java
@@ -77,7 +77,7 @@ class TeleminPerformanceEffect extends OneShotEffect {
opponent.revealCards(source, reveal, game);
opponent.moveCards(nonCreatures, Zone.GRAVEYARD, source, game);
if (creature != null) {
- game.applyEffects();
+ game.getState().processAction(game);
controller.moveCards(creature, Zone.BATTLEFIELD, source, game);
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TemperedVeteran.java b/Mage.Sets/src/mage/cards/t/TemperedVeteran.java
new file mode 100644
index 00000000000..d9470f439d1
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TemperedVeteran.java
@@ -0,0 +1,67 @@
+package mage.cards.t;
+
+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.counter.AddCountersTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.counters.CounterType;
+import mage.filter.FilterPermanent;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.permanent.CounterPredicate;
+import mage.target.TargetPermanent;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TemperedVeteran extends CardImpl {
+
+ private static final FilterPermanent filter
+ = new FilterCreaturePermanent("creature with a +1/+1 counter on it");
+
+ static {
+ filter.add(new CounterPredicate(CounterType.P1P1));
+ }
+
+ public TemperedVeteran(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.KNIGHT);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(2);
+
+ // {W}, {T}: Put a +1/+1 counter on target creature with a +1/+1 counter on it.
+ Ability ability = new SimpleActivatedAbility(
+ new AddCountersTargetEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl("{W}")
+ );
+ ability.addCost(new TapSourceCost());
+ ability.addTarget(new TargetPermanent(filter));
+ this.addAbility(ability);
+
+ // {4}{W}{W}, {T}: Put a +1/+1 counter on target creature.
+ ability = new SimpleActivatedAbility(
+ new AddCountersTargetEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl("{4}{W}{W}")
+ );
+ ability.addCost(new TapSourceCost());
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(ability);
+ }
+
+ private TemperedVeteran(final TemperedVeteran card) {
+ super(card);
+ }
+
+ @Override
+ public TemperedVeteran copy() {
+ return new TemperedVeteran(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TemporalAperture.java b/Mage.Sets/src/mage/cards/t/TemporalAperture.java
index 1bd65e5d275..9f6e7ae786a 100644
--- a/Mage.Sets/src/mage/cards/t/TemporalAperture.java
+++ b/Mage.Sets/src/mage/cards/t/TemporalAperture.java
@@ -1,4 +1,3 @@
-
package mage.cards.t;
import java.util.UUID;
@@ -121,11 +120,8 @@ class TemporalApertureTopCardCastEffect extends AsThoughEffectImpl {
if (controller != null
&& game.getState().getZone(objectId) == Zone.LIBRARY) {
if (controller.getLibrary().getFromTop(game).equals(card)) {
- if (objectCard == card
- && objectCard.getSpellAbility() != null
- && objectCard.getSpellAbility().spellCanBeActivatedRegularlyNow(controller.getId(), game)
- || objectCard.isLand()) {
- controller.setCastSourceIdWithAlternateMana(objectId, null, null);
+ if (objectCard == card && objectCard.getSpellAbility() != null) { // only if castable
+ allowCardToPlayWithoutMana(objectId, source, affectedControllerId, game);
return true;
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TenaciousDead.java b/Mage.Sets/src/mage/cards/t/TenaciousDead.java
index a9f9a1e0e21..54c980379d5 100644
--- a/Mage.Sets/src/mage/cards/t/TenaciousDead.java
+++ b/Mage.Sets/src/mage/cards/t/TenaciousDead.java
@@ -3,7 +3,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DoIfCostPaid;
@@ -29,7 +29,7 @@ public final class TenaciousDead extends CardImpl {
// When Tenacious Dead dies, you may pay {1}{B}. If you do, return it to the battlefield tapped under its owner's control.
Effect effect = new DoIfCostPaid(new ReturnToBattlefieldUnderOwnerControlSourceEffect(true), new ManaCostsImpl("{1}{B}"));
- this.addAbility(new DiesTriggeredAbility(effect, false));
+ this.addAbility(new DiesSourceTriggeredAbility(effect, false));
}
diff --git a/Mage.Sets/src/mage/cards/t/TentativeConnection.java b/Mage.Sets/src/mage/cards/t/TentativeConnection.java
index 48a3673c909..0683d1d77ed 100644
--- a/Mage.Sets/src/mage/cards/t/TentativeConnection.java
+++ b/Mage.Sets/src/mage/cards/t/TentativeConnection.java
@@ -2,11 +2,13 @@ package mage.cards.t;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.effects.common.UntapTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
+import mage.abilities.hint.ConditionHint;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.MenaceAbility;
import mage.cards.CardImpl;
@@ -37,13 +39,10 @@ public final class TentativeConnection extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}");
// This spell costs {3} less to cast if you control a creature with menace.
- Ability ability = new SimpleStaticAbility(
- Zone.STACK,
- new SpellCostReductionSourceEffect(
- 3, new PermanentsOnTheBattlefieldCondition(filter)
- )
- );
+ Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(3, condition));
ability.setRuleAtTheTop(true);
+ ability.addHint(new ConditionHint(condition, "You control a creature with menace"));
this.addAbility(ability);
// Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.
diff --git a/Mage.Sets/src/mage/cards/t/TenthDistrictLegionnaire.java b/Mage.Sets/src/mage/cards/t/TenthDistrictLegionnaire.java
index 3f1dd366522..b4e52204603 100644
--- a/Mage.Sets/src/mage/cards/t/TenthDistrictLegionnaire.java
+++ b/Mage.Sets/src/mage/cards/t/TenthDistrictLegionnaire.java
@@ -1,6 +1,5 @@
package mage.cards.t;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@@ -13,6 +12,8 @@ import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
+import java.util.UUID;
+
/**
* @author TheElk801
*/
@@ -33,7 +34,7 @@ public final class TenthDistrictLegionnaire extends CardImpl {
Ability ability = new HeroicAbility(new AddCountersSourceEffect(
CounterType.P1P1.createInstance()
), false, false);
- ability.addEffect(new ScryEffect(1).setText(", then scry 1"));
+ ability.addEffect(new ScryEffect(1).concatBy(", then"));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/t/Terastodon.java b/Mage.Sets/src/mage/cards/t/Terastodon.java
index 4a73c47b75d..3adf3d54bba 100644
--- a/Mage.Sets/src/mage/cards/t/Terastodon.java
+++ b/Mage.Sets/src/mage/cards/t/Terastodon.java
@@ -88,7 +88,7 @@ class TerastodonEffect extends OneShotEffect {
}
}
}
- game.applyEffects();
+ game.getState().processAction(game);
ElephantToken elephantToken = new ElephantToken();
for (Entry entry : destroyedPermanents.entrySet()) {
elephantToken.putOntoBattlefield(entry.getValue(), game, source.getSourceId(), entry.getKey());
diff --git a/Mage.Sets/src/mage/cards/t/TerrorOfThePeaks.java b/Mage.Sets/src/mage/cards/t/TerrorOfThePeaks.java
new file mode 100644
index 00000000000..93eadfdf00f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TerrorOfThePeaks.java
@@ -0,0 +1,136 @@
+package mage.cards.t;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.Mode;
+import mage.abilities.SpellAbility;
+import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.costs.common.PayLifeCost;
+import mage.abilities.effects.common.DamageTargetEffect;
+import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.game.permanent.Permanent;
+import mage.target.Target;
+import mage.target.common.TargetAnyTarget;
+
+import java.util.Collection;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TerrorOfThePeaks extends CardImpl {
+
+ public TerrorOfThePeaks(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}");
+
+ this.subtype.add(SubType.DRAGON);
+ this.power = new MageInt(5);
+ this.toughness = new MageInt(4);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Spells your opponents cast that target Terror of the Peaks cost an additional 3 life to cast.
+ this.addAbility(new SimpleStaticAbility(new TerrorOfThePeaksCostIncreaseEffect()));
+
+ // Whenever another creature enters the battlefield under your control, Terror of the Peaks deals damage equal to that creature's power to any target.
+ this.addAbility(new TerrorOfThePeaksTriggeredAbility());
+ }
+
+ private TerrorOfThePeaks(final TerrorOfThePeaks card) {
+ super(card);
+ }
+
+ @Override
+ public TerrorOfThePeaks copy() {
+ return new TerrorOfThePeaks(this);
+ }
+}
+
+class TerrorOfThePeaksCostIncreaseEffect extends CostModificationEffectImpl {
+
+ TerrorOfThePeaksCostIncreaseEffect() {
+ super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
+ staticText = "Spells your opponents cast that target {this} cost an additional 3 life to cast";
+ }
+
+ private TerrorOfThePeaksCostIncreaseEffect(TerrorOfThePeaksCostIncreaseEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source, Ability abilityToModify) {
+ SpellAbility spellAbility = (SpellAbility) abilityToModify;
+ spellAbility.addCost(new PayLifeCost(3));
+ return true;
+ }
+
+ @Override
+ public boolean applies(Ability abilityToModify, Ability source, Game game) {
+ if (!(abilityToModify instanceof SpellAbility)
+ || !game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
+ return false;
+ }
+ return abilityToModify
+ .getModes()
+ .getSelectedModes()
+ .stream()
+ .map(uuid -> abilityToModify.getModes().get(uuid))
+ .map(Mode::getTargets)
+ .flatMap(Collection::stream)
+ .map(Target::getTargets)
+ .flatMap(Collection::stream)
+ .anyMatch(uuid -> uuid.equals(source.getSourceId()));
+ }
+
+ @Override
+ public TerrorOfThePeaksCostIncreaseEffect copy() {
+ return new TerrorOfThePeaksCostIncreaseEffect(this);
+ }
+}
+
+class TerrorOfThePeaksTriggeredAbility extends EntersBattlefieldAllTriggeredAbility {
+
+ TerrorOfThePeaksTriggeredAbility() {
+ super(null, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE);
+ }
+
+ private TerrorOfThePeaksTriggeredAbility(final TerrorOfThePeaksTriggeredAbility ability) {
+ super(ability);
+ }
+
+ @Override
+ public TerrorOfThePeaksTriggeredAbility copy() {
+ return new TerrorOfThePeaksTriggeredAbility(this);
+ }
+
+ @Override
+ public boolean checkTrigger(GameEvent event, Game game) {
+ if (!super.checkTrigger(event, game)) {
+ return false;
+ }
+ Permanent permanent = game.getPermanent(event.getTargetId());
+ if (permanent == null) {
+ return false;
+ }
+ this.getEffects().clear();
+ this.getTargets().clear();
+ this.addEffect(new DamageTargetEffect(permanent.getPower().getValue()));
+ this.addTarget(new TargetAnyTarget().withChooseHint("gets " + permanent.getPower().getValue() + " damage"));
+ return true;
+ }
+
+ @Override
+ public String getRule() {
+ return "Whenever another creature enters the battlefield under your control, " +
+ "{this} deals damage equal to that creature's power to any target.";
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java b/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java
index 0e995429533..a0980c9bec9 100644
--- a/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java
+++ b/Mage.Sets/src/mage/cards/t/TestamentOfFaith.java
@@ -111,7 +111,7 @@ class TestamentOfFaithBecomesCreatureSourceEffect extends ContinuousEffectImpl i
if (sublayer == SubLayer.NA) {
if (!token.getAbilities().isEmpty()) {
for (Ability ability: token.getAbilities()) {
- permanent.addAbility(ability, source.getSourceId(), game, false);
+ permanent.addAbility(ability, source.getSourceId(), game);
}
}
}
diff --git a/Mage.Sets/src/mage/cards/t/TeysaOrzhovScion.java b/Mage.Sets/src/mage/cards/t/TeysaOrzhovScion.java
index 16a82f9d075..520f0b35a59 100644
--- a/Mage.Sets/src/mage/cards/t/TeysaOrzhovScion.java
+++ b/Mage.Sets/src/mage/cards/t/TeysaOrzhovScion.java
@@ -1,7 +1,5 @@
-
package mage.cards.t;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
@@ -12,11 +10,7 @@ import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.SuperType;
-import mage.constants.TargetController;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
@@ -25,14 +19,16 @@ import mage.game.permanent.token.SpiritWhiteToken;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author emerald000
*/
public final class TeysaOrzhovScion extends CardImpl {
-
+
private static final FilterControlledCreaturePermanent filterWhite = new FilterControlledCreaturePermanent("three white creatures");
private static final FilterCreaturePermanent filterBlack = new FilterCreaturePermanent("another black creature you control");
+
static {
filterWhite.add(new ColorPredicate(ObjectColor.WHITE));
filterBlack.add(new ColorPredicate(ObjectColor.BLACK));
@@ -41,7 +37,7 @@ public final class TeysaOrzhovScion extends CardImpl {
}
public TeysaOrzhovScion(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{B}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ADVISOR);
@@ -53,9 +49,9 @@ public final class TeysaOrzhovScion extends CardImpl {
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new SacrificeTargetCost(new TargetControlledCreaturePermanent(3, 3, filterWhite, true)));
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability);
-
+
// Whenever another black creature you control dies, create a 1/1 white Spirit creature token with flying.
- this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken("GPT")), false, filterBlack));
+ this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken()), false, filterBlack));
}
public TeysaOrzhovScion(final TeysaOrzhovScion card) {
diff --git a/Mage.Sets/src/mage/cards/t/TezzeretMasterOfMetal.java b/Mage.Sets/src/mage/cards/t/TezzeretMasterOfMetal.java
index 368382bb53a..f26c2ce66c9 100644
--- a/Mage.Sets/src/mage/cards/t/TezzeretMasterOfMetal.java
+++ b/Mage.Sets/src/mage/cards/t/TezzeretMasterOfMetal.java
@@ -1,27 +1,19 @@
-
package mage.cards.t;
-import java.util.List;
-import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
import mage.abilities.effects.common.RevealCardsFromLibraryUntilEffect;
+import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.SubType;
-import mage.constants.Duration;
-import mage.constants.Layer;
-import mage.constants.Outcome;
-import mage.constants.SubLayer;
-import mage.constants.SuperType;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterArtifactCard;
import mage.filter.common.FilterControlledArtifactPermanent;
@@ -31,8 +23,10 @@ import mage.game.permanent.Permanent;
import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
+import java.util.List;
+import java.util.UUID;
+
/**
- *
* @author Styxo
*/
public final class TezzeretMasterOfMetal extends CardImpl {
@@ -48,8 +42,10 @@ public final class TezzeretMasterOfMetal extends CardImpl {
this.addAbility(new LoyaltyAbility(new RevealCardsFromLibraryUntilEffect(new FilterArtifactCard(), Zone.HAND, Zone.LIBRARY), 1));
// -3: Target opponent loses life equal to the number of artifacts you control.
- Ability ability = new LoyaltyAbility(new LoseLifeTargetEffect(new PermanentsOnBattlefieldCount(new FilterControlledArtifactPermanent())), -3);
+ DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledArtifactPermanent());
+ Ability ability = new LoyaltyAbility(new LoseLifeTargetEffect(xValue), -3);
ability.addTarget(new TargetOpponent());
+ ability.addHint(new ValueHint("Artifacts you control", xValue));
this.addAbility(ability);
// -8: Gain control of all artifacts and creatures target opponent controls.
diff --git a/Mage.Sets/src/mage/cards/t/TezzeretsSimulacrum.java b/Mage.Sets/src/mage/cards/t/TezzeretsSimulacrum.java
index 0749fb4e452..3c9e33e2fc3 100644
--- a/Mage.Sets/src/mage/cards/t/TezzeretsSimulacrum.java
+++ b/Mage.Sets/src/mage/cards/t/TezzeretsSimulacrum.java
@@ -1,28 +1,35 @@
-
package mage.cards.t;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
+import mage.abilities.hint.ConditionHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
-import mage.filter.common.FilterPlaneswalkerPermanent;
+import mage.filter.common.FilterControlledPlaneswalkerPermanent;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class TezzeretsSimulacrum extends CardImpl {
+ private static final FilterControlledPlaneswalkerPermanent filter = new FilterControlledPlaneswalkerPermanent();
+
+ static {
+ filter.add(SubType.TEZZERET.getPredicate());
+ }
+
public TezzeretsSimulacrum(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}");
@@ -31,13 +38,13 @@ public final class TezzeretsSimulacrum extends CardImpl {
this.toughness = new MageInt(3);
// {T}: Target opponent loses 1 life. If you control a Tezzeret planeswalker, that player loses 3 life instead.
- FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent();
- filter.add(SubType.TEZZERET.getPredicate());
+ Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new ConditionalOneShotEffect(new LoseLifeTargetEffect(3), new LoseLifeTargetEffect(1),
- new PermanentsOnTheBattlefieldCondition(filter),
+ condition,
"Target opponent loses 1 life. If you control a Tezzeret planeswalker, that player loses 3 life instead"), new TapSourceCost());
ability.addTarget(new TargetOpponent());
+ ability.addHint(new ConditionHint(condition, "You control a Tezzeret planeswalker"));
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/t/ThaliaGuardianOfThraben.java b/Mage.Sets/src/mage/cards/t/ThaliaGuardianOfThraben.java
index 4176be6c9ca..985e87e5de1 100644
--- a/Mage.Sets/src/mage/cards/t/ThaliaGuardianOfThraben.java
+++ b/Mage.Sets/src/mage/cards/t/ThaliaGuardianOfThraben.java
@@ -1,26 +1,28 @@
-
package mage.cards.t;
-import java.util.UUID;
import mage.MageInt;
-import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.abilities.keyword.FirstStrikeAbility;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
-import mage.game.Game;
-import mage.util.CardUtil;
+import mage.filter.FilterCard;
+import mage.filter.predicate.Predicates;
+
+import java.util.UUID;
/**
- *
* @author BetaSteward
*/
public final class ThaliaGuardianOfThraben extends CardImpl {
+ private static final FilterCard filter = new FilterCard("Noncreature spells");
+
+ static {
+ filter.add(Predicates.not(CardType.CREATURE.getPredicate()));
+ }
+
public ThaliaGuardianOfThraben(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
addSuperType(SuperType.LEGENDARY);
@@ -33,7 +35,7 @@ public final class ThaliaGuardianOfThraben extends CardImpl {
this.addAbility(FirstStrikeAbility.getInstance());
// Noncreature spells cost {1} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ThaliaGuardianOfThrabenCostReductionEffect()));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(1, filter, TargetController.ANY)));
}
@@ -45,39 +47,4 @@ public final class ThaliaGuardianOfThraben extends CardImpl {
public ThaliaGuardianOfThraben copy() {
return new ThaliaGuardianOfThraben(this);
}
-}
-
-class ThaliaGuardianOfThrabenCostReductionEffect extends CostModificationEffectImpl {
-
- ThaliaGuardianOfThrabenCostReductionEffect() {
- super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.INCREASE_COST);
- staticText = "Noncreature spells cost {1} more to cast";
- }
-
- ThaliaGuardianOfThrabenCostReductionEffect(ThaliaGuardianOfThrabenCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- CardUtil.increaseCost(abilityToModify, 1);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- if (abilityToModify instanceof SpellAbility) {
- Card card = game.getCard(abilityToModify.getSourceId());
- if (card != null && !card.isCreature()) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public ThaliaGuardianOfThrabenCostReductionEffect copy() {
- return new ThaliaGuardianOfThrabenCostReductionEffect(this);
- }
-
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/t/ThassasOracle.java b/Mage.Sets/src/mage/cards/t/ThassasOracle.java
index a7ee33cc0e2..49fca6d9b8f 100644
--- a/Mage.Sets/src/mage/cards/t/ThassasOracle.java
+++ b/Mage.Sets/src/mage/cards/t/ThassasOracle.java
@@ -29,7 +29,10 @@ public final class ThassasOracle extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(3);
- // When Thassa's Oracle enters the battlefield, look at the top X cards of your library, where X is your devotion to blue. Put one of them on top of your library and the rest on the bottom of your library in a random order. If X is greater than or equal to the number of cards in your library, you win the game.
+ // When Thassa's Oracle enters the battlefield, look at the top X cards of your library, where X is your devotion to blue.
+ // Put up to one of them on top of your library and the rest on the bottom of your library in a random order.
+ // If X is greater than or equal to the number of cards in your library, you win the game.
+ // (Each Blue in the mana costs of permanents you control counts toward your devotion to blue.)
this.addAbility(new EntersBattlefieldTriggeredAbility(new ThassasOracleEffect())
.addHint(DevotionCount.U.getHint()));
}
diff --git a/Mage.Sets/src/mage/cards/t/TheAkroanWar.java b/Mage.Sets/src/mage/cards/t/TheAkroanWar.java
index 2a5cac325b9..19891d2612c 100644
--- a/Mage.Sets/src/mage/cards/t/TheAkroanWar.java
+++ b/Mage.Sets/src/mage/cards/t/TheAkroanWar.java
@@ -18,6 +18,7 @@ import mage.game.Game;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
+import mage.abilities.condition.common.SourceRemainsInZoneCondition;
/**
* @author TheElk801
@@ -42,8 +43,8 @@ public final class TheAkroanWar extends CardImpl {
SagaChapter.CHAPTER_I,
new ConditionalContinuousEffect(
new GainControlTargetEffect(Duration.Custom, true),
- SourceOnBattlefieldCondition.instance, "gain control of target creature " +
- "for as long as {this} remains on the battlefield"
+ new SourceRemainsInZoneCondition(Zone.BATTLEFIELD),
+ "gain control of target creature for as long as {this} remains on the battlefield"
), new TargetCreaturePermanent()
);
diff --git a/Mage.Sets/src/mage/cards/t/TheCauldronOfEternity.java b/Mage.Sets/src/mage/cards/t/TheCauldronOfEternity.java
index e4a8026e2e6..a1d627c1de4 100644
--- a/Mage.Sets/src/mage/cards/t/TheCauldronOfEternity.java
+++ b/Mage.Sets/src/mage/cards/t/TheCauldronOfEternity.java
@@ -1,25 +1,25 @@
package mage.cards.t;
-import mage.MageObject;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.common.DiesCreatureTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.effects.common.PutOnLibraryTargetEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.*;
+import mage.constants.CardType;
+import mage.constants.SuperType;
+import mage.constants.Zone;
import mage.filter.StaticFilters;
-import mage.game.Game;
-import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
-import mage.util.CardUtil;
import java.util.UUID;
@@ -34,7 +34,11 @@ public final class TheCauldronOfEternity extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
// This spell costs {2} less to cast for each creature card in your graveyard.
- this.addAbility(new SimpleStaticAbility(Zone.ALL, new TheCauldronOfEternityCostReductionEffect()));
+ DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(2, xValue));
+ ability.setRuleAtTheTop(true);
+ ability.addHint(new ValueHint("Creature card in your graveyard", xValue));
+ this.addAbility(ability);
// Whenever a creature you control dies, put it on the bottom of its owner's library.
this.addAbility(new DiesCreatureTriggeredAbility(
@@ -43,7 +47,7 @@ public final class TheCauldronOfEternity extends CardImpl {
));
// {2}{B}, {T}, Pay 2 life: Return target creature card from your graveyard to the battlefield. Activate this ability only any time you could cast a sorcery.
- Ability ability = new ActivateAsSorceryActivatedAbility(
+ ability = new ActivateAsSorceryActivatedAbility(
Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), new ManaCostsImpl("{2}{B}")
);
ability.addCost(new TapSourceCost());
@@ -61,44 +65,3 @@ public final class TheCauldronOfEternity extends CardImpl {
return new TheCauldronOfEternity(this);
}
}
-
-class TheCauldronOfEternityCostReductionEffect extends CostModificationEffectImpl {
-
- TheCauldronOfEternityCostReductionEffect() {
- super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {2} less to cast for each creature card in your graveyard";
- }
-
- private TheCauldronOfEternityCostReductionEffect(final TheCauldronOfEternityCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- Player player = game.getPlayer(source.getControllerId());
- if (player == null) {
- return false;
- }
- int reductionAmount = player
- .getGraveyard()
- .getCards(game)
- .stream()
- .filter(MageObject::isCreature)
- .mapToInt(card -> 2)
- .sum();
- CardUtil.reduceCost(abilityToModify, reductionAmount);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- return abilityToModify instanceof SpellAbility
- && abilityToModify.getSourceId().equals(source.getSourceId())
- && game.getCard(abilityToModify.getSourceId()) != null;
- }
-
- @Override
- public TheCauldronOfEternityCostReductionEffect copy() {
- return new TheCauldronOfEternityCostReductionEffect(this);
- }
-}
diff --git a/Mage.Sets/src/mage/cards/t/TheCircleOfLoyalty.java b/Mage.Sets/src/mage/cards/t/TheCircleOfLoyalty.java
index ef80797958c..6acd774073a 100644
--- a/Mage.Sets/src/mage/cards/t/TheCircleOfLoyalty.java
+++ b/Mage.Sets/src/mage/cards/t/TheCircleOfLoyalty.java
@@ -1,24 +1,23 @@
package mage.cards.t;
import mage.abilities.Ability;
-import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
-import mage.abilities.effects.common.cost.CostModificationEffectImpl;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
-import mage.filter.FilterPermanent;
import mage.filter.FilterSpell;
import mage.filter.common.FilterControlledPermanent;
-import mage.game.Game;
import mage.game.permanent.token.KnightToken;
-import mage.util.CardUtil;
import java.util.UUID;
@@ -27,10 +26,16 @@ import java.util.UUID;
*/
public final class TheCircleOfLoyalty extends CardImpl {
- private static final FilterSpell filter = new FilterSpell("a legendary spell");
+ private static final FilterSpell filterLegendary = new FilterSpell("a legendary spell");
static {
- filter.add(SuperType.LEGENDARY.getPredicate());
+ filterLegendary.add(SuperType.LEGENDARY.getPredicate());
+ }
+
+ static final FilterControlledPermanent filterKnight = new FilterControlledPermanent("Knight you control");
+
+ static {
+ filterKnight.add(SubType.KNIGHT.getPredicate());
}
public TheCircleOfLoyalty(UUID ownerId, CardSetInfo setInfo) {
@@ -39,7 +44,10 @@ public final class TheCircleOfLoyalty extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
// This spell costs {1} less to cast for each Knight you control.
- this.addAbility(new SimpleStaticAbility(Zone.ALL, new TheCircleOfLoyaltyCostReductionEffect()));
+ DynamicValue xValue = new PermanentsOnBattlefieldCount(filterKnight);
+ this.addAbility(new SimpleStaticAbility(
+ Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue)
+ ).addHint(new ValueHint("Knight you control", xValue)));
// Creatures you control get +1/+1.
this.addAbility(new SimpleStaticAbility(
@@ -48,7 +56,7 @@ public final class TheCircleOfLoyalty extends CardImpl {
// Whenever you cast a legendary spell, create a 2/2 white Knight creature token with vigilance.
this.addAbility(new SpellCastControllerTriggeredAbility(
- new CreateTokenEffect(new KnightToken()), filter, false
+ new CreateTokenEffect(new KnightToken()), filterLegendary, false
));
// {3}{W}, {T}: Create a 2/2 white Knight creature token with vigilance.
@@ -67,37 +75,4 @@ public final class TheCircleOfLoyalty extends CardImpl {
public TheCircleOfLoyalty copy() {
return new TheCircleOfLoyalty(this);
}
-}
-
-class TheCircleOfLoyaltyCostReductionEffect extends CostModificationEffectImpl {
-
- private static final FilterPermanent filter = new FilterControlledPermanent(SubType.KNIGHT);
-
- TheCircleOfLoyaltyCostReductionEffect() {
- super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.REDUCE_COST);
- staticText = "This spell costs {1} less to cast for each Knight you control";
- }
-
- private TheCircleOfLoyaltyCostReductionEffect(final TheCircleOfLoyaltyCostReductionEffect effect) {
- super(effect);
- }
-
- @Override
- public boolean apply(Game game, Ability source, Ability abilityToModify) {
- int reductionAmount = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game);
- CardUtil.reduceCost(abilityToModify, reductionAmount);
- return true;
- }
-
- @Override
- public boolean applies(Ability abilityToModify, Ability source, Game game) {
- return abilityToModify instanceof SpellAbility
- && abilityToModify.getSourceId().equals(source.getSourceId())
- && game.getCard(abilityToModify.getSourceId()) != null;
- }
-
- @Override
- public TheCircleOfLoyaltyCostReductionEffect copy() {
- return new TheCircleOfLoyaltyCostReductionEffect(this);
- }
-}
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/t/TheGitrogMonster.java b/Mage.Sets/src/mage/cards/t/TheGitrogMonster.java
index 8fc2ee9ce18..a4073f519e0 100644
--- a/Mage.Sets/src/mage/cards/t/TheGitrogMonster.java
+++ b/Mage.Sets/src/mage/cards/t/TheGitrogMonster.java
@@ -1,7 +1,5 @@
-
package mage.cards.t;
-import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
@@ -29,7 +27,7 @@ import mage.target.common.TargetControlledPermanent;
public final class TheGitrogMonster extends CardImpl {
public TheGitrogMonster(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{G}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{G}");
addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.FROG);
this.subtype.add(SubType.HORROR);
@@ -79,12 +77,10 @@ class TheGitrogMonsterTriggeredAbility extends TriggeredAbilityImpl {
ZoneChangeGroupEvent zEvent = (ZoneChangeGroupEvent) event;
if (zEvent != null && Zone.GRAVEYARD == zEvent.getToZone() && zEvent.getCards() != null) {
for (Card card : zEvent.getCards()) {
- if (card != null) {
+ if (card != null) {
UUID cardOwnerId = card.getOwnerId();
- Set cardType = card.getCardType();
if (cardOwnerId != null
&& card.isOwnedBy(getControllerId())
- && cardType != null
&& card.isLand()) {
return true;
}
diff --git a/Mage.Sets/src/mage/cards/t/TheGreatAurora.java b/Mage.Sets/src/mage/cards/t/TheGreatAurora.java
index ee5e5e07f91..063ae0af37b 100644
--- a/Mage.Sets/src/mage/cards/t/TheGreatAurora.java
+++ b/Mage.Sets/src/mage/cards/t/TheGreatAurora.java
@@ -90,7 +90,7 @@ class TheGreatAuroraEffect extends OneShotEffect {
}
}
- game.applyEffects(); // so effects from creatures that were on the battlefield won't trigger from draw or put into play
+ game.getState().processAction(game); // so effects from creatures that were on the battlefield won't trigger from draw or put into play
// Draw cards
for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
diff --git a/Mage.Sets/src/mage/cards/t/TheImmortalSun.java b/Mage.Sets/src/mage/cards/t/TheImmortalSun.java
index f2795b87c97..dd3c5078cf2 100644
--- a/Mage.Sets/src/mage/cards/t/TheImmortalSun.java
+++ b/Mage.Sets/src/mage/cards/t/TheImmortalSun.java
@@ -1,8 +1,5 @@
-
package mage.cards.t;
-import java.util.Optional;
-import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
@@ -14,19 +11,16 @@ import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
-import mage.constants.CardType;
-import mage.constants.Duration;
-import mage.constants.Outcome;
-import mage.constants.SuperType;
-import mage.constants.TargetController;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
+import java.util.Optional;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class TheImmortalSun extends CardImpl {
@@ -38,11 +32,14 @@ public final class TheImmortalSun extends CardImpl {
// Players can't activate planeswalkers' loyalty abilities.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new TheImmortalSunCantActivateEffect()));
+
// At the beginning of your draw step, draw an additional card.
this.addAbility(new BeginningOfDrawTriggeredAbility(new DrawCardSourceControllerEffect(1)
.setText("draw an additional card"), TargetController.YOU, false));
+
// Spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(new FilterCard("Spells"), 1)));
+
// Creatures you control get +1/+1.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield)));
}
diff --git a/Mage.Sets/src/mage/cards/t/TheLocustGod.java b/Mage.Sets/src/mage/cards/t/TheLocustGod.java
index 752b438e496..0e3c4852e26 100644
--- a/Mage.Sets/src/mage/cards/t/TheLocustGod.java
+++ b/Mage.Sets/src/mage/cards/t/TheLocustGod.java
@@ -5,7 +5,7 @@ import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.DrawCardControllerTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
@@ -52,7 +52,7 @@ public final class TheLocustGod extends CardImpl {
this.addAbility(ability);
// When The Locust God dies, return it to its owner's hand at the beginning of the next end step.
- this.addAbility(new DiesTriggeredAbility(new TheLocustGodEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new TheLocustGodEffect()));
}
public TheLocustGod(final TheLocustGod card) {
diff --git a/Mage.Sets/src/mage/cards/t/TheMagicMirror.java b/Mage.Sets/src/mage/cards/t/TheMagicMirror.java
index 9090a80225b..2238d81cfcf 100644
--- a/Mage.Sets/src/mage/cards/t/TheMagicMirror.java
+++ b/Mage.Sets/src/mage/cards/t/TheMagicMirror.java
@@ -4,11 +4,13 @@ import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
+import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect;
-import mage.abilities.effects.common.cost.SourceCostReductionForEachCardInGraveyardEffect;
+import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
+import mage.abilities.hint.ValueHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
@@ -30,10 +32,11 @@ public final class TheMagicMirror extends CardImpl {
this.addSuperType(SuperType.LEGENDARY);
// This spell costs {1} less to cast for each instant and sorcery card in your graveyard.
- this.addAbility(new SimpleStaticAbility(
- Zone.ALL, new SourceCostReductionForEachCardInGraveyardEffect(
- StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY
- )).setRuleAtTheTop(true));
+ DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_INSTANT_AND_SORCERY);
+ Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(1, xValue));
+ ability.setRuleAtTheTop(true);
+ ability.addHint(new ValueHint("Instant and sorcery card in your graveyard", xValue));
+ this.addAbility(ability);
// You have no maximum hand size.
this.addAbility(new SimpleStaticAbility(new MaximumHandSizeControllerEffect(
@@ -42,7 +45,7 @@ public final class TheMagicMirror extends CardImpl {
)));
// At the beginning of your upkeep, put a knowledge counter on The Magic Mirror, then draw a card for each knowledge counter on The Magic Mirror.
- Ability ability = new BeginningOfUpkeepTriggeredAbility(
+ ability = new BeginningOfUpkeepTriggeredAbility(
new AddCountersSourceEffect(CounterType.KNOWLEDGE.createInstance())
.setText("put a knowledge counter on {this},"),
TargetController.YOU, false
diff --git a/Mage.Sets/src/mage/cards/t/TheMendingOfDominaria.java b/Mage.Sets/src/mage/cards/t/TheMendingOfDominaria.java
index bfd4f42c4d4..3438e2374b0 100644
--- a/Mage.Sets/src/mage/cards/t/TheMendingOfDominaria.java
+++ b/Mage.Sets/src/mage/cards/t/TheMendingOfDominaria.java
@@ -56,7 +56,7 @@ class TheMendingOfDominariaFirstEffect extends OneShotEffect {
public TheMendingOfDominariaFirstEffect() {
super(Outcome.ReturnToHand);
- this.staticText = "Put the top two cards of your library into your graveyard, then you may return a creature card from your graveyard to your hand";
+ this.staticText = "Mill two cards, then you may return a creature card from your graveyard to your hand";
}
public TheMendingOfDominariaFirstEffect(final TheMendingOfDominariaFirstEffect effect) {
diff --git a/Mage.Sets/src/mage/cards/t/TheRoyalScions.java b/Mage.Sets/src/mage/cards/t/TheRoyalScions.java
index 83fda327c07..291bbe9b25f 100644
--- a/Mage.Sets/src/mage/cards/t/TheRoyalScions.java
+++ b/Mage.Sets/src/mage/cards/t/TheRoyalScions.java
@@ -1,9 +1,9 @@
package mage.cards.t;
import mage.abilities.Ability;
-import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.dynamicvalue.common.CardsInControllerHandCount;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
@@ -18,7 +18,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
-import mage.game.events.GameEvent;
import mage.target.common.TargetAnyTarget;
import mage.target.common.TargetCreaturePermanent;
@@ -89,41 +88,12 @@ class TheRoyalScionsCreateReflexiveTriggerEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
effect.apply(game, source);
- game.addDelayedTriggeredAbility(new TheRoyalScionsReflexiveTriggeredAbility(), source);
- game.fireEvent(GameEvent.getEvent(GameEvent.EventType.OPTION_USED, source.getOriginalId(), source.getSourceId(), source.getControllerId(), 0));
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new DamageTargetEffect(CardsInControllerHandCount.instance), false,
+ "{this} deals damage to any target equal to the number of cards in your hand"
+ );
+ ability.addTarget(new TargetAnyTarget());
+ game.fireReflexiveTriggeredAbility(ability, source);
return true;
}
}
-
-class TheRoyalScionsReflexiveTriggeredAbility extends DelayedTriggeredAbility {
-
- TheRoyalScionsReflexiveTriggeredAbility() {
- super(new DamageTargetEffect(CardsInControllerHandCount.instance), Duration.OneUse, true);
- this.addTarget(new TargetAnyTarget());
- }
-
- private TheRoyalScionsReflexiveTriggeredAbility(final TheRoyalScionsReflexiveTriggeredAbility ability) {
- super(ability);
- }
-
- @Override
- public TheRoyalScionsReflexiveTriggeredAbility copy() {
- return new TheRoyalScionsReflexiveTriggeredAbility(this);
- }
-
- @Override
- public boolean checkEventType(GameEvent event, Game game) {
- return event.getType() == GameEvent.EventType.OPTION_USED;
- }
-
- @Override
- public boolean checkTrigger(GameEvent event, Game game) {
- return event.getPlayerId().equals(this.getControllerId())
- && event.getSourceId().equals(this.getSourceId());
- }
-
- @Override
- public String getRule() {
- return "When you do, {this} deals damage to any target equal to the number of cards in your hand.";
- }
-}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/t/TheScarabGod.java b/Mage.Sets/src/mage/cards/t/TheScarabGod.java
index 7a7f4fbf4c6..e8d7e44ae05 100644
--- a/Mage.Sets/src/mage/cards/t/TheScarabGod.java
+++ b/Mage.Sets/src/mage/cards/t/TheScarabGod.java
@@ -7,7 +7,7 @@ import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -54,7 +54,7 @@ public final class TheScarabGod extends CardImpl {
this.addAbility(ability);
// When The Scarab God dies, return it to its owner's hand at the beginning of the next end step.
- this.addAbility(new DiesTriggeredAbility(new TheScarabGodEffect3()));
+ this.addAbility(new DiesSourceTriggeredAbility(new TheScarabGodEffect3()));
}
public TheScarabGod(final TheScarabGod card) {
diff --git a/Mage.Sets/src/mage/cards/t/TheScorpionGod.java b/Mage.Sets/src/mage/cards/t/TheScorpionGod.java
index b973513f0e4..b912a6d28ef 100644
--- a/Mage.Sets/src/mage/cards/t/TheScorpionGod.java
+++ b/Mage.Sets/src/mage/cards/t/TheScorpionGod.java
@@ -6,7 +6,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
@@ -63,7 +63,7 @@ public final class TheScorpionGod extends CardImpl {
this.addAbility(ability);
// When The Scorpion God dies, return it to its owner's hand at the beginning of the next end step.
- this.addAbility(new DiesTriggeredAbility(new TheScorpionGodEffect()));
+ this.addAbility(new DiesSourceTriggeredAbility(new TheScorpionGodEffect()));
}
public TheScorpionGod(final TheScorpionGod card) {
diff --git a/Mage.Sets/src/mage/cards/t/TheWretched.java b/Mage.Sets/src/mage/cards/t/TheWretched.java
index 61cf1d51ceb..e06617533fd 100644
--- a/Mage.Sets/src/mage/cards/t/TheWretched.java
+++ b/Mage.Sets/src/mage/cards/t/TheWretched.java
@@ -1,6 +1,6 @@
-
package mage.cards.t;
+import java.util.Objects;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
@@ -13,44 +13,61 @@ import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.BlockedAttackerWatcher;
+import mage.watchers.common.LostControlWatcher;
/**
*
* @author jeffwadsworth
*
-5/1/2009 The ability grants you control of all creatures that are blocking it as the ability resolves. This will include
-* any creatures that were put onto the battlefield blocking it.
-5/1/2009 Any blocking creatures that regenerated during combat will have been removed from combat. Since such creatures
-* are no longer in combat, they cannot be blocking The Wretched, which means you won't be able to gain control of them.
-5/1/2009 If The Wretched itself regenerated during combat, then it will have been removed from combat. Since it is no longer
-* in combat, there cannot be any creatures blocking it, which means you won't be able to gain control of any creatures.
-10/1/2009 The Wretched's ability triggers only if it's still on the battlefield when the end of combat step begins (after the
-* combat damage step). For example, if it's blocked by a 7/7 creature and is destroyed, its ability won't trigger at all.
-10/1/2009 If The Wretched leaves the battlefield, you no longer control it, so the duration of its control-change effect ends.
-10/1/2009 If you lose control of The Wretched before its ability resolves, you won't gain control of the creatures blocking it at all.
-10/1/2009 Once the ability resolves, it doesn't care whether the permanents you gained control of remain creatures, only that
-* they remain on the battlefield.
+ * 5/1/2009 The ability grants you control of all creatures that are blocking it
+ * as the ability resolves. This will include any creatures that were put onto
+ * the battlefield blocking it.
+ *
+ * 5/1/2009 Any blocking creatures that regenerated during combat will have been
+ * removed from combat. Since such creatures are no longer in combat, they
+ * cannot be blocking The Wretched, which means you won't be able to gain
+ * control of them.
+ *
+ * 5/1/2009 If The Wretched itself regenerated during combat, then it will have
+ * been removed from combat. Since it is no longer in combat, there cannot be
+ * any creatures blocking it, which means you won't be able to gain control of
+ * any creatures.
+ *
+ * 10/1/2009 The Wretched's ability triggers only if it's still on the
+ * battlefield when the end of combat step begins (after the combat damage
+ * step). For example, if it's blocked by a 7/7 creature and is destroyed, its
+ * ability won't trigger at all.
+ *
+ * 10/1/2009 If The Wretched leaves the battlefield, you no longer control it,
+ * so the duration of its control-change effect ends.
+ *
+ * 10/1/2009 If you lose control of The Wretched before its ability resolves,
+ * you won't gain control of the creatures blocking it at all.
+ *
+ * 10/1/2009 Once the ability resolves, it doesn't care whether the permanents
+ * you gained control of remain creatures, only that they remain on the
+ * battlefield.
*/
-
public final class TheWretched extends CardImpl {
public TheWretched(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.subtype.add(SubType.DEMON);
this.power = new MageInt(2);
this.toughness = new MageInt(5);
// At end of combat, gain control of all creatures blocking The Wretched for as long as you control The Wretched.
- this.addAbility(new EndOfCombatTriggeredAbility(new TheWretchedEffect(), false), new BlockedAttackerWatcher());
-
+ Ability ability = new EndOfCombatTriggeredAbility(new TheWretchedEffect(), false);
+ this.addAbility(ability, new BlockedAttackerWatcher());
+ ability.addWatcher(new LostControlWatcher());
}
public TheWretched(final TheWretched card) {
@@ -83,16 +100,20 @@ class TheWretchedEffect extends OneShotEffect {
if (theWretched.isRemovedFromCombat() || !theWretched.isAttacking()) {
return false;
}
- if (!new SourceOnBattlefieldControlUnchangedCondition().apply(game, source)) {
+ // Check if control of source has changed since ability triggered????? (does it work is it neccessary???)
+ Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId());
+ if (permanent != null && !Objects.equals(permanent.getControllerId(), source.getControllerId())) {
return false;
}
- for (CombatGroup combatGroup :game.getCombat().getGroups()) {
+ for (CombatGroup combatGroup : game.getCombat().getGroups()) {
if (combatGroup.getAttackers().contains(source.getSourceId())) {
- for(UUID creatureId: combatGroup.getBlockers()) {
+ for (UUID creatureId : combatGroup.getBlockers()) {
Permanent blocker = game.getPermanent(creatureId);
if (blocker != null && blocker.getBlocking() > 0) {
- ContinuousEffect effect = new ConditionalContinuousEffect(new GainControlTargetEffect(Duration.Custom, source.getControllerId()), new SourceOnBattlefieldControlUnchangedCondition(), "");
+ ContinuousEffect effect = new ConditionalContinuousEffect(
+ new GainControlTargetEffect(Duration.Custom, source.getControllerId()),
+ new SourceOnBattlefieldControlUnchangedCondition(), "");
effect.setTargetPointer(new FixedTarget(blocker.getId()));
game.addEffect(effect, source);
diff --git a/Mage.Sets/src/mage/cards/t/ThicketBasilisk.java b/Mage.Sets/src/mage/cards/t/ThicketBasilisk.java
index ceb3f948556..989d765d6ad 100644
--- a/Mage.Sets/src/mage/cards/t/ThicketBasilisk.java
+++ b/Mage.Sets/src/mage/cards/t/ThicketBasilisk.java
@@ -3,7 +3,7 @@ package mage.cards.t;
import java.util.UUID;
import mage.MageInt;
-import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility;
+import mage.abilities.common.BlocksOrBecomesBlockedSourceTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
@@ -37,7 +37,7 @@ public final class ThicketBasilisk extends CardImpl {
// Whenever Thicket Basilisk blocks or becomes blocked by a non-Wall creature, destroy that creature at end of combat.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DestroyTargetEffect()), true);
effect.setText("destroy that creature at end of combat");
- this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(effect, filter, false));
+ this.addAbility(new BlocksOrBecomesBlockedSourceTriggeredAbility(effect, filter, false));
}
public ThicketBasilisk(final ThicketBasilisk card) {
diff --git a/Mage.Sets/src/mage/cards/t/ThievesGuildEnforcer.java b/Mage.Sets/src/mage/cards/t/ThievesGuildEnforcer.java
new file mode 100644
index 00000000000..40d870a3ef4
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/ThievesGuildEnforcer.java
@@ -0,0 +1,89 @@
+package mage.cards.t;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveEachPlayerEffect;
+import mage.abilities.effects.common.continuous.BoostSourceEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.DeathtouchAbility;
+import mage.abilities.keyword.FlashAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.constants.TargetController;
+import mage.filter.FilterPermanent;
+import mage.game.Game;
+import mage.game.Graveyard;
+import mage.players.Player;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ThievesGuildEnforcer extends CardImpl {
+
+ private static final FilterPermanent filter = new FilterPermanent(SubType.ROGUE, "{this} or another Rogue");
+
+ public ThievesGuildEnforcer(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}");
+
+ this.subtype.add(SubType.HUMAN);
+ this.subtype.add(SubType.ROGUE);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(1);
+
+ // Flash
+ this.addAbility(FlashAbility.getInstance());
+
+ // Whenever Thieves' Guild Enforcer or another Rogue enters the battlefield under your control, each opponent mills two cards.
+ this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new PutTopCardOfLibraryIntoGraveEachPlayerEffect(
+ 2, TargetController.OPPONENT
+ ), filter, false, true
+ ));
+
+ // As long as an opponent has eight or more cards in their graveyard, Thieves' Guild Enforcer gets +2/+1 and has deathtouch.
+ Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
+ new BoostSourceEffect(2, 1, Duration.WhileOnBattlefield),
+ ThievesGuildEnforcerCondition.instance, "as long as an opponent " +
+ "has eight or more cards in their graveyard, {this} gets +2/+1"
+ ));
+ ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(
+ DeathtouchAbility.getInstance(), Duration.WhileOnBattlefield
+ ), ThievesGuildEnforcerCondition.instance, "and has deathtouch"));
+ this.addAbility(ability);
+ }
+
+ private ThievesGuildEnforcer(final ThievesGuildEnforcer card) {
+ super(card);
+ }
+
+ @Override
+ public ThievesGuildEnforcer copy() {
+ return new ThievesGuildEnforcer(this);
+ }
+}
+
+enum ThievesGuildEnforcerCondition implements Condition {
+ instance;
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ return game
+ .getOpponents(source.getControllerId())
+ .stream()
+ .map(game::getPlayer)
+ .filter(Objects::nonNull)
+ .map(Player::getGraveyard)
+ .mapToInt(Graveyard::size)
+ .anyMatch(i -> i >= 8);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Sets/src/mage/cards/t/ThornMammoth.java b/Mage.Sets/src/mage/cards/t/ThornMammoth.java
index 6d5a1e96271..9435c6c1ac5 100644
--- a/Mage.Sets/src/mage/cards/t/ThornMammoth.java
+++ b/Mage.Sets/src/mage/cards/t/ThornMammoth.java
@@ -2,7 +2,7 @@ package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
+import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
import mage.abilities.effects.common.FightTargetSourceEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
@@ -30,10 +30,9 @@ public final class ThornMammoth extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// Whenever Thorn Mammoth or another creature enters the battlefield under your control, Thorn Mammoth fights up to one target creature you don't control.
- Ability ability = new EntersBattlefieldControlledTriggeredAbility(
- new FightTargetSourceEffect(), StaticFilters.FILTER_PERMANENT_CREATURE,
- "Whenever {this} or another creature enters the battlefield under your control, " +
- "{this} fights up to one target creature you don't control."
+ Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility(
+ new FightTargetSourceEffect().setText("{this} fights up to one target creature you don't control"),
+ StaticFilters.FILTER_PERMANENT_CREATURE, false, true
);
ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, false));
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/t/ThornOfAmethyst.java b/Mage.Sets/src/mage/cards/t/ThornOfAmethyst.java
index 3de6135ad23..78eed2b2e1b 100644
--- a/Mage.Sets/src/mage/cards/t/ThornOfAmethyst.java
+++ b/Mage.Sets/src/mage/cards/t/ThornOfAmethyst.java
@@ -1,31 +1,33 @@
-
package mage.cards.t;
-import java.util.UUID;
import mage.abilities.common.SimpleStaticAbility;
-import mage.abilities.effects.common.cost.SpellsCostIncreasementAllEffect;
+import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
+import java.util.UUID;
+
/**
- *
* @author Plopman
*/
public final class ThornOfAmethyst extends CardImpl {
private static final FilterCard filter = new FilterCard("Noncreature spells");
+
static {
filter.add(Predicates.not(CardType.CREATURE.getPredicate()));
}
+
public ThornOfAmethyst(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// Noncreature spells cost {1} more to cast.
- this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasementAllEffect(filter, 1)));
+ this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostIncreasingAllEffect(1, filter, TargetController.ANY)));
}
public ThornOfAmethyst(final ThornOfAmethyst card) {
diff --git a/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java b/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java
index ed4faf06f7a..dae6de61490 100644
--- a/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java
+++ b/Mage.Sets/src/mage/cards/t/ThoughtCollapse.java
@@ -8,7 +8,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
-import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetSpell;
@@ -44,8 +43,7 @@ class ThoughtCollapseEffect extends OneShotEffect {
ThoughtCollapseEffect() {
super(Outcome.Benefit);
- staticText = "Counter target spell. Its controller puts " +
- "the top three cards of their library into their graveyard.";
+ staticText = "Counter target spell. Its controller mills three cards";
}
private ThoughtCollapseEffect(final ThoughtCollapseEffect effect) {
@@ -63,7 +61,7 @@ class ThoughtCollapseEffect extends OneShotEffect {
if (player == null) {
return false;
}
- player.moveCards(player.getLibrary().getTopCards(game, 3), Zone.GRAVEYARD, source, game);
+ player.millCards(3, source, game);
return effect.apply(game, source);
}
-}
\ No newline at end of file
+}
diff --git a/Mage.Sets/src/mage/cards/t/ThoughtDissector.java b/Mage.Sets/src/mage/cards/t/ThoughtDissector.java
index f8170540896..d57da0a9b60 100644
--- a/Mage.Sets/src/mage/cards/t/ThoughtDissector.java
+++ b/Mage.Sets/src/mage/cards/t/ThoughtDissector.java
@@ -90,7 +90,7 @@ class ThoughtDissectorEffect extends OneShotEffect {
}
targetOpponent.revealCards(source, reveal, game);
if (artifact != null) {
- game.applyEffects();
+ game.getState().processAction(game);
controller.moveCards(artifact, Zone.BATTLEFIELD, source, game);
Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game);
if (sourcePermanent != null) {
diff --git a/Mage.Sets/src/mage/cards/t/ThoughtDistortion.java b/Mage.Sets/src/mage/cards/t/ThoughtDistortion.java
index 743f64978c2..98ca1755d97 100644
--- a/Mage.Sets/src/mage/cards/t/ThoughtDistortion.java
+++ b/Mage.Sets/src/mage/cards/t/ThoughtDistortion.java
@@ -1,7 +1,7 @@
package mage.cards.t;
import mage.abilities.Ability;
-import mage.abilities.common.CantBeCounteredAbility;
+import mage.abilities.common.CantBeCounteredSourceAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@@ -28,7 +28,7 @@ public final class ThoughtDistortion extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{B}");
// This spell can't be countered.
- this.addAbility(new CantBeCounteredAbility());
+ this.addAbility(new CantBeCounteredSourceAbility());
// Target opponent reveals their hand. Exile all noncreature, nonland cards from that player's hand and graveyard.
this.getSpellAbility().addEffect(new ThoughtDistortionEffect());
diff --git a/Mage.Sets/src/mage/cards/t/ThoughtGorger.java b/Mage.Sets/src/mage/cards/t/ThoughtGorger.java
index 117beb14e2d..f20363f2bba 100644
--- a/Mage.Sets/src/mage/cards/t/ThoughtGorger.java
+++ b/Mage.Sets/src/mage/cards/t/ThoughtGorger.java
@@ -1,7 +1,5 @@
-
package mage.cards.t;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@@ -11,22 +9,23 @@ import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.constants.SubType;
import mage.constants.Outcome;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
+import java.util.UUID;
+
/**
- *
* @author jeffwadsworth
*/
public final class ThoughtGorger extends CardImpl {
public ThoughtGorger(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
this.subtype.add(SubType.HORROR);
this.power = new MageInt(2);
@@ -35,15 +34,13 @@ public final class ThoughtGorger extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// When Thought Gorger enters the battlefield, put a +1/+1 counter on it for each card in your hand. If you do, discard your hand.
- Ability ability1 = new EntersBattlefieldTriggeredAbility(new ThoughtGorgerEffectEnters());
- this.addAbility(ability1);
+ this.addAbility(new EntersBattlefieldTriggeredAbility(new ThoughtGorgerEffectEnters()));
// When Thought Gorger leaves the battlefield, draw a card for each +1/+1 counter on it.
- Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ThoughtGorgerEffectLeaves(), false);
- this.addAbility(ability2);
+ this.addAbility(new LeavesBattlefieldTriggeredAbility(new ThoughtGorgerEffectLeaves(), false));
}
- public ThoughtGorger(final ThoughtGorger card) {
+ private ThoughtGorger(final ThoughtGorger card) {
super(card);
}
@@ -56,12 +53,12 @@ public final class ThoughtGorger extends CardImpl {
class ThoughtGorgerEffectEnters extends OneShotEffect {
- public ThoughtGorgerEffectEnters() {
+ ThoughtGorgerEffectEnters() {
super(Outcome.Benefit);
this.staticText = "put a +1/+1 counter on it for each card in your hand. If you do, discard your hand.";
}
- public ThoughtGorgerEffectEnters(final ThoughtGorgerEffectEnters effect) {
+ private ThoughtGorgerEffectEnters(final ThoughtGorgerEffectEnters effect) {
super(effect);
}
@@ -74,24 +71,27 @@ class ThoughtGorgerEffectEnters extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent thoughtGorger = game.getPermanent(source.getSourceId());
- if (player != null && !player.getHand().isEmpty() && thoughtGorger != null ) {
- int cardsInHand = player.getHand().size();
- thoughtGorger.addCounters(CounterType.P1P1.createInstance(cardsInHand), source, game);
- player.discard(cardsInHand, false, source, game);
- return true;
+ if (player == null
+ || player.getHand().isEmpty()
+ || thoughtGorger == null
+ || !thoughtGorger.addCounters(
+ CounterType.P1P1.createInstance(player.getHand().size()), source, game
+ )) {
+ return false;
}
- return false;
+ player.discard(player.getHand(), source, game);
+ return true;
}
}
class ThoughtGorgerEffectLeaves extends OneShotEffect {
- public ThoughtGorgerEffectLeaves() {
+ ThoughtGorgerEffectLeaves() {
super(Outcome.Neutral);
this.staticText = "draw a card for each +1/+1 counter on it.";
}
- public ThoughtGorgerEffectLeaves(final ThoughtGorgerEffectLeaves effect) {
+ private ThoughtGorgerEffectLeaves(final ThoughtGorgerEffectLeaves effect) {
super(effect);
}
diff --git a/Mage.Sets/src/mage/cards/t/ThoughtHemorrhage.java b/Mage.Sets/src/mage/cards/t/ThoughtHemorrhage.java
index a4b9bee2e9d..7c10810ef06 100644
--- a/Mage.Sets/src/mage/cards/t/ThoughtHemorrhage.java
+++ b/Mage.Sets/src/mage/cards/t/ThoughtHemorrhage.java
@@ -86,7 +86,7 @@ class ThoughtHemorrhageEffect extends OneShotEffect {
+ targetPlayer.getName(), targetPlayer.getHand(), game);
int cardsFound = 0;
for (Card card : targetPlayer.getHand().getCards(game)) {
- if (CardUtil.haveSameNames(card.getName(), cardName)) {
+ if (CardUtil.haveSameNames(card, cardName, game)) {
cardsFound++;
}
}
diff --git a/Mage.Sets/src/mage/cards/t/ThoughtSponge.java b/Mage.Sets/src/mage/cards/t/ThoughtSponge.java
index 6721f81d766..da1d3a75f02 100644
--- a/Mage.Sets/src/mage/cards/t/ThoughtSponge.java
+++ b/Mage.Sets/src/mage/cards/t/ThoughtSponge.java
@@ -2,7 +2,7 @@ package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount;
@@ -45,7 +45,7 @@ public final class ThoughtSponge extends CardImpl {
), new CardsDrawnThisTurnWatcher());
// When Thought Sponge dies, draw cards equal to its power.
- this.addAbility(new DiesTriggeredAbility(
+ this.addAbility(new DiesSourceTriggeredAbility(
new DrawCardSourceControllerEffect(xValue).setText("draw cards equal to its power")
));
}
diff --git a/Mage.Sets/src/mage/cards/t/ThrabenFoulbloods.java b/Mage.Sets/src/mage/cards/t/ThrabenFoulbloods.java
index 7460f5d5a27..a2a07b22830 100644
--- a/Mage.Sets/src/mage/cards/t/ThrabenFoulbloods.java
+++ b/Mage.Sets/src/mage/cards/t/ThrabenFoulbloods.java
@@ -26,7 +26,7 @@ public final class ThrabenFoulbloods extends CardImpl {
public ThrabenFoulbloods(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.ZOMBIE);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
diff --git a/Mage.Sets/src/mage/cards/t/ThrabenPurebloods.java b/Mage.Sets/src/mage/cards/t/ThrabenPurebloods.java
index ecc9344de72..e5c7d92fb62 100644
--- a/Mage.Sets/src/mage/cards/t/ThrabenPurebloods.java
+++ b/Mage.Sets/src/mage/cards/t/ThrabenPurebloods.java
@@ -16,7 +16,7 @@ public final class ThrabenPurebloods extends CardImpl {
public ThrabenPurebloods(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{W}");
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(5);
diff --git a/Mage.Sets/src/mage/cards/t/ThranTome.java b/Mage.Sets/src/mage/cards/t/ThranTome.java
new file mode 100644
index 00000000000..d67e5bd5e7c
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/ThranTome.java
@@ -0,0 +1,113 @@
+package mage.cards.t;
+
+import mage.MageObject;
+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.OneShotEffect;
+import mage.cards.*;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+import mage.filter.FilterCard;
+import mage.game.Game;
+import mage.players.Player;
+import mage.target.Target;
+import mage.target.common.TargetCardInLibrary;
+import mage.target.common.TargetOpponent;
+
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author arcox
+ */
+public final class ThranTome extends CardImpl {
+
+ public ThranTome(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
+
+ // Reveal the top three cards of your library. Target opponent chooses one of those cards. Put that card into your graveyard, then draw two cards.
+ Ability ability = new SimpleActivatedAbility(new ThranTomeEffect(), new ManaCostsImpl("{5}"));
+ ability.addCost(new TapSourceCost());
+ this.addAbility(ability);
+ }
+
+ public ThranTome(final ThranTome card) {
+ super(card);
+ }
+
+ @Override
+ public ThranTome copy() {
+ return new ThranTome(this);
+ }
+}
+
+class ThranTomeEffect extends OneShotEffect {
+
+ public ThranTomeEffect() {
+ super(Outcome.Benefit);
+ this.staticText = "Reveal the top three cards of your library. Target opponent chooses one of those cards. Put that card into your graveyard, then draw two cards";
+ }
+
+ public ThranTomeEffect(final ThranTomeEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public ThranTomeEffect copy() {
+ return new ThranTomeEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ // validate source and controller exist
+ Player controller = game.getPlayer(source.getControllerId());
+ MageObject sourceObject = game.getObject(source.getSourceId());
+
+ if (sourceObject == null && controller == null) {
+ return false;
+ }
+
+ // target an opponent, if able
+ Player opponent;
+ Set opponents = game.getOpponents(controller.getId());
+ opponents.removeIf(opp -> !game.getPlayer(opp).canBeTargetedBy(sourceObject, source.getControllerId(), game));
+
+ if (opponents.isEmpty()) {
+ return false;
+ } else {
+ if (opponents.size() == 1) {
+ opponent = game.getPlayer(opponents.iterator().next());
+ } else {
+ Target target = new TargetOpponent();
+ controller.chooseTarget(Outcome.Detriment, target, source, game);
+ opponent = game.getPlayer(target.getFirstTarget());
+ }
+ }
+
+ // reveal the cards and choose one. put it in the graveyard
+ Card cardToGraveyard;
+ Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 3));
+ controller.revealCards(sourceObject.getIdName(), cards, game);
+
+ if (cards.size() == 1) {
+ cardToGraveyard = cards.getRandom(game);
+ } else {
+ TargetCardInLibrary target = new TargetCardInLibrary(1, new FilterCard());
+ opponent.chooseTarget(outcome, cards, target, source, game);
+ cardToGraveyard = game.getCard(target.getFirstTarget());
+ }
+
+ // put the chosen card in the graveyard
+ if (cardToGraveyard != null) {
+ controller.moveCards(cardToGraveyard, Zone.GRAVEYARD, source, game);
+ cards.remove(cardToGraveyard);
+ }
+
+ // draw 2
+ controller.drawCards(2, source.getSourceId(), game);
+ return true;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/ThrasherBrute.java b/Mage.Sets/src/mage/cards/t/ThrasherBrute.java
index e841325ff7b..640395a0e4a 100644
--- a/Mage.Sets/src/mage/cards/t/ThrasherBrute.java
+++ b/Mage.Sets/src/mage/cards/t/ThrasherBrute.java
@@ -1,24 +1,24 @@
package mage.cards.t;
-import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.LoseLifeTargetEffect;
-import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
+import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterTeamPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetOpponent;
+import java.util.UUID;
+
/**
- *
* @author TheElk801
*/
public final class ThrasherBrute extends CardImpl {
@@ -35,12 +35,9 @@ public final class ThrasherBrute extends CardImpl {
// Whenever Thrasher Brute or another Warrior enters the battlefield under your team's control, target opponent loses 1 life and you gain 1 life.
Ability ability = new EntersBattlefieldAllTriggeredAbility(
- Zone.BATTLEFIELD,
- new LoseLifeTargetEffect(1),
- filter,
- false,
+ Zone.BATTLEFIELD, new LoseLifeTargetEffect(1), filter, false,
"Whenever {this} or another Warrior enters the battlefield under your team's control, "
- + "target opponent loses 1 life and you gain 1 life."
+ + "target opponent loses 1 life and you gain 1 life."
);
ability.addEffect(new GainLifeEffect(1));
ability.addTarget(new TargetOpponent());
@@ -63,8 +60,8 @@ class ThrasherBruteFilter extends FilterTeamPermanent {
super();
}
- ThrasherBruteFilter(final ThrasherBruteFilter effect) {
- super(effect);
+ private ThrasherBruteFilter(final ThrasherBruteFilter filter) {
+ super(filter);
}
@Override
@@ -74,16 +71,8 @@ class ThrasherBruteFilter extends FilterTeamPermanent {
@Override
public boolean match(Permanent permanent, UUID sourceId, UUID playerId, Game game) {
- if (super.match(permanent, sourceId, playerId, game)) {
- if (sourceId.equals(permanent.getId())) {
- return true;
- } else {
- if (permanent.hasSubtype(SubType.WARRIOR, game)) {
- return true;
- }
- }
- }
- return false;
+ return super.match(permanent, sourceId, playerId, game)
+ && (sourceId.equals(permanent.getId())
+ || permanent.hasSubtype(SubType.WARRIOR, game));
}
-
}
diff --git a/Mage.Sets/src/mage/cards/t/ThrashingMossdog.java b/Mage.Sets/src/mage/cards/t/ThrashingMossdog.java
index d3a8501c73d..c107bab3a18 100644
--- a/Mage.Sets/src/mage/cards/t/ThrashingMossdog.java
+++ b/Mage.Sets/src/mage/cards/t/ThrashingMossdog.java
@@ -23,7 +23,7 @@ public final class ThrashingMossdog extends CardImpl {
public ThrashingMossdog (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}");
this.subtype.add(SubType.PLANT);
- this.subtype.add(SubType.HOUND);
+ this.subtype.add(SubType.DOG);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
diff --git a/Mage.Sets/src/mage/cards/t/ThrivingBluff.java b/Mage.Sets/src/mage/cards/t/ThrivingBluff.java
new file mode 100644
index 00000000000..f3f5cfec253
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/ThrivingBluff.java
@@ -0,0 +1,45 @@
+package mage.cards.t;
+
+import mage.abilities.common.AsEntersBattlefieldAbility;
+import mage.abilities.common.EntersBattlefieldTappedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.effects.common.ChooseColorEffect;
+import mage.abilities.effects.mana.AddManaChosenColorEffect;
+import mage.abilities.mana.RedManaAbility;
+import mage.abilities.mana.SimpleManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ThrivingBluff extends CardImpl {
+
+ public ThrivingBluff(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
+
+ // Thriving Bluff enters the battlefield tapped.
+ this.addAbility(new EntersBattlefieldTappedAbility());
+
+ // As Thriving Bluff enters the battlefield, choose a color other than red.
+ this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral, "Red")));
+
+ // {T}: Add {R} or one mana of the chosen color.
+ this.addAbility(new RedManaAbility());
+ this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaChosenColorEffect(), new TapSourceCost()));
+ }
+
+ private ThrivingBluff(final ThrivingBluff card) {
+ super(card);
+ }
+
+ @Override
+ public ThrivingBluff copy() {
+ return new ThrivingBluff(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/ThrivingGrove.java b/Mage.Sets/src/mage/cards/t/ThrivingGrove.java
new file mode 100644
index 00000000000..6b11f3196ef
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/ThrivingGrove.java
@@ -0,0 +1,45 @@
+package mage.cards.t;
+
+import mage.abilities.common.AsEntersBattlefieldAbility;
+import mage.abilities.common.EntersBattlefieldTappedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.effects.common.ChooseColorEffect;
+import mage.abilities.effects.mana.AddManaChosenColorEffect;
+import mage.abilities.mana.GreenManaAbility;
+import mage.abilities.mana.SimpleManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ThrivingGrove extends CardImpl {
+
+ public ThrivingGrove(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
+
+ // Thriving Grove enters the battlefield tapped.
+ this.addAbility(new EntersBattlefieldTappedAbility());
+
+ // As Thriving Grove enters the battlefield, choose a color other than green.
+ this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral, "Green")));
+
+ // {T}: Add {G} or one mana of the chosen color.
+ this.addAbility(new GreenManaAbility());
+ this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaChosenColorEffect(), new TapSourceCost()));
+ }
+
+ private ThrivingGrove(final ThrivingGrove card) {
+ super(card);
+ }
+
+ @Override
+ public ThrivingGrove copy() {
+ return new ThrivingGrove(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/ThrivingHeath.java b/Mage.Sets/src/mage/cards/t/ThrivingHeath.java
new file mode 100644
index 00000000000..1368e8cb79e
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/ThrivingHeath.java
@@ -0,0 +1,45 @@
+package mage.cards.t;
+
+import mage.abilities.common.AsEntersBattlefieldAbility;
+import mage.abilities.common.EntersBattlefieldTappedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.effects.common.ChooseColorEffect;
+import mage.abilities.effects.mana.AddManaChosenColorEffect;
+import mage.abilities.mana.SimpleManaAbility;
+import mage.abilities.mana.WhiteManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ThrivingHeath extends CardImpl {
+
+ public ThrivingHeath(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
+
+ // Thriving Heath enters the battlefield tapped.
+ this.addAbility(new EntersBattlefieldTappedAbility());
+
+ // As Thriving Heath enters the battlefield, choose a color other than white.
+ this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral, "White")));
+
+ // {T}: Add {W} or one mana of the chosen color.
+ this.addAbility(new WhiteManaAbility());
+ this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaChosenColorEffect(), new TapSourceCost()));
+ }
+
+ private ThrivingHeath(final ThrivingHeath card) {
+ super(card);
+ }
+
+ @Override
+ public ThrivingHeath copy() {
+ return new ThrivingHeath(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/ThrivingIsle.java b/Mage.Sets/src/mage/cards/t/ThrivingIsle.java
new file mode 100644
index 00000000000..c0564e8c2ad
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/ThrivingIsle.java
@@ -0,0 +1,45 @@
+package mage.cards.t;
+
+import mage.abilities.common.AsEntersBattlefieldAbility;
+import mage.abilities.common.EntersBattlefieldTappedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.effects.common.ChooseColorEffect;
+import mage.abilities.effects.mana.AddManaChosenColorEffect;
+import mage.abilities.mana.BlueManaAbility;
+import mage.abilities.mana.SimpleManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ThrivingIsle extends CardImpl {
+
+ public ThrivingIsle(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
+
+ // Thriving Isle enters the battlefield tapped.
+ this.addAbility(new EntersBattlefieldTappedAbility());
+
+ // As Thriving Isle enters the battlefield, choose a color other than blue.
+ this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral, "Blue")));
+
+ // {T}: Add {U} or one mana of the chosen color.
+ this.addAbility(new BlueManaAbility());
+ this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaChosenColorEffect(), new TapSourceCost()));
+ }
+
+ private ThrivingIsle(final ThrivingIsle card) {
+ super(card);
+ }
+
+ @Override
+ public ThrivingIsle copy() {
+ return new ThrivingIsle(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/ThrivingMoor.java b/Mage.Sets/src/mage/cards/t/ThrivingMoor.java
new file mode 100644
index 00000000000..5765c37066d
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/ThrivingMoor.java
@@ -0,0 +1,45 @@
+package mage.cards.t;
+
+import mage.abilities.common.AsEntersBattlefieldAbility;
+import mage.abilities.common.EntersBattlefieldTappedAbility;
+import mage.abilities.costs.common.TapSourceCost;
+import mage.abilities.effects.common.ChooseColorEffect;
+import mage.abilities.effects.mana.AddManaChosenColorEffect;
+import mage.abilities.mana.BlackManaAbility;
+import mage.abilities.mana.SimpleManaAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Outcome;
+import mage.constants.Zone;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class ThrivingMoor extends CardImpl {
+
+ public ThrivingMoor(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
+
+ // Thriving Moor enters the battlefield tapped.
+ this.addAbility(new EntersBattlefieldTappedAbility());
+
+ // As Thriving Moor enters the battlefield, choose a color other than black.
+ this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral, "Black")));
+
+ // {T}: Add {B} or one mana of the chosen color.
+ this.addAbility(new BlackManaAbility());
+ this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaChosenColorEffect(), new TapSourceCost()));
+ }
+
+ private ThrivingMoor(final ThrivingMoor card) {
+ super(card);
+ }
+
+ @Override
+ public ThrivingMoor copy() {
+ return new ThrivingMoor(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/ThrullChampion.java b/Mage.Sets/src/mage/cards/t/ThrullChampion.java
index e5bed4d9479..a200e4607cb 100644
--- a/Mage.Sets/src/mage/cards/t/ThrullChampion.java
+++ b/Mage.Sets/src/mage/cards/t/ThrullChampion.java
@@ -1,4 +1,3 @@
-
package mage.cards.t;
import java.util.UUID;
@@ -19,6 +18,7 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.target.TargetPermanent;
+import mage.watchers.common.LostControlWatcher;
/**
*
@@ -33,7 +33,7 @@ public final class ThrullChampion extends CardImpl {
}
public ThrullChampion(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}");
this.subtype.add(SubType.THRULL);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
@@ -47,6 +47,7 @@ public final class ThrullChampion extends CardImpl {
"Gain control of target Thrull for as long as you control {this}");
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, ThrullChampionGainControlEffect, new TapSourceCost());
ability.addTarget(new TargetPermanent(filter));
+ ability.addWatcher(new LostControlWatcher());
this.addAbility(ability);
}
diff --git a/Mage.Sets/src/mage/cards/t/ThunderscapeFamiliar.java b/Mage.Sets/src/mage/cards/t/ThunderscapeFamiliar.java
index d66b96c6d4d..3bea2e13576 100644
--- a/Mage.Sets/src/mage/cards/t/ThunderscapeFamiliar.java
+++ b/Mage.Sets/src/mage/cards/t/ThunderscapeFamiliar.java
@@ -1,7 +1,5 @@
-
package mage.cards.t;
-import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.common.SimpleStaticAbility;
@@ -16,8 +14,9 @@ import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorPredicate;
+import java.util.UUID;
+
/**
- *
* @author North
*/
public final class ThunderscapeFamiliar extends CardImpl {
@@ -31,7 +30,7 @@ public final class ThunderscapeFamiliar extends CardImpl {
}
public ThunderscapeFamiliar(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}");
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.KAVU);
this.power = new MageInt(1);
@@ -39,6 +38,7 @@ public final class ThunderscapeFamiliar extends CardImpl {
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
+
// Black spells and green spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
}
diff --git a/Mage.Sets/src/mage/cards/t/TibaltsRager.java b/Mage.Sets/src/mage/cards/t/TibaltsRager.java
index 26d32825714..8599f5a0700 100644
--- a/Mage.Sets/src/mage/cards/t/TibaltsRager.java
+++ b/Mage.Sets/src/mage/cards/t/TibaltsRager.java
@@ -2,7 +2,7 @@ package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
-import mage.abilities.common.DiesTriggeredAbility;
+import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DamageTargetEffect;
@@ -29,7 +29,7 @@ public final class TibaltsRager extends CardImpl {
this.toughness = new MageInt(2);
// When Tibalt's Rager dies, it deals 1 damage to any target.
- Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(1, "it"));
+ Ability ability = new DiesSourceTriggeredAbility(new DamageTargetEffect(1, "it"));
ability.addTarget(new TargetAnyTarget());
this.addAbility(ability);
diff --git a/Mage.Sets/src/mage/cards/t/TideSkimmer.java b/Mage.Sets/src/mage/cards/t/TideSkimmer.java
new file mode 100644
index 00000000000..c46364b2cb8
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TideSkimmer.java
@@ -0,0 +1,51 @@
+package mage.cards.t;
+
+import mage.MageInt;
+import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.filter.common.FilterCreaturePermanent;
+import mage.filter.predicate.mageobject.AbilityPredicate;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TideSkimmer extends CardImpl {
+
+ private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with flying");
+
+ static {
+ filter.add(new AbilityPredicate(FlyingAbility.class));
+ }
+
+ public TideSkimmer(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
+
+ this.subtype.add(SubType.DRAKE);
+ this.power = new MageInt(2);
+ this.toughness = new MageInt(3);
+
+ // Flying
+ this.addAbility(FlyingAbility.getInstance());
+
+ // Whenever you attack with two or more creatures with flying, draw a card.
+ this.addAbility(new AttacksWithCreaturesTriggeredAbility(
+ new DrawCardSourceControllerEffect(1), 2, filter
+ ));
+ }
+
+ private TideSkimmer(final TideSkimmer card) {
+ super(card);
+ }
+
+ @Override
+ public TideSkimmer copy() {
+ return new TideSkimmer(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TidyConclusion.java b/Mage.Sets/src/mage/cards/t/TidyConclusion.java
index 69b74d23b7f..c362070795e 100644
--- a/Mage.Sets/src/mage/cards/t/TidyConclusion.java
+++ b/Mage.Sets/src/mage/cards/t/TidyConclusion.java
@@ -1,29 +1,29 @@
-
package mage.cards.t;
-import java.util.UUID;
-import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
+import mage.abilities.dynamicvalue.common.ArtifactYouControlCount;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.GainLifeEffect;
+import mage.abilities.hint.common.ArtifactYouControlHint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
-import mage.filter.common.FilterControlledArtifactPermanent;
import mage.target.common.TargetCreaturePermanent;
+import java.util.UUID;
+
/**
- *
* @author LevelX2
*/
public final class TidyConclusion extends CardImpl {
public TidyConclusion(UUID ownerId, CardSetInfo setInfo) {
- super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{B}{B}");
+ super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}{B}");
// Destroy target creature. You gain 1 life for each artifact you control.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
- this.getSpellAbility().addEffect(new GainLifeEffect(new PermanentsOnBattlefieldCount(new FilterControlledArtifactPermanent())));
+ this.getSpellAbility().addEffect(new GainLifeEffect(ArtifactYouControlCount.instance));
+ this.getSpellAbility().addHint(ArtifactYouControlHint.instance);
}
public TidyConclusion(final TidyConclusion card) {
diff --git a/Mage.Sets/src/mage/cards/t/TinybonesTrinketThief.java b/Mage.Sets/src/mage/cards/t/TinybonesTrinketThief.java
new file mode 100644
index 00000000000..dd67bdf538f
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TinybonesTrinketThief.java
@@ -0,0 +1,128 @@
+package mage.cards.t;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
+import mage.abilities.common.SimpleActivatedAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.costs.mana.ManaCostsImpl;
+import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.DrawCardSourceControllerEffect;
+import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.game.Game;
+import mage.game.events.GameEvent;
+import mage.players.Player;
+import mage.watchers.Watcher;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TinybonesTrinketThief extends CardImpl {
+
+ public TinybonesTrinketThief(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
+
+ this.addSuperType(SuperType.LEGENDARY);
+ this.subtype.add(SubType.SKELETON);
+ this.subtype.add(SubType.ROGUE);
+ this.power = new MageInt(1);
+ this.toughness = new MageInt(2);
+
+ // At the beginning of each end step, if an opponent discarded a card this turn, you draw a card and you lose 1 life.
+ Ability ability = new ConditionalInterveningIfTriggeredAbility(
+ new BeginningOfEndStepTriggeredAbility(
+ new DrawCardSourceControllerEffect(1),
+ TargetController.EACH_PLAYER, false
+ ), TinybonesTrinketThiefCondition.instance, "At the beginning of each end step, " +
+ "if an opponent discarded a card this turn, you draw a card and you lose 1 life."
+ );
+ ability.addEffect(new LoseLifeSourceControllerEffect(1));
+ this.addAbility(ability, new TinybonesTrinketThiefWatcher());
+
+ // {4}{B}{B}: Each opponent with no cards in hand loses 10 life.
+ this.addAbility(new SimpleActivatedAbility(new TinybonesTrinketThiefEffect(), new ManaCostsImpl("{4}{B}{B}")));
+ }
+
+ private TinybonesTrinketThief(final TinybonesTrinketThief card) {
+ super(card);
+ }
+
+ @Override
+ public TinybonesTrinketThief copy() {
+ return new TinybonesTrinketThief(this);
+ }
+}
+
+enum TinybonesTrinketThiefCondition implements Condition {
+ instance;
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ TinybonesTrinketThiefWatcher watcher = game.getState().getWatcher(TinybonesTrinketThiefWatcher.class);
+ return watcher != null && watcher.checkPlayer(source.getControllerId());
+ }
+}
+
+class TinybonesTrinketThiefWatcher extends Watcher {
+
+ private final Set playerSet = new HashSet<>();
+
+ TinybonesTrinketThiefWatcher() {
+ super(WatcherScope.GAME);
+ }
+
+ @Override
+ public void watch(GameEvent event, Game game) {
+ if (event.getType() == GameEvent.EventType.DISCARDED_CARD) {
+ playerSet.addAll(game.getOpponents(event.getPlayerId()));
+ }
+ }
+
+ @Override
+ public void reset() {
+ playerSet.clear();
+ super.reset();
+ }
+
+ boolean checkPlayer(UUID playerId) {
+ return playerSet.contains(playerId);
+ }
+}
+
+class TinybonesTrinketThiefEffect extends OneShotEffect {
+
+ TinybonesTrinketThiefEffect() {
+ super(Outcome.Benefit);
+ staticText = "each opponent with no cards in hand loses 10 life";
+ }
+
+ private TinybonesTrinketThiefEffect(final TinybonesTrinketThiefEffect effect) {
+ super(effect);
+ }
+
+ @Override
+ public TinybonesTrinketThiefEffect copy() {
+ return new TinybonesTrinketThiefEffect(this);
+ }
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ for (UUID playerId : game.getOpponents(source.getControllerId())) {
+ Player player = game.getPlayer(playerId);
+ if (player != null && player.getHand().isEmpty()) {
+ player.loseLife(10, game, false);
+ }
+ }
+ return true;
+ }
+}
+// tiny bones comin out my
+// tiny bones comin out my mouth
diff --git a/Mage.Sets/src/mage/cards/t/TitanicBrawl.java b/Mage.Sets/src/mage/cards/t/TitanicBrawl.java
index 29c627c3fd6..c23972f76e6 100644
--- a/Mage.Sets/src/mage/cards/t/TitanicBrawl.java
+++ b/Mage.Sets/src/mage/cards/t/TitanicBrawl.java
@@ -38,7 +38,7 @@ public final class TitanicBrawl extends CardImpl {
// This spell costs {1} less to cast if it targets a creature you control with a +1/+1 counter on it.
this.addAbility(new SimpleStaticAbility(
- Zone.STACK, new SpellCostReductionSourceEffect(1, condition)
+ Zone.ALL, new SpellCostReductionSourceEffect(1, condition).setCanWorksOnStackOnly(true)
).setRuleAtTheTop(true));
// Target creature you control fights target creature you don't control.
diff --git a/Mage.Sets/src/mage/cards/t/TitansNest.java b/Mage.Sets/src/mage/cards/t/TitansNest.java
index 4de69fb4304..f805e124d3e 100644
--- a/Mage.Sets/src/mage/cards/t/TitansNest.java
+++ b/Mage.Sets/src/mage/cards/t/TitansNest.java
@@ -89,7 +89,10 @@ class TitansNestEffect extends OneShotEffect {
class TitansNestManaAbility extends ActivatedManaAbilityImpl {
TitansNestManaAbility() {
- super(Zone.BATTLEFIELD, (BasicManaEffect) new BasicManaEffect(new TitansNestConditionalMana()).setText("Add {C}. Spend this mana only to cast a colored spell without {X} in its mana cost."), new ExileFromGraveCost(new TargetCardInYourGraveyard()));
+ super(Zone.BATTLEFIELD, (BasicManaEffect) new BasicManaEffect(
+ new TitansNestConditionalMana())
+ .setText("Add {C}. Spend this mana only to cast a colored spell without {X} in its mana cost."),
+ new ExileFromGraveCost(new TargetCardInYourGraveyard()));
this.netMana.add(Mana.ColorlessMana(1));
}
diff --git a/Mage.Sets/src/mage/cards/t/TogetherForever.java b/Mage.Sets/src/mage/cards/t/TogetherForever.java
index ed2a9aca89c..7bb233674e1 100644
--- a/Mage.Sets/src/mage/cards/t/TogetherForever.java
+++ b/Mage.Sets/src/mage/cards/t/TogetherForever.java
@@ -40,8 +40,8 @@ public final class TogetherForever extends CardImpl {
public TogetherForever(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{W}");
- // When Together Forever enters the battlefield, support 2. (Put a +1/+1 counter on each of up to two other target creatures.)
- this.addAbility(new SupportAbility(this, 2));
+ // When Together Forever enters the battlefield, support 2. (Put a +1/+1 counter on each of up to two target creatures.)
+ this.addAbility(new SupportAbility(this, 2, false));
// {1}: Choose target creature with a counter on it. When that creature dies this turn, return that card to its owner's hand.
Ability ability = new SimpleActivatedAbility(new TogetherForeverEffect(), new GenericManaCost(1));
diff --git a/Mage.Sets/src/mage/cards/t/TolarianKraken.java b/Mage.Sets/src/mage/cards/t/TolarianKraken.java
new file mode 100644
index 00000000000..c4f5d19c42a
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TolarianKraken.java
@@ -0,0 +1,49 @@
+package mage.cards.t;
+
+import mage.MageInt;
+import mage.abilities.common.DrawCardControllerTriggeredAbility;
+import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
+import mage.abilities.costs.mana.GenericManaCost;
+import mage.abilities.effects.common.DoWhenCostPaid;
+import mage.abilities.effects.common.MayTapOrUntapTargetEffect;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.SubType;
+import mage.target.common.TargetCreaturePermanent;
+
+import java.util.UUID;
+
+/**
+ * @author TheElk801
+ */
+public final class TolarianKraken extends CardImpl {
+
+ public TolarianKraken(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
+
+ this.subtype.add(SubType.KRAKEN);
+ this.power = new MageInt(4);
+ this.toughness = new MageInt(6);
+
+ // Whenever you draw a card, you may pay {1}. When you do, you may tap or untap target creature.
+ ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
+ new MayTapOrUntapTargetEffect(), false,
+ "you may tap or untap target creature"
+ );
+ ability.addTarget(new TargetCreaturePermanent());
+ this.addAbility(new DrawCardControllerTriggeredAbility(new DoWhenCostPaid(
+ ability, new GenericManaCost(1),
+ "Pay {1} to tap or untap a creature?"
+ ), false));
+ }
+
+ private TolarianKraken(final TolarianKraken card) {
+ super(card);
+ }
+
+ @Override
+ public TolarianKraken copy() {
+ return new TolarianKraken(this);
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TomeAnima.java b/Mage.Sets/src/mage/cards/t/TomeAnima.java
new file mode 100644
index 00000000000..28a29266eab
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/t/TomeAnima.java
@@ -0,0 +1,58 @@
+package mage.cards.t;
+
+import mage.MageInt;
+import mage.abilities.Ability;
+import mage.abilities.common.SimpleStaticAbility;
+import mage.abilities.condition.Condition;
+import mage.abilities.decorator.ConditionalContinuousEffect;
+import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
+import mage.abilities.keyword.CantBeBlockedSourceAbility;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.SubType;
+import mage.game.Game;
+import mage.watchers.common.CardsDrawnThisTurnWatcher;
+
+import java.util.UUID;
+
+/**
+ * @author arcox
+ */
+public final class TomeAnima extends CardImpl {
+
+ public TomeAnima(UUID ownerId, CardSetInfo setInfo) {
+ super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
+
+ this.subtype.add(SubType.SPIRIT);
+ this.power = new MageInt(3);
+ this.toughness = new MageInt(3);
+
+ // Tome Anima can’t be blocked as long as you’ve drawn two or more cards this turn.
+ this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
+ new GainAbilitySourceEffect(new CantBeBlockedSourceAbility(), Duration.WhileOnBattlefield),
+ TomeAnimaCondition.instance,
+ "{this} can't be blocked as long as you've drawn two or more cards this turn"
+ )), new CardsDrawnThisTurnWatcher());
+ }
+
+ private TomeAnima(final TomeAnima card) {
+ super(card);
+ }
+
+ @Override
+ public TomeAnima copy() {
+ return new TomeAnima(this);
+ }
+}
+
+enum TomeAnimaCondition implements Condition {
+ instance;
+
+ @Override
+ public boolean apply(Game game, Ability source) {
+ CardsDrawnThisTurnWatcher watcher = game.getState().getWatcher(CardsDrawnThisTurnWatcher.class);
+ return watcher != null && watcher.getCardsDrawnThisTurn(source.getControllerId()) > 1;
+ }
+}
diff --git a/Mage.Sets/src/mage/cards/t/TorbranThaneOfRedFell.java b/Mage.Sets/src/mage/cards/t/TorbranThaneOfRedFell.java
index 659c6588b94..3abdd57d629 100644
--- a/Mage.Sets/src/mage/cards/t/TorbranThaneOfRedFell.java
+++ b/Mage.Sets/src/mage/cards/t/TorbranThaneOfRedFell.java
@@ -30,7 +30,8 @@ public final class TorbranThaneOfRedFell extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(4);
- // If a red source you control would deal damage to an opponent or a permanent an opponent controls, it deals that much damage plus 2 instead.
+ // If a red source you control would deal damage to an opponent or a
+ // permanent an opponent controls, it deals that much damage plus 2 instead.
this.addAbility(new SimpleStaticAbility(new TorbranThaneOfRedFellEffect()));
}
@@ -48,8 +49,8 @@ class TorbranThaneOfRedFellEffect extends ReplacementEffectImpl {
TorbranThaneOfRedFellEffect() {
super(Duration.WhileOnBattlefield, Outcome.Damage);
- this.staticText = "If a red source you control would deal damage to an opponent " +
- "or a permanent an opponent controls, it deals that much damage plus 2 instead.";
+ this.staticText = "If a red source you control would deal damage to an opponent "
+ + "or a permanent an opponent controls, it deals that much damage plus 2 instead.";
}
private TorbranThaneOfRedFellEffect(final TorbranThaneOfRedFellEffect effect) {
@@ -76,9 +77,9 @@ class TorbranThaneOfRedFellEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
- Player player = game.getPlayer(source.getControllerId());
- if (player == null
- || !player.hasOpponent(getControllerOrSelf(event.getTargetId(), game), game)
+ Player controller = game.getPlayer(source.getControllerId());
+ if (controller == null
+ || !controller.hasOpponent(getControllerOrSelf(event.getTargetId(), game), game)
|| !source.isControlledBy(game.getControllerId(event.getSourceId()))) {
return false;
}
@@ -89,8 +90,10 @@ class TorbranThaneOfRedFellEffect extends ReplacementEffectImpl {
} else {
sourceObject = sourcePermanent;
}
+
return sourceObject != null
- && sourceObject.getColor(game).isRed();
+ && sourceObject.getColor(game).isRed()
+ && event.getAmount() > 0;
}
private static UUID getControllerOrSelf(UUID id, Game game) {
diff --git a/Mage.Sets/src/mage/cards/t/Torchling.java b/Mage.Sets/src/mage/cards/t/Torchling.java
index 2de726dc712..0cae200ef72 100644
--- a/Mage.Sets/src/mage/cards/t/Torchling.java
+++ b/Mage.Sets/src/mage/cards/t/Torchling.java
@@ -1,7 +1,6 @@
package mage.cards.t;
import mage.MageInt;
-import mage.MageItem;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ColoredManaCost;
@@ -24,11 +23,8 @@ import mage.game.stack.StackObject;
import mage.target.Target;
import mage.target.TargetSpell;
import mage.target.common.TargetCreaturePermanent;
-
-import java.util.Collection;
-import java.util.Objects;
import java.util.UUID;
-import java.util.stream.Stream;
+import mage.abilities.Mode;
/**
* @author emerald000
@@ -88,20 +84,23 @@ public final class Torchling extends CardImpl {
}
enum TorchlingPredicate implements ObjectSourcePlayerPredicate> {
+
instance;
@Override
public boolean apply(ObjectSourcePlayer input, Game game) {
- Stream